mirror of
https://github.com/wu736139669/hapi.git
synced 2026-08-05 06:24:37 +00:00
Hub already passes access.sessionId on resume (#1088); Cursor CLI still ignored it (Codex-only). Parse/pass the flag for cursor and lock in reuse-without-ready-wait tests. Co-authored-by: Debian <heavygee@oos-linux.in.lockhouse> Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
co-authored by
Debian
Cursor
parent
fee853766a
commit
40314237ae
@@ -1240,6 +1240,158 @@ describe('session model', () => {
|
||||
}
|
||||
})
|
||||
|
||||
it('cursor ACP resume passes existingSessionId and reuses row without session-ready wait (#991)', async () => {
|
||||
const store = new Store(':memory:')
|
||||
const engine = new SyncEngine(
|
||||
store,
|
||||
{} as never,
|
||||
new RpcRegistry(),
|
||||
{ broadcast() {} } as never
|
||||
)
|
||||
|
||||
try {
|
||||
const oldSession = engine.getOrCreateSession(
|
||||
'cursor-reopen-old',
|
||||
{
|
||||
path: '/tmp/project',
|
||||
host: 'localhost',
|
||||
machineId: 'machine-1',
|
||||
flavor: 'cursor',
|
||||
cursorSessionId: 'cursor-csid-load-fail',
|
||||
cursorSessionProtocol: 'acp'
|
||||
},
|
||||
null,
|
||||
'default'
|
||||
)
|
||||
engine.getOrCreateMachine(
|
||||
'machine-1',
|
||||
{ host: 'localhost', platform: 'linux', happyCliVersion: '0.1.0' },
|
||||
null,
|
||||
'default'
|
||||
)
|
||||
engine.handleMachineAlive({ machineId: 'machine-1', time: Date.now() })
|
||||
engine.handleSessionEnd({ sid: oldSession.id, time: Date.now() })
|
||||
|
||||
let capturedExistingSessionId: string | undefined
|
||||
let waitForSessionReadyCalls = 0
|
||||
let mergeCalls = 0
|
||||
const sessionCache = (engine as any).sessionCache
|
||||
const mergeSessions = sessionCache.mergeSessions.bind(sessionCache)
|
||||
sessionCache.mergeSessions = async (oldSessionId: string, newSessionId: string, namespace: string) => {
|
||||
mergeCalls += 1
|
||||
return mergeSessions(oldSessionId, newSessionId, namespace)
|
||||
}
|
||||
|
||||
;(engine as any).rpcGateway.spawnSession = async (
|
||||
_machineId: string,
|
||||
_directory: string,
|
||||
_agent: string,
|
||||
_model?: string,
|
||||
_modelReasoningEffort?: string,
|
||||
_yolo?: boolean,
|
||||
_sessionType?: string,
|
||||
_worktreeName?: string,
|
||||
_resumeSessionId?: string,
|
||||
_effort?: string,
|
||||
_permissionMode?: string,
|
||||
_serviceTier?: string,
|
||||
existingSessionId?: string
|
||||
) => {
|
||||
capturedExistingSessionId = existingSessionId
|
||||
engine.handleSessionAlive({ sid: oldSession.id, time: Date.now() })
|
||||
return { type: 'success', sessionId: oldSession.id }
|
||||
}
|
||||
;(engine as any).rpcGateway.getCursorChatStoreStatus = async () => ({ onDisk: true, store: 'acp' })
|
||||
;(engine as any).waitForSessionActive = async () => true
|
||||
;(engine as any).waitForSessionReady = async () => {
|
||||
waitForSessionReadyCalls += 1
|
||||
return 'timeout'
|
||||
}
|
||||
|
||||
const result = await engine.resumeSession(oldSession.id, 'default')
|
||||
|
||||
expect(result).toEqual({ type: 'success', sessionId: oldSession.id })
|
||||
expect(capturedExistingSessionId).toBe(oldSession.id)
|
||||
expect(waitForSessionReadyCalls).toBe(0)
|
||||
expect(mergeCalls).toBe(0)
|
||||
expect(store.sessions.getSession(oldSession.id)).not.toBeNull()
|
||||
} finally {
|
||||
engine.stop()
|
||||
}
|
||||
})
|
||||
|
||||
it('cursor ACP resume succeeds on same row without merge (#991)', async () => {
|
||||
const store = new Store(':memory:')
|
||||
const engine = new SyncEngine(
|
||||
store,
|
||||
{} as never,
|
||||
new RpcRegistry(),
|
||||
{ broadcast() {} } as never
|
||||
)
|
||||
|
||||
try {
|
||||
const oldSession = engine.getOrCreateSession(
|
||||
'cursor-reopen-old-ready',
|
||||
{
|
||||
path: '/tmp/project',
|
||||
host: 'localhost',
|
||||
machineId: 'machine-1',
|
||||
flavor: 'cursor',
|
||||
cursorSessionId: 'cursor-csid-load-ok',
|
||||
cursorSessionProtocol: 'acp'
|
||||
},
|
||||
null,
|
||||
'default'
|
||||
)
|
||||
engine.getOrCreateMachine(
|
||||
'machine-1',
|
||||
{ host: 'localhost', platform: 'linux', happyCliVersion: '0.1.0' },
|
||||
null,
|
||||
'default'
|
||||
)
|
||||
engine.handleMachineAlive({ machineId: 'machine-1', time: Date.now() })
|
||||
engine.handleSessionEnd({ sid: oldSession.id, time: Date.now() })
|
||||
|
||||
let mergeCalls = 0
|
||||
const sessionCache = (engine as any).sessionCache
|
||||
const mergeSessions = sessionCache.mergeSessions.bind(sessionCache)
|
||||
sessionCache.mergeSessions = async (oldSessionId: string, newSessionId: string, namespace: string) => {
|
||||
mergeCalls += 1
|
||||
return mergeSessions(oldSessionId, newSessionId, namespace)
|
||||
}
|
||||
|
||||
;(engine as any).rpcGateway.spawnSession = async (
|
||||
_machineId: string,
|
||||
_directory: string,
|
||||
_agent: string,
|
||||
_model?: string,
|
||||
_modelReasoningEffort?: string,
|
||||
_yolo?: boolean,
|
||||
_sessionType?: string,
|
||||
_worktreeName?: string,
|
||||
_resumeSessionId?: string,
|
||||
_effort?: string,
|
||||
_permissionMode?: string,
|
||||
_serviceTier?: string,
|
||||
existingSessionId?: string
|
||||
) => {
|
||||
expect(existingSessionId).toBe(oldSession.id)
|
||||
engine.handleSessionAlive({ sid: oldSession.id, time: Date.now() })
|
||||
return { type: 'success', sessionId: oldSession.id }
|
||||
}
|
||||
;(engine as any).rpcGateway.getCursorChatStoreStatus = async () => ({ onDisk: true, store: 'acp' })
|
||||
;(engine as any).waitForSessionActive = async () => true
|
||||
|
||||
const result = await engine.resumeSession(oldSession.id, 'default')
|
||||
|
||||
expect(result).toEqual({ type: 'success', sessionId: oldSession.id })
|
||||
expect(mergeCalls).toBe(0)
|
||||
expect(store.sessions.getSession(oldSession.id)).not.toBeNull()
|
||||
} finally {
|
||||
engine.stop()
|
||||
}
|
||||
})
|
||||
|
||||
it('defers mergeSessions for cursor reopen until session-ready (load failure leaves old row)', async () => {
|
||||
const store = new Store(':memory:')
|
||||
const engine = new SyncEngine(
|
||||
|
||||
Reference in New Issue
Block a user