Skip to content

Commit ee906cc

Browse files
heavygeecursoragent
andcommitted
fix(web): allow claude session resume via hub message-id recovery
Hub `resolveAgentResumeId` falls back to `recoverClaudeSessionIdFromMessages` on the claude branch when `metadata.claudeSessionId` is absent, so the web guard must not block inactive claude sessions that have stored messages but no metadata id. Other flavors have no such recovery path and stay rejected. Addresses second HAPI Bot review thread on tiann#761 (`web/src/lib/sessionResume.ts:41`). Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent 45bb1ef commit ee906cc

2 files changed

Lines changed: 25 additions & 0 deletions

File tree

web/src/lib/sessionResume.test.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,4 +93,22 @@ describe('sessionResume', () => {
9393
it('inactiveSessionCanResume rejects when metadata path is missing', () => {
9494
expect(inactiveSessionCanResume(makeSession({ metadata: { path: '', host: 'localhost' } }), 0)).toBe(false)
9595
})
96+
97+
it('inactiveSessionCanResume allows claude resume by message recovery when no claudeSessionId is stored', () => {
98+
expect(inactiveSessionCanResume(makeSession({
99+
metadata: { path: '/tmp/project', host: 'localhost', flavor: 'claude' },
100+
}), 3)).toBe(true)
101+
})
102+
103+
it('inactiveSessionCanResume allows claude recovery when flavor is missing (defaults to claude)', () => {
104+
expect(inactiveSessionCanResume(makeSession({
105+
metadata: { path: '/tmp/project', host: 'localhost' },
106+
}), 3)).toBe(true)
107+
})
108+
109+
it('inactiveSessionCanResume rejects non-claude flavors with messages but no flavor-specific id (no recovery path)', () => {
110+
expect(inactiveSessionCanResume(makeSession({
111+
metadata: { path: '/tmp/project', host: 'localhost', flavor: 'codex' },
112+
}), 3)).toBe(false)
113+
})
96114
})

web/src/lib/sessionResume.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ export function resolveAgentSessionIdFromMetadata(
2424
/**
2525
* Whether an inactive session can be activated via resume (or fresh spawn on first send).
2626
* Matches hub: resume with agent id, or fresh spawn when path exists, no agent id, no user messages.
27+
* Claude with messages but no `claudeSessionId` is allowed because hub
28+
* `recoverClaudeSessionIdFromMessages` reconstructs the resume id from the
29+
* stored message log (only the claude path has this recovery fallback).
2730
*/
2831
export function inactiveSessionCanResume(
2932
session: Session,
@@ -38,5 +41,9 @@ export function inactiveSessionCanResume(
3841
if (resolveAgentSessionIdFromMetadata(session.metadata)) {
3942
return true
4043
}
44+
const flavor = isKnownFlavor(session.metadata.flavor) ? session.metadata.flavor : 'claude'
45+
if (flavor === 'claude' && userMessageCount > 0) {
46+
return true
47+
}
4148
return userMessageCount === 0
4249
}

0 commit comments

Comments
 (0)