fix(snapshot): register filesystem tools through explicit overlay
This commit is contained in:
@@ -274,6 +274,27 @@ function parseJsonlRecords(text: string): Record<string, unknown>[] {
|
||||
.map(line => JSON.parse(line) as Record<string, unknown>)
|
||||
}
|
||||
|
||||
/**
|
||||
* Find tool calls whose structured result reports `UNKNOWN_TOOL`.
|
||||
*
|
||||
* Snapshot refresh must not turn a missing registration into accepted behavior;
|
||||
* intentional unknown-tool behavior belongs in a focused unit or e2e test.
|
||||
*
|
||||
* @param rawLog The session JSONL to inspect.
|
||||
* @returns The failing call ids in log order, using a diagnostic placeholder when absent.
|
||||
*/
|
||||
export function unknownToolCallIds(rawLog: string): string[] {
|
||||
return parseJsonlRecords(rawLog).flatMap((record) => {
|
||||
if (record.type !== 'tool/result') return []
|
||||
const data = record.data
|
||||
if (data === null || typeof data !== 'object') return []
|
||||
const { callId, error } = data as { callId?: unknown; error?: unknown }
|
||||
if (error === null || typeof error !== 'object') return []
|
||||
if ((error as { code?: unknown }).code !== 'UNKNOWN_TOOL') return []
|
||||
return [typeof callId === 'string' ? callId : '<missing callId>']
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the cross-log id/cwd replacements used by refresh write-back.
|
||||
*
|
||||
@@ -401,6 +422,11 @@ export function defineAcpSnapshotSuite(options: SnapshotSuiteOptions): void {
|
||||
...scenario.configPath !== undefined ? { configPath: scenario.configPath } : {},
|
||||
})
|
||||
|
||||
for (const log of result.sessionLogs) {
|
||||
expect(unknownToolCallIds(log.content), `session ${log.id}: snapshot scenarios must not accept UNKNOWN_TOOL`)
|
||||
.toEqual([])
|
||||
}
|
||||
|
||||
// Scrub every volatile id the run produced: the ACP server-issued session id plus every
|
||||
// harvested log's recorded id (a subagent child id never surfaces over ACP, but it
|
||||
// appears in the child's own log header).
|
||||
@@ -598,5 +624,20 @@ export function defineAcpSnapshotSuite(options: SnapshotSuiteOptions): void {
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
it('no committed session fixture accepts UNKNOWN_TOOL', async () => {
|
||||
for (const scenario of scenarios) {
|
||||
const dir = join(snapshotsDir, scenario.name)
|
||||
const files = [
|
||||
'session.jsonl',
|
||||
...Array.from({ length: scenario.childSessions ?? 0 }, (_, i) => `session.${i + 1}.jsonl`),
|
||||
]
|
||||
for (const file of files) {
|
||||
const fixture = await readFile(join(dir, file), 'utf8')
|
||||
expect(unknownToolCallIds(fixture), `${scenario.name}/${file} contains UNKNOWN_TOOL`)
|
||||
.toEqual([])
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user