mirror of
https://github.com/wu736139669/hapi.git
synced 2026-08-05 06:24:37 +00:00
fix(cursor): register cursorSessionId before ACP session/load (#837)
Pre-write resume token into session metadata before awaiting session/load so hub and web see cursorSessionId immediately after resume spawn. Fixes #834 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -12,7 +12,9 @@ const harness = vi.hoisted(() => ({
|
|||||||
backendArgs: null as { command: string; args?: string[] } | null,
|
backendArgs: null as { command: string; args?: string[] } | null,
|
||||||
setConfigOptionCalls: [] as Array<{ sessionId: string; configId: string; value: string }>,
|
setConfigOptionCalls: [] as Array<{ sessionId: string; configId: string; value: string }>,
|
||||||
deferSetConfigOption: null as Promise<void> | null,
|
deferSetConfigOption: null as Promise<void> | null,
|
||||||
releaseSetConfigOption: null as (() => void) | null
|
releaseSetConfigOption: null as (() => void) | null,
|
||||||
|
deferLoadSession: null as Promise<void> | null,
|
||||||
|
releaseLoadSession: null as (() => void) | null
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const legacyLauncher = vi.hoisted(() => vi.fn());
|
const legacyLauncher = vi.hoisted(() => vi.fn());
|
||||||
@@ -38,6 +40,9 @@ vi.mock('./utils/cursorAcpBackend', () => ({
|
|||||||
supportsLoadSession: vi.fn(() => harness.supportsLoadSession),
|
supportsLoadSession: vi.fn(() => harness.supportsLoadSession),
|
||||||
loadSession: vi.fn(async () => {
|
loadSession: vi.fn(async () => {
|
||||||
harness.loadSessionCalled = true;
|
harness.loadSessionCalled = true;
|
||||||
|
if (harness.deferLoadSession) {
|
||||||
|
await harness.deferLoadSession;
|
||||||
|
}
|
||||||
if (harness.loadSessionError) throw harness.loadSessionError;
|
if (harness.loadSessionError) throw harness.loadSessionError;
|
||||||
return 'loaded-acp-session';
|
return 'loaded-acp-session';
|
||||||
}),
|
}),
|
||||||
@@ -174,6 +179,8 @@ describe('cursorAcpRemoteLauncher', () => {
|
|||||||
harness.setConfigOptionCalls = [];
|
harness.setConfigOptionCalls = [];
|
||||||
harness.deferSetConfigOption = null;
|
harness.deferSetConfigOption = null;
|
||||||
harness.releaseSetConfigOption = null;
|
harness.releaseSetConfigOption = null;
|
||||||
|
harness.deferLoadSession = null;
|
||||||
|
harness.releaseLoadSession = null;
|
||||||
legacyLauncher.mockClear();
|
legacyLauncher.mockClear();
|
||||||
process.stdin.isTTY = false;
|
process.stdin.isTTY = false;
|
||||||
process.stdout.isTTY = false;
|
process.stdout.isTTY = false;
|
||||||
@@ -204,6 +211,27 @@ describe('cursorAcpRemoteLauncher', () => {
|
|||||||
expect(harness.newSessionCalled).toBe(false);
|
expect(harness.newSessionCalled).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('registers cursorSessionId before session/load completes', async () => {
|
||||||
|
let releaseLoadSession!: () => void;
|
||||||
|
harness.deferLoadSession = new Promise<void>((resolve) => {
|
||||||
|
harness.releaseLoadSession = resolve;
|
||||||
|
releaseLoadSession = resolve;
|
||||||
|
});
|
||||||
|
|
||||||
|
const session = makeSession('resume-thread-1');
|
||||||
|
const launchPromise = cursorAcpRemoteLauncher(session);
|
||||||
|
|
||||||
|
await vi.waitFor(() => {
|
||||||
|
expect(session.onSessionFoundWithProtocol).toHaveBeenCalledWith('resume-thread-1', 'acp');
|
||||||
|
});
|
||||||
|
expect(harness.loadSessionCalled).toBe(true);
|
||||||
|
|
||||||
|
releaseLoadSession();
|
||||||
|
await launchPromise;
|
||||||
|
|
||||||
|
expect(session.onSessionFoundWithProtocol).toHaveBeenCalledWith('loaded-acp-session', 'acp');
|
||||||
|
});
|
||||||
|
|
||||||
it('throws when session/load fails instead of falling back to stream-json', async () => {
|
it('throws when session/load fails instead of falling back to stream-json', async () => {
|
||||||
harness.loadSessionError = new Error('session not found');
|
harness.loadSessionError = new Error('session not found');
|
||||||
const session = makeSession('old-stream-json-id');
|
const session = makeSession('old-stream-json-id');
|
||||||
|
|||||||
@@ -96,6 +96,8 @@ class CursorAcpRemoteLauncher extends RemoteLauncherBase {
|
|||||||
let acpSessionId: string;
|
let acpSessionId: string;
|
||||||
|
|
||||||
if (resumeSessionId && backend.supportsLoadSession()) {
|
if (resumeSessionId && backend.supportsLoadSession()) {
|
||||||
|
// Register pending cursorSessionId before awaiting session/load (Zed PR #54431).
|
||||||
|
session.onSessionFoundWithProtocol(resumeSessionId, 'acp');
|
||||||
try {
|
try {
|
||||||
acpSessionId = await backend.loadSession({
|
acpSessionId = await backend.loadSession({
|
||||||
sessionId: resumeSessionId,
|
sessionId: resumeSessionId,
|
||||||
@@ -119,7 +121,9 @@ class CursorAcpRemoteLauncher extends RemoteLauncherBase {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (acpSessionId !== resumeSessionId) {
|
||||||
session.onSessionFoundWithProtocol(acpSessionId, 'acp');
|
session.onSessionFoundWithProtocol(acpSessionId, 'acp');
|
||||||
|
}
|
||||||
|
|
||||||
syncCursorModelsFromAcp(backend, acpSessionId);
|
syncCursorModelsFromAcp(backend, acpSessionId);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user