| Age | Commit message (Collapse) | Author |
|
The backend already supported GET /conversations?workspaceId= but the CLI
never sent it. Wire the list command to that filter:
- args.ts: parse --workspace / -w on 'list' (placed before the --catch-all
so the single-dash -w shorthand isn't taken for a positional prefix);
add workspaceId? to the list ParsedCommand.
- http.ts: add workspaceId? to FetchConversationsOpts; send ?workspaceId=
(after q/status, preserving URLSearchParams order).
- main.ts: forward parsed.workspaceId into fetchConversations; update USAGE.
Composable with --status and the <prefix> short-id arg. 'Open conversations
in workspace X' is now: dispatch list --workspace X (status defaults to
active,idle). No contract changes — purely additive CLI wiring.
Tests: +4 args (incl. composability + missing-value error), +2 http
(exact ?workspaceId= URL + combined status/workspaceId with %2C encoding).
typecheck EXIT 0, biome clean (364 files), full suite 1558 passed.
Live-verified against an isolated server.
|
|
Add the same --file <path> support that the summon (chat) command has to the
'dispatch send' subcommand. When --file is given, the file's contents are read
and attached to the message (composed via composeMessage, identical to chat).
- args.ts: add 'file' to the send ParsedCommand, make 'text' optional, parse
--file, and require at least one of --text or --file.
- main.ts: read the file and compose the message in the send case, using the
composed message in both the --queue and streaming branches; update USAGE.
- args.test.ts: cover --file parsing (alone, with --text, missing value) and
update the existing send expectations + the both-missing error message.
|
|
cli (Wave 2+3)
session-orchestrator: workspaceId on StartTurnInput/EnqueueInput; effective cwd
resolution (getCwd → getEffectiveCwd); auto-create workspace on turn start;
warm parity (same effective cwd). 93 tests (+8).
transport-http: workspace routes (GET/PUT/DELETE /workspaces, title, default-cwd);
workspaceId threading on POST /chat + queue; ?workspaceId= filter on
GET /conversations; DELETE /conversations/:id/cwd (clears explicit cwd);
GET /conversations/:id/lsp uses effective cwd; slug validation. 166 tests.
transport-ws: workspaceId threading on chat.send + chat.queue. 32 tests.
cli: --workspace/-w flag; ConversationMeta test fakes fixed. 123 tests.
Full typecheck EXIT 0, biome clean. 1283 vitest + 199 transport bun pass
(1 pre-existing tool-shell failure unrelated to workspaces).
|
|
Add stopTurn to the orchestrator: aborts the in-flight turn's
AbortController without changing conversation status. The turn
seals normally (finishReason: 'aborted'), partial messages are
persisted, and the conversation transitions active → idle via the
normal settle path.
Distinct from closeConversation which marks the conversation closed.
- POST /conversations/:id/stop endpoint
- dispatch stop <id> CLI command
- FE handoff: frontend-stop-generation-handoff.md
|
|
Implement roadmap item 10: conversation compaction to reclaim context
window without losing the thread.
Wire (0.11.0):
- Add CompactionResult type
- Add ConversationCompactedMessage WS event
Transport-contract (0.15.0):
- Add CompactResponse, CompactThresholdResponse, SetCompactThresholdRequest
- Add ConversationCompactedMessage to WsServerMessage union
- Re-export CompactionResult
Conversation-store:
- replaceHistory: delete all chunks, reset seq, append new messages
- getCompactThreshold / setCompactThreshold (per-conversation setting)
- compactThresholdKey added to keys.ts
Session-orchestrator:
- CompactionService interface + compactionHandle
- conversationCompacted hook descriptor
- createCompactionService: load history, split old/recent, call provider
to summarize, replaceHistory with [system: summary] + recent N
- Auto-trigger: resolveCompaction lazy dep, fires after turn settles
(checks threshold, non-blocking)
- Hook declared in manifest contributes.hooks + services
Transport-http:
- POST /conversations/:id/compact (manual trigger)
- GET /conversations/:id/compact-threshold (read setting)
- PUT /conversations/:id/compact-threshold (set setting)
Transport-ws:
- Subscribe to conversationCompacted hook
- Broadcast conversation.compacted WS message
CLI:
- dispatch compact <conversationId> command
FE handoff: frontend-compaction-handoff.md
|
|
Implement roadmap item 9: tab persistence across devices.
Wire (0.10.0):
- Add ConversationStatus type (active | idle | closed)
- Add status field to ConversationMeta
Transport-contract (0.14.0):
- Add conversation.statusChanged WS message to WsServerMessage union
- Re-export ConversationStatus
Conversation-store:
- Track status in ConversationMetaRow (default: idle)
- getConversationStatus / setConversationStatus methods
- listConversations accepts { status: ConversationStatus[] } filter
- Old meta rows without status default to idle on read
Session-orchestrator:
- conversationStatusChanged hook descriptor
- Emit on transitions: idle→active (turn start), active→idle (turn settle),
→closed (closeConversation)
- Persist status to store as fire-and-forget side effect
- Declare hook in manifest contributes.hooks
Transport-ws:
- Subscribe to conversationStatusChanged hook
- Broadcast conversation.statusChanged WS message to all clients
Transport-http:
- GET /conversations?status=active,idle filter (parseStatusFilter pure helper)
- POST /conversations/:id/close now sets status to closed
CLI:
- dispatch list defaults to active,idle (excludes closed)
- --status <state> flag to filter by single status
- --all flag to include closed
FE handoff: frontend-conversation-lifecycle-handoff.md
|
|
dispatch open <conversationId> broadcasts a conversation.open WS message
to all connected frontend clients without sending any message. Useful
after 'read' or 'send --queue' when you just want the frontend to
open/focus a conversation's tab.
|
|
dispatch <model> --text "..." --open now starts a new conversation AND
signals the frontend to open the tab — no need for a separate
'dispatch send --open' step.
|
|
CLI gains three new sub-commands:
- dispatch list [--server] — list conversations (short ID + title + activity)
- dispatch read <id> [--server] — block until turn settles, print last AI message
- dispatch send <id> --text [--queue] [--open] [--cwd] [--effort] [--server]
- Default: blocking (consumes NDJSON stream, prints accumulated text + conv ID)
- --queue: non-blocking (POST /conversations/:id/queue, exit immediately)
- --open: signals frontend to open the conversation tab (POST /conversations/:id/open)
Short-ID resolution: 4+ char prefix → GET /conversations?q= → resolve to full ID.
32+ char input is treated as a full UUID (no resolution). Errors on 0 or >1 matches.
48 new tests (108 total in cli). Pure arg parser + HTTP client functions, zero vi.mock.
|
|
threaded to providers
- conversation-store: get/setReasoningEffort (own key space, mirrors cwd)
- session-orchestrator: resolveReasoningEffort (override -> stored -> 'high'),
StartTurnInput.reasoningEffort, warm() parity (cache-safe)
- transport-http: /chat validation (400 on bad level) + GET/PUT
/conversations/:id/reasoning-effort
- transport-ws: chat.send threading + validation
- cli: --effort <low|medium|high|xhigh|max>
993 vitest + 189 bun tests green; typecheck + biome clean.
|
|
--text/--file/--cwd/--conversation)
HTTP client of transport-contract; pure-core arg/render/ndjson + injected fetch/fs shell.
Docs: GLOSSARY (credential/key/model name/model catalog), tasks.md milestone, ORCHESTRATOR geography.
|