Initial import: live state on api.qbirr.com (server v0.6.3)
This commit is contained in:
+236
@@ -0,0 +1,236 @@
|
||||
# Changelog
|
||||
|
||||
All notable changes to wpide-server will be documented in this file. Format
|
||||
follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); versioning
|
||||
is [SemVer](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [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`.
|
||||
Reference in New Issue
Block a user