`/models` now returns only deepseek-v4-pro and deepseek-v4-flash;
deepseek-chat / deepseek-reasoner sunset 2026-07-24 and the
deepseek-v3.2 hard-coded in the ark-coding fallback list never
existed. Both v4 models default to thinking enabled and the API
toggles via `{"thinking":{"type":"disabled"}}` — keep
`thinkingMode: 'disabled'` so the app's fast/non-thinking default
stays intact (server reasoning paths honor it; the Zig openai-compat
path doesn't emit the toggle yet, so calls through that path still
get provider-default thinking until it's wired). v4-pro promoted to
full tier; legacy aliases pinned to an exact RegExp so future
deepseek-* variants don't inherit a forced disabled mode.
Bandaid for the unwired toggle: v4-pro gets `timeoutMultiplier: 2`
because its default-on reasoning blows past the orchestrator's
planning timeout on long system prompts (observed in dev: planning
phase falls back, sub-agent then succeeds — UX degraded but
functional). Drop the multiplier once the Zig path actually sends
`thinking:{type:disabled}`.
Don't add a BUILTIN_MODEL_LISTS.deepseek entry — DeepSeek exposes
/v1/models, so let `fetchProviderModels` pull the live catalog
through `/api/ai/provider-models` instead of pinning a snapshot
(the ark-coding `deepseek-v3.2` ghost above shows what those
snapshots drift into).
Covers the endpoint's full responsibility matrix:
- 400: missing body / unknown tool name (via different branches)
- 404: unknown tool, invalid pageId, invalid parent_id,
invalid default_parent_id
- 409: no live-canvas doc synced (element-tool route + DSL route)
- 501: real filePath (live://canvas is accepted as sentinel)
- 400: DSL with parse errors (per-line preview in message)
- happy paths: element-tool writes to sync-state; parent_id
actually nests inserted node under named container; DSL
route invokes runBatchDesignDsl + returns inserted IDs
Uses `vi.mock('h3', ...)` so the handler runs as a plain async
function — no live Nitro runtime. `clearSyncState()` in each
beforeEach isolates doc-mutation cases. server-logger mocked to
keep test output clean.
Full-repo: 2010 tests across 209 files.