Files
codewhale/docs/RUNTIME_API.md
T
Hunter Bown cfcdce3d03 feat: runtime and UX polish
P1 features:
- System prompt injection on session resume (ThreadRecord gains system_prompt
  field, ensure_engine_loaded passes it to Op::SyncSession)
- Session resume bridge: GET/POST /v1/sessions/{id}, seed_thread_from_messages
- Task detail panel with deep links (?task=<id>), timeline, tool calls
- Tauri desktop build fix (CI=true in tauri:build script)

P2 features:
- Task detail auto-refresh polling for running/queued tasks (3s interval)
- Session delete: DELETE /v1/sessions/{id} endpoint + palette delete button
- Transcript full-text search input with combined role filter + search
- Per-item copy-to-clipboard, collapse/expand for long outputs, filter chips

Polish:
- Typography scale CSS variables, skeleton loading utilities
- Panel slide-in animation for task detail, fade-up for list items
- Toast auto-dismiss (4s success, 6s error) with dismiss buttons
- Focus trap in command palette, backdrop click to close
- Escape key closes task detail panel
- ARIA improvements: role=alert on error toasts, role=listbox on palette
- Responsive breakpoints for tablet (task detail stacking, palette width)
- prefers-reduced-motion respected throughout

All validation checks pass:
- cargo test (517 tests), cargo check
- pnpm typecheck, lint (0 errors), test (36 tests)
- pnpm web:build, desktop:build
2026-02-18 10:58:13 -06:00

5.2 KiB

Runtime API (HTTP/SSE)

DeepSeek CLI can expose a local runtime API for external clients:

deepseek serve --http --host 127.0.0.1 --port 7878 --workers 2

Defaults:

  • bind: 127.0.0.1:7878
  • workers: 2 (clamped to 1..8)

Security Model (Local-First)

  • The server is designed for trusted local use.
  • There is no built-in auth, user isolation, or TLS termination.
  • Do not expose this API directly to untrusted networks.
  • If remote access is required, place it behind your own authenticated reverse proxy/VPN.

Runtime Data Model

The runtime uses a durable Thread/Turn/Item lifecycle.

  • ThreadRecord
    • id, created_at, updated_at
    • model, workspace, mode
    • latest_turn_id, latest_response_bookmark, archived
  • TurnRecord
    • id, thread_id
    • status: queued|in_progress|completed|failed|interrupted|canceled
    • timestamps, duration, usage, error summary
  • TurnItemRecord
    • id, turn_id
    • kind: user_message|agent_message|tool_call|file_change|command_execution|context_compaction|status|error
    • lifecycle status: queued|in_progress|completed|failed|interrupted|canceled

The event log is append-only with global monotonic seq for replay/resume.

Endpoints

Health and Session

  • GET /health
  • GET /v1/sessions?limit=50&search=<substring>
  • GET /v1/workspace/status
  • GET /v1/skills
  • GET /v1/apps/mcp/servers
  • GET /v1/apps/mcp/tools?server=<optional>

Compatibility Stream (Single Turn)

  • POST /v1/stream

Backwards-compatible one-shot SSE wrapper. Internally creates an archived runtime thread+turn.

Request body:

{
  "prompt": "Summarize recent commits",
  "model": "deepseek-reasoner",
  "mode": "agent",
  "workspace": ".",
  "allow_shell": false,
  "trust_mode": false,
  "auto_approve": true
}

Typical SSE events:

  • turn.started
  • message.delta
  • tool.started
  • tool.progress
  • tool.completed
  • approval.required
  • sandbox.denied
  • status
  • error
  • turn.completed
  • done

Thread Lifecycle

  • POST /v1/threads
  • GET /v1/threads?limit=50&include_archived=false
  • GET /v1/threads/summary?limit=50&search=<optional>&include_archived=false
  • GET /v1/threads/{id}
  • PATCH /v1/threads/{id} (currently supports { "archived": true|false })
  • POST /v1/threads/{id}/resume
  • POST /v1/threads/{id}/fork

Create thread request example:

{
  "model": "deepseek-reasoner",
  "workspace": ".",
  "mode": "agent",
  "allow_shell": false,
  "trust_mode": false,
  "auto_approve": true,
  "archived": false
}

Turn Lifecycle

  • POST /v1/threads/{id}/turns
  • POST /v1/threads/{id}/turns/{turn_id}/steer
  • POST /v1/threads/{id}/turns/{turn_id}/interrupt
  • POST /v1/threads/{id}/compact

Notes:

  • Only one active turn is allowed per thread (409 Conflict on overlap).
  • interrupt returns quickly and marks turn.interrupt_requested.
  • Terminal turn status becomes interrupted only after cleanup completes.
  • Manual compaction is exposed as a turn with context_compaction item lifecycle events.
  • Archiving/unarchiving threads updates persisted thread state and emits thread.updated.

Replayable Events

  • GET /v1/threads/{id}/events?since_seq=<u64>

Returns SSE replay backlog, then live events for that thread.

SSE payload shape:

{
  "seq": 42,
  "timestamp": "2026-02-11T20:18:49.123Z",
  "thread_id": "thr_1234abcd",
  "turn_id": "turn_5678efgh",
  "item_id": "item_90ab12cd",
  "event": "item.delta",
  "payload": {
    "delta": "partial output",
    "kind": "agent_message"
  }
}

Common event names:

  • thread.started
  • thread.forked
  • turn.started
  • turn.lifecycle
  • turn.steered
  • turn.interrupt_requested
  • turn.completed
  • item.started
  • item.delta
  • item.completed
  • item.failed
  • item.interrupted
  • approval.required
  • sandbox.denied

Compaction visibility:

  • auto compaction emits item.started/item.completed with item kind context_compaction and auto=true
  • manual compaction emits the same with auto=false

Background Tasks

  • GET /v1/tasks
  • POST /v1/tasks
  • GET /v1/tasks/{id}
  • POST /v1/tasks/{id}/cancel

Tasks execute through the same runtime thread/turn pipeline and include:

  • linked thread_id / turn_id
  • runtime event count
  • timeline + tool summaries + artifact references

Automations

  • GET /v1/automations
  • POST /v1/automations
  • GET /v1/automations/{id}
  • PATCH /v1/automations/{id}
  • DELETE /v1/automations/{id}
  • POST /v1/automations/{id}/run
  • POST /v1/automations/{id}/pause
  • POST /v1/automations/{id}/resume
  • GET /v1/automations/{id}/runs?limit=20

RRULE support is intentionally constrained to:

  • hourly: FREQ=HOURLY;INTERVAL=<hours>[;BYDAY=MO,TU,...]
  • weekly: FREQ=WEEKLY;BYDAY=...;BYHOUR=<0-23>;BYMINUTE=<0-59>

Automations are persisted under ~/.deepseek/automations (override with DEEPSEEK_AUTOMATIONS_DIR). Each run is executed as a normal background task and links to task/thread/turn ids.

Persistence

Runtime store (default under task data root):

  • runtime/threads/*.json
  • runtime/turns/*.json
  • runtime/items/*.json
  • runtime/events/{thread_id}.jsonl
  • runtime/state.json (monotonic sequence)

Task store:

  • default ~/.deepseek/tasks (override with DEEPSEEK_TASKS_DIR)

Both runtime and task state are restart-safe.