Files

12 KiB
Raw Permalink Blame History

Changelog

All notable changes to wpide-server will be documented in this file. Format follows Keep a Changelog; versioning is SemVer.

[0.7.0] — 2026-05-26

Added

  • Marketing landing page at / (src/routes/landing.ts). Dark-theme, single-file HTML/CSS (same self-contained pattern as /app). Sections: sticky nav, hero with value-prop + CTAs to /app, model trust-strip (DeepSeek/Anthropic/OpenAI/xAI), 6-card features grid, 3-step "how it works" with an inline chat preview, final CTA, footer.
  • Quick docs page at /docs — setup steps, brain-split explainer, model-routing tiers, minimal API surface reference.
  • Brand name read from BRAND_NAME env (default WP IDE Server) so the customer-facing name can be changed without touching code.
  • No /pricing yet — deliberately deferred until tiers are finalised.

Notes

  • /app (the existing dashboard) is unchanged and reachable from the new nav. The landing nav links: Docs · Sign in · Get started.

[0.6.3] — 2026-05-26

Changed

  • Request logging back to !isDev (silent in prod). Was temporarily forced on to debug the live browser-direct tool round-trip with the plugin on Hostinger (see plugin 56.95/56.96). Now that browser-direct is verified end-to-end (744 ms tool round-trip from mersaai.diretenders.com), prod logs go quiet again — every 30s /v1/health from Docker's healthcheck no longer fills the log file.

Kept

  • The targeted diagnostic lines added in 0.6.2 stay in for future support work:
    • browser-direct: awaiting tool result from browser (orchestrator)
    • browser-direct: tool result TIMED OUT after 90s (orchestrator)
    • tool_result POST received … matched:true|false (runs route) These are low-volume and useful for diagnosing future host quirks.

[0.6.2] — 2026-05-26

Fixed

  • z.coerce.boolean() read every boolean env var as true. Boolean("false") is true in JS, so ALLOW_INSECURE_TLS=false, REQUIRE_LICENSE=false, and FREE_TIER_ACTIVE=false were all silently true. Replaced with a boolish() parser that treats 0/false/no/off as false and 1/true/yes/on as true. This bit on the first real VPS deploy: TLS verification stayed disabled and license gating would have switched on unexpectedly.

Added

  • Production deploy artifacts (deploy/). vps-bootstrap.sh (Ubuntu prep: update, ufw, base tools) and docker-compose.coolify.yml (runs the container behind Coolify's existing Traefik proxy on the external coolify network, with Let's Encrypt labels). First live deploy: Contabo VPS → Coolify/Traefik → https://api.qbirr.com.

[0.6.1] — 2026-05-26

Fixed

  • SSE stream endpoint now sends CORS headers. The /v1/runs/:id/stream reply is hijacked (raw), so the cors plugin didn't run on it. Added access-control-allow-origin (echoes request origin) so the plugin's browser-direct EventSource can open the stream cross-origin (browser on the WP site → server on another domain). Without this the browser blocked the stream.

[0.6.0] — 2026-05-25 — Memory, teams, browser-direct tools

Added

  • Server-side conversation memory (orchestrator/memory.ts). Persists each run's user goal + final answer per session_id; recalls the last ~12 turns and merges (de-duplicated) into context on the next run. Runs now have continuity even when the plugin sends little history. (DB migration v3: conversation_turns.)
  • Multi-tenant teams (accounts/teams.ts, routes/teams.ts). Orgs + members + roles; POST/GET /v1/teams, member add/remove. A member inherits the org owner's subscription tier (team owner pays once, seats share the tier) — wired into resolveAccess. (Migration v3: orgs, org_members, subscriptions.org_id.)
  • Browser-direct tool execution (cap-immune transport, server side). browser_tools: true on a run makes the loop emit tool_call SSE events and await POST /v1/runs/:id/tool_result from the browser, instead of calling back into the plugin. Removes the long-lived request from the WP host entirely → works on any shared host. Relay mode (plugin callback) remains the default; this is additive. Proven end-to-end via test (tool_call emitted → result posted → run completed using the posted data).

