feat(continuity): Add file-based continuity command handling to orchestrator#331
feat(continuity): Add file-based continuity command handling to orchestrator#331khaliqgant merged 10 commits intomainfrom
Conversation
| this.messageQueue.push({ | ||
| from: 'system', | ||
| body: response, | ||
| messageId: `continuity-${Date.now()}`, | ||
| thread: 'continuity-response', | ||
| }); | ||
| this.log(`Queued continuity response for injection`); |
There was a problem hiding this comment.
🟡 Missing processMessageQueue() call after queuing continuity response
When a continuity command (like load) returns a response, the response is pushed to messageQueue but processMessageQueue() is never called to trigger injection.
Click to expand
How the bug is triggered
When an agent sends a load continuity command and handleCommand() returns a response (e.g., previous session context), the code at lines 1167-1172 queues the response but doesn't call processMessageQueue().
Actual vs Expected
- Actual: The response sits in the queue until either the queue monitor runs (every 5 seconds per
QUEUE_MONITOR_INTERVAL_MS) or another message arrives. - Expected: The response should be injected immediately, as done in
tmux-wrapper.ts:1177which callsthis.checkForInjectionOpportunity()after pushing.
Impact
Continuity responses (session context on load) will be delayed by up to 5 seconds, degrading user experience when agents request their previous session state.
Recommendation: Add this.processMessageQueue(); after line 1173, similar to how other message queue operations in this file call it (e.g., line 2037).
Was this helpful? React with 👍 or 👎 to provide feedback.
| if (command.content && this.processedContinuityCommands.has(cmdHash)) { | ||
| this.log(`Continuity command already processed: ${cmdHash}`); | ||
| return; |
There was a problem hiding this comment.
🟡 Deduplication check fails for 'uncertain' commands due to wrong field check
The deduplication condition checks command.content but for uncertain commands, the content is stored in command.item, causing these commands to never be deduplicated.
Click to expand
How the bug is triggered
For an uncertain command with content "API rate limit handling unclear":
- Line 1145 sets
command.item = "API rate limit handling unclear" command.contentremainsundefined- Line 1149 creates hash:
"uncertain:API rate limit handling unclear"(correct) - Line 1150 checks:
if (command.content && this.processedContinuityCommands.has(cmdHash))- butcommand.contentis falsy! - The duplicate check is skipped, and duplicate
uncertaincommands are processed.
Actual vs Expected
- Actual:
uncertaincommands are never deduplicated becausecommand.contentis undefined for them. - Expected: The check should use
(command.content || command.item)to match the hash computation, consistent withtmux-wrapper.ts:1150-1154which useshasContent = command.content || command.query || command.item.
Impact
Duplicate uncertain commands will be processed multiple times, potentially recording the same uncertainty item repeatedly in the continuity ledger.
Recommendation: Change line 1150 from if (command.content && this.processedContinuityCommands.has(cmdHash)) to if ((command.content || command.item) && this.processedContinuityCommands.has(cmdHash)) to match the hash computation on line 1149.
Was this helpful? React with 👍 or 👎 to provide feedback.
…strator Previously, file-based continuity commands (KIND: continuity) were parsed by relay-pty and output to stderr, but the orchestrator only processed relay_command types, causing continuity commands to be silently dropped. Changes: - Add handleRustContinuityCommand() in relay-pty-orchestrator.ts to process continuity JSON from relay-pty stderr - Map Rust ContinuityCommand format to TypeScript ContinuityCommand - Forward to ContinuityManager.handleCommand() for persistence - Add 5 tests for continuity command handling - Document continuity file format in relay-pty-schemas.ts This enables proper session persistence via the file-based protocol: KIND: continuity ACTION: save/load/uncertain 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
27a36c4 to
dc8c07c
Compare
Fixes CI failures caused by npm bug #4828 where optional dependencies (@rollup/rollup-linux-x64-gnu) are not installed correctly. Added 'npm install --no-save rollup || true' step after npm ci in: - test.yml (test, coverage, lint jobs) - node-compat.yml (install-test job) - sqlite-migrations.yml - publish.yml (build job, after both npm ci and clean reinstall) This ensures vitest's rollup dependency has platform-specific binaries available even when npm's optional dependency handling fails.
Create shared request/response handling helpers to ensure SDK and MCP clients stay in lockstep and prevent future inconsistencies. Added: - Type aliases: SpawnResult, ReleaseResult - createRequestHandler() - shared request/response logic - createRequestEnvelope() - envelope creation helper - isMatchingResponse() - response matching logic - handleResponse() - response resolution logic - toSpawnResult() / toReleaseResult() - conversion functions - generateRequestId() - ID generation helper This provides a single source of truth for request/response handling and ensures both clients behave identically.
Fix all inconsistencies between MCP and SDK client implementations: 1. spawn() - Now waits for SPAWN_RESULT like SDK, uses shared helpers 2. release() - Returns ReleaseResultPayload with success/name/error 3. sendAndWait() - Returns full AckPayload instead of fabricated object 4. send() - Supports kind/data options like SDK sendMessage 5. Envelopes - All spawn/release include 'from: agentName' field Refactored to use shared client helpers from @agent-relay/utils, reducing code duplication and ensuring consistency going forward. Updated tests to use AckPayload structure.
🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Fixes npm ci failures in CI by including optional dependency entries for all platforms (esbuild, rollup, turbo platform binaries). 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Aligns hybrid-client.ts and simple.ts with the new AckPayload return type from the SDK/MCP consistency changes. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Since spawn() now waits for SPAWN_RESULT like SDK, tests need to mock the socket to send back a SPAWN_RESULT response. Updated both failing tests to properly mock the response.
… deps The createRequestHandler in client-helpers imports createConnection from node:net. The test mock needs to properly preserve the original module while overriding createConnection. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Previously, file-based continuity commands (KIND: continuity) were parsed by relay-pty and output to stderr, but the orchestrator only processed relay_command types, causing continuity commands to be silently dropped.
Changes:
This enables proper session persistence via the file-based protocol:
KIND: continuity
ACTION: save/load/uncertain