From 87c12689cc7da66938f6a43d9dccf5faa766c549 Mon Sep 17 00:00:00 2001 From: yiliang114 Date: Fri, 28 Aug 2026 15:36:59 +0800 Subject: [PATCH 1/2] fix(test): dispatch ACP cron responses by prompt --- integration-tests/cli/acp-cron.test.ts | 32 ++++++++++++++------------ 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/integration-tests/cli/acp-cron.test.ts b/integration-tests/cli/acp-cron.test.ts index 4d9d7b8f6f3..5137512e84d 100644 --- a/integration-tests/cli/acp-cron.test.ts +++ b/integration-tests/cli/acp-cron.test.ts @@ -74,6 +74,16 @@ type PermissionRequest = { }>; }; +const CRON_CREATE_INSTRUCTION = 'Call cron_create with cron expression'; + +function isCronCreateRequest(body: Record): boolean { + const messages = body['messages']; + return ( + Array.isArray(messages) && + JSON.stringify(messages.at(-1))?.includes(CRON_CREATE_INSTRUCTION) === true + ); +} + /** * Sets up an ACP test environment with cron support enabled, backed by * a fake-openai-server for deterministic model responses. @@ -400,14 +410,8 @@ async function initSession( const rig = new TestRig(); await rig.setup('acp-cron-e2e'); - // Only requestIndex 0 is load-bearing: it returns the cron_create - // tool call. The CLI makes internal model calls (tool-call - // classification, suggestion mode) between user-facing turns, so - // later indices do not map 1:1 to the prompts sent below. No - // assertion reads scripted response content, so the default reply - // suffices for every other turn. - const fakeServer = await startFakeOpenAIServer(({ requestIndex }) => { - if (requestIndex === 0) { + const fakeServer = await startFakeOpenAIServer(({ body }) => { + if (isCronCreateRequest(body)) { return { toolCalls: [ fakeToolCall('cron_create', { @@ -440,14 +444,12 @@ async function initSession( })) as { stopReason: string }; expect(createResult.stopReason).toBe('end_turn'); - // Fail fast if the cron_create tool call was not served to the first - // user prompt. An internal model call before the first prompt (title - // generation, a classifier pass) would shift dispatch and otherwise - // surface only as an opaque 75s timeout in Part 3a. + // Fail fast instead of surfacing a missing tool call as an opaque + // 75s timeout in Part 3a. expect( - JSON.stringify(fakeServer.requests[0]?.body['messages']), - 'requestIndex 0 was not the cron_create prompt — dispatch shifted', - ).toContain('CRONFIRE7742'); + fakeServer.requests.some(({ body }) => isCronCreateRequest(body)), + 'fake server did not receive the cron_create prompt', + ).toBe(true); // --- Part 2: Session stays responsive while cron is pending --- const interactiveResult = (await sendRequest('session/prompt', { From 6e68840f90e69fadcbc8e09ba29dc5434c730c95 Mon Sep 17 00:00:00 2001 From: yiliang114 Date: Fri, 28 Aug 2026 15:41:22 +0800 Subject: [PATCH 2/2] test: limit cron dispatch to user prompts --- integration-tests/cli/acp-cron.test.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/integration-tests/cli/acp-cron.test.ts b/integration-tests/cli/acp-cron.test.ts index 5137512e84d..e6ad819b9c6 100644 --- a/integration-tests/cli/acp-cron.test.ts +++ b/integration-tests/cli/acp-cron.test.ts @@ -78,9 +78,13 @@ const CRON_CREATE_INSTRUCTION = 'Call cron_create with cron expression'; function isCronCreateRequest(body: Record): boolean { const messages = body['messages']; + const latestMessage = Array.isArray(messages) ? messages.at(-1) : undefined; return ( - Array.isArray(messages) && - JSON.stringify(messages.at(-1))?.includes(CRON_CREATE_INSTRUCTION) === true + typeof latestMessage === 'object' && + latestMessage !== null && + 'role' in latestMessage && + latestMessage.role === 'user' && + JSON.stringify(latestMessage)?.includes(CRON_CREATE_INSTRUCTION) === true ); }