Notes

  • The browser-direct plugin JS (browser opens EventSource + runs the tool via admin-ajax + POSTs the result) is the remaining client-side step; the server fully supports it now.

[0.5.0] — 2026-05-25 — SaaS platform foundation

Added

  • Accounts & auth. Email+password (scrypt, no native deps), Google + GitHub OAuth (authorization-code flow), session JWT in an httpOnly cookie. /v1/auth/{register,login,logout,me,set-password} and /v1/auth/oauth/:provider/{start,callback}.
  • Licensing & subscriptions (no credits). Each account gets a license key + a subscription row (tier basic|pro|max, status). The run path resolves the license → tier and gates on an active subscription (REQUIRE_LICENSE, default off in dev so local testing needs no account; DEV_DEFAULT_TIER applies when off).
  • Model routing by tier (routing/policy.ts): tier sets the model ceiling — basic→flash, pro→+thinking, max→+pro-max — combined with mode/complexity. Explicit model picks are honored only within the tier, else downgraded. DeepSeek thinking param wired through.
  • Stripe billing (fetch, no SDK): /v1/billing/{checkout,portal,webhook} with manual webhook signature verification; subscription state mirrored into the DB. Disabled cleanly when keys absent.
  • Dashboard at /app: signup/login (email + Google + GitHub), license key with copy, plan + tier picker + manage-billing. Single inline HTML page, no build step.
  • DB migration v2: users, oauth_identities, licenses, subscriptions, sites (site registry); runs gain user_id/tier/model.
  • Deploy: SETUP.md operator checklist, docker-compose.prod.yml + Caddyfile.prod for a plain VPS (Coolify uses the Dockerfile directly). SQLite on a persistent volume for v1; Postgres is the documented scale-up path.

Notes

  • Credits/metering intentionally deferred — access is subscription-gated, tier gates models. Multi-tenant teams, server-side memory, and the browser-direct SSE transport remain as later sub-projects.

[0.4.1] — 2026-05-25

Fixed

  • Reasoning rendered one token per line in the chat. The agentic loop was emitting a thinking event per reasoning token; the plugin relays each as a thought event, and the browser appends one list item per thought — so each reasoning token landed on its own line. Now the loop accumulates reasoning_content per step and emits a single thinking event when the step's LLM call finishes (matches the local orchestrator's one-thought-per-step model). Content tokens still stream individually into the live bubble.

[0.4.0] — 2026-05-25

Added

  • SSE token streaming. GET /v1/runs/:run_id/stream streams a run's live events (token, thinking, tool_call, tool_result, status, done, error, end) with ?since=<seq> resume. Backed by a per-run event buffer in the registry (addEvent).
  • OpenAIClient.chatStream() — streaming chat completions over fetch: parses SSE token deltas, accumulates content / reasoning_content / tool_calls, returns the same shape as chat(). Connect-only retry (safe to retry before any token; never mid-stream).
  • The agentic loop now uses chatStream and emits token/tool events into the run's buffer as they happen.

Fixed

  • DeepSeek v4 thinking mode HTTP 400 — the loop now echoes the assistant message's reasoning_content back on the next turn after a tool call, as DeepSeek v4 requires. (chat() and chatStream() both capture the field; the loop re-sends it.)

[0.3.0] — 2026-05-25

Added

  • Async run model — removes the synchronous timeout ceiling.
    • POST /v1/runs/start registers a run, kicks off the orchestrator in the background, and returns { run_id, session_id } immediately.
    • GET /v1/runs/:run_id/status reports live progress (status, steps_done, tools_used, elapsed_ms, partial_content) and the full PHP-shape response once finished.
    • In-memory run registry (src/orchestrator/registry.ts) with a 30-min TTL for finished runs. process_request shares its step/tool arrays with the registry so status reflects progress as it happens.
    • Old synchronous POST /v1/runs retained for non-browser callers.
  • Built-in server-side wait tool — lets agents pace long-running diagnostics without a DB SLEEP() (SQLite has none). Handled in-loop, never calls back to the plugin. Max 30s per call.
  • LLM chat retry hardened: 6 attempts, 20s per-attempt timeout (fails fast on a hung VPN connection and retries), abort/timeout treated as retryable. Step cap raised 25 → 40.
  • AGENT_STEP tool_call → <name> logged at info level for live flow visibility.

