test(pi): wire packaged confirmation delay

This commit is contained in:
2026-08-26 07:50:23 +08:00
parent 26d616c9b6
commit f5e6a04c7d
2 changed files with 19 additions and 1 deletions

View File

@@ -125,6 +125,7 @@ export interface PiWorkerProcessAdapter {
subscribeInvalidation(listener: (error: PiProcessError) => void): () => void; subscribeInvalidation(listener: (error: PiProcessError) => void): () => void;
stop(reason: PiWorkerStopReason): Promise<PiWorkerStopResult>; stop(reason: PiWorkerStopReason): Promise<PiWorkerStopResult>;
injectFailureForProof?(failure: PiWorkerProofFailure): Promise<void>; injectFailureForProof?(failure: PiWorkerProofFailure): Promise<void>;
delayNextResponseForProof?(commandType: string, delayMs: number): void;
} }
export interface PiManagedProviderInput { export interface PiManagedProviderInput {
@@ -193,6 +194,13 @@ class ManagedPiConversationWorker implements PiConversationWorker {
} }
await this.process.injectFailureForProof(failure); await this.process.injectFailureForProof(failure);
} }
delayNextResponseForProof(commandType: string, delayMs: number): void {
if (!this.process.delayNextResponseForProof) {
throw new Error('Managed Pi process does not support proof response delay');
}
this.process.delayNextResponseForProof(commandType, delayMs);
}
} }
export function createPiManagedWorkerOpener( export function createPiManagedWorkerOpener(

View File

@@ -34,6 +34,7 @@ const NOW = '2026-08-22T16:00:00.000Z';
class OpenerFakeProcess implements PiWorkerProcessAdapter { class OpenerFakeProcess implements PiWorkerProcessAdapter {
readonly generation = 1; readonly generation = 1;
readonly proofResponseDelays: Array<{ commandType: string; delayMs: number }> = [];
constructor( constructor(
private readonly sessionId: string, private readonly sessionId: string,
private readonly options: PiWorkerProcessOptions, private readonly options: PiWorkerProcessOptions,
@@ -60,6 +61,9 @@ class OpenerFakeProcess implements PiWorkerProcessAdapter {
subscribe(_listener: (event: PiRpcEvent) => void): () => void { return () => undefined; } subscribe(_listener: (event: PiRpcEvent) => void): () => void { return () => undefined; }
subscribeInvalidation(_listener: (error: PiProcessError) => void): () => void { return () => undefined; } subscribeInvalidation(_listener: (error: PiProcessError) => void): () => void { return () => undefined; }
delayNextResponseForProof(commandType: string, delayMs: number): void {
this.proofResponseDelays.push({ commandType, delayMs });
}
async stop() { return { mode: 'stdin-close' as const, code: 0, signal: null }; } async stop() { return { mode: 'stdin-close' as const, code: 0, signal: null }; }
} }
@@ -120,6 +124,7 @@ describe('managed Pi worker opener', () => {
updatedAt: NOW, updatedAt: NOW,
}; };
const processOptions: PiWorkerProcessOptions[] = []; const processOptions: PiWorkerProcessOptions[] = [];
const processes: OpenerFakeProcess[] = [];
const telemetry: PiRuntimeTelemetryEvent[] = []; const telemetry: PiRuntimeTelemetryEvent[] = [];
const registry = new PiSessionRegistry({ projectStore }); const registry = new PiSessionRegistry({ projectStore });
const extensionHost = new PiManagedExtensionHost(); const extensionHost = new PiManagedExtensionHost();
@@ -140,7 +145,9 @@ describe('managed Pi worker opener', () => {
createProcess: (options) => { createProcess: (options) => {
processOptions.push(options); processOptions.push(options);
const sessionIndex = options.additionalArgs?.indexOf('--session-id') ?? -1; const sessionIndex = options.additionalArgs?.indexOf('--session-id') ?? -1;
return new OpenerFakeProcess(options.additionalArgs?.[sessionIndex + 1] ?? '', options); const process = new OpenerFakeProcess(options.additionalArgs?.[sessionIndex + 1] ?? '', options);
processes.push(process);
return process;
}, },
}); });
const opener = createOpener(registry); const opener = createOpener(registry);
@@ -200,6 +207,9 @@ describe('managed Pi worker opener', () => {
expect(JSON.stringify(telemetry)).not.toContain(created.id); expect(JSON.stringify(telemetry)).not.toContain(created.id);
expect(JSON.stringify(telemetry)).not.toContain('PRIVATE MANAGED PROMPT'); expect(JSON.stringify(telemetry)).not.toContain('PRIVATE MANAGED PROMPT');
expect(JSON.stringify(telemetry)).not.toContain('provider-secret-value'); expect(JSON.stringify(telemetry)).not.toContain('provider-secret-value');
expect(first.worker.delayNextResponseForProof).toBeTypeOf('function');
first.worker.delayNextResponseForProof?.('prompt', 12_000);
expect(processes[0]?.proofResponseDelays).toEqual([{ commandType: 'prompt', delayMs: 12_000 }]);
await first.worker.stop('test_injection'); await first.worker.stop('test_injection');
await reopened.worker.stop('test_injection'); await reopened.worker.stop('test_injection');
await restarted.worker.stop('test_injection'); await restarted.worker.stop('test_injection');