feat: Auto-resume idle agents for inter-agent conversations

When an agent asks a question via `cw ask` targeting an idle agent,
the conversation router now auto-resumes the idle agent's session so
it can answer. Previously, questions to idle agents sat unanswered
forever because target resolution only matched running agents.

Changes:
- Add `resumeForConversation()` to AgentManager interface and implement
  on MultiProviderAgentManager (mirrors resumeForCommit pattern)
- Relax createConversation target resolution: prefer running, fall back
  to idle (was running-only)
- Trigger auto-resume after conversation creation for idle targets
- Add concurrency lock (conversationResumeLocks Set) to prevent
  double-resume race conditions
This commit is contained in:
Lukas May
2026-03-03 13:29:39 +01:00
parent 938700d45d
commit 9edc93a268
7 changed files with 116 additions and 7 deletions

View File

@@ -115,6 +115,25 @@ cw account add --token <token> --email user@example.com
Stored as `credentials: {"claudeAiOauth":{"accessToken":"<token>"}}` and `configJson: {"hasCompletedOnboarding":true}`.
## Auto-Resume for Conversations
When Agent A asks Agent B a question via `cw ask` and Agent B is idle, the conversation router automatically resumes Agent B's session. This mirrors the `resumeForCommit()` pattern.
### Flow
1. `createConversation` tRPC procedure creates the conversation record
2. Target resolution prefers `running` agents, falls back to `idle` (previously only matched `running`)
3. After creation, checks if target agent is idle → calls `agentManager.resumeForConversation()`
4. Agent resumes with a prompt to: answer via `cw answer`, drain pending conversations via `cw listen`, then complete
### Guards
- Agent must be `idle` status with a valid `sessionId`
- Provider must support resume (`resumeStyle !== 'none'`)
- Worktree must still exist (`existsSync` check)
- In-memory `conversationResumeLocks` Set prevents double-resume race when multiple conversations arrive simultaneously
- Resume failure is caught and logged — conversation is always created even if resume fails
## Auto-Cleanup & Commit Retries
After an agent completes (status → `idle`), `tryAutoCleanup` checks if its project worktrees have uncommitted changes:

View File

@@ -25,7 +25,7 @@
| **Worktree** | `worktree:created`, `worktree:removed`, `worktree:merged`, `worktree:conflict` | 4 |
| **Account** | `account:credentials_refreshed`, `account:credentials_expired`, `account:credentials_validated` | 3 |
| **Preview** | `preview:building`, `preview:ready`, `preview:stopped`, `preview:failed` | 4 |
| **Conversation** | `conversation:created`, `conversation:answered` | 2 |
| **Conversation** | `conversation:created`, `conversation:answered` | 2 | `conversation:created` triggers auto-resume of idle target agents via `resumeForConversation()` |
| **Log** | `log:entry` | 1 |
### Key Event Payloads