[0.2.1] — 2026-05-25

Added

  • xAI (Grok) provider client — OpenAI-compatible base URL https://api.x.ai/v1.
  • DeepSeek provider client — base URL https://api.deepseek.com/v1.
  • Provider auto-routing in pickProvider(): explicit override → model-name prefix (deepseek*, grok*, gpt-*) → first configured key (deepseek → xai → openai). defaultModelFor() picks a sane model per provider.
  • ALLOW_INSECURE_TLS (default on in dev) — skips outbound TLS verification for machines behind a VPN/MITM whose root CA Node doesn't trust. Set off in prod.
  • Tool-manifest sanitizer (src/tools/manifest.ts) — coerces PHP's empty [] to {} where objects are required and strips null values, so strict validators (DeepSeek) stop rejecting the plugin's 95 tool schemas with HTTP 400.
  • LLM chat calls now retry up to 3× with backoff on network errors (connect timeout, DNS, TLS) and 5xx/429 — rides through flaky-VPN blips. 4xx are treated as real errors and not retried.
  • Detailed logging on tool-exec callback failures (URL, status, headers, body length) to diagnose cross-machine / rewrite issues.

Changed

  • Server binds to 0.0.0.0 by default (was 127.0.0.1) so other LAN machines can reach it. Default port 3017.
  • Default model is now deepseek-chat.

[0.2.0] — 2026-05-21

Added

  • GET / root route returns an API directory (name, version, endpoint hints) — friendlier than the previous 404 when poking around in a browser.
  • POST /v1/runs — main orchestrator entrypoint. Accepts { goal, context, options, tools_manifest, callback_url, callback_secret, license_key, site_url } and returns the exact response shape PHP's wp_ide_process_agentic() uses: { success, content, tool_results, execution: { run_id, session_id, mode, steps, status_messages, ... }, approval_payload }.
  • GET /v1/runs/:run_id — fetch a stored run record.
  • Greeting + simple paths fully working. Greetings need no LLM call; simple invokes OpenAI chat/completions (default gpt-4o-mini). Agentic path is a placeholder that returns a "step 5" message.
  • Orchestrator router (src/orchestrator/router.ts) — port of WP_IDE_AI_Router::classify; cheap regex/keyword heuristics that pick greeting / simple / agentic without an LLM call.
  • OpenAI client over fetch (src/providers/openai.ts) — no SDK dependency. Provider router (src/providers/index.ts) dispatches by model name; Anthropic / xAI plug in here in later steps.
  • Runs table CRUD (src/db/runs.ts) — persists every run with status transitions so a future status endpoint can answer "what happened".

Notes

  • OPENAI_API_KEY is read from .env on boot. Without it the simple path returns a clear actionable error in the standard response shape; the greeting path still works because it doesn't call any LLM.

[0.1.0] — 2026-05-21

Added

  • Initial Fastify scaffold (Node 20, TypeScript, ESM).
  • GET /v1/health returns name, version, uptime, Node version, timestamp.
  • SQLite via better-sqlite3 as the dev database; WAL mode + foreign keys enabled. Postgres URL recognised for later Coolify deploy but not yet wired.
  • Initial schema: schema_version, runs tables (more added per milestone).
  • Zod-validated env loader, pino logger, CORS, graceful shutdown.
  • start-dev.bat for one-command Windows dev startup.
  • Dockerfile for future Coolify deployment (not used locally).
  • Optional Caddyfile for local TLS via wpide.local.