fix(coding-runtime): close Pi extension lifecycle races
This commit is contained in:
@@ -14,6 +14,7 @@ import {
|
||||
import { PiConversationRuntime } from '../../electron/coding-runtime/pi/runtime';
|
||||
import { PiSessionProjectionError } from '../../electron/coding-runtime/pi/session-projector';
|
||||
import { PiSessionRegistry } from '../../electron/coding-runtime/pi/session-registry';
|
||||
import { PiManagedExtensionHost } from '../../electron/coding-runtime/pi/extension-host';
|
||||
import {
|
||||
PiWorkerPool,
|
||||
type PiConversationWorker,
|
||||
@@ -114,6 +115,18 @@ class RuntimeFakeWorker implements PiConversationWorker {
|
||||
}
|
||||
}
|
||||
|
||||
class TrackingExtensionHost extends PiManagedExtensionHost {
|
||||
readonly runs = new Map<string, { generation: number; runId: string }>();
|
||||
|
||||
override async bindRun(conversationId: string, generation: number, runId: string): Promise<void> {
|
||||
this.runs.set(conversationId, { generation, runId });
|
||||
}
|
||||
|
||||
override async clearRun(conversationId: string, _generation: number, runId?: string): Promise<void> {
|
||||
if (!runId || this.runs.get(conversationId)?.runId === runId) this.runs.delete(conversationId);
|
||||
}
|
||||
}
|
||||
|
||||
afterEach(async () => {
|
||||
await Promise.all(roots.splice(0).map((root) => rm(root, { recursive: true, force: true })));
|
||||
});
|
||||
@@ -189,10 +202,12 @@ describe('Pi Conversation runtime', () => {
|
||||
};
|
||||
},
|
||||
});
|
||||
const trackingHost = new TrackingExtensionHost();
|
||||
const runtime = new PiConversationRuntime({
|
||||
pool,
|
||||
registry: new PiSessionRegistry({ projectStore }),
|
||||
createId: (kind) => `${kind}-fixed`,
|
||||
extensionHost: trackingHost,
|
||||
resolveModel: async (candidate) => {
|
||||
if (candidate.accountId !== 'account-b' || candidate.modelId !== 'model-b') {
|
||||
throw new Error('model unavailable');
|
||||
@@ -483,6 +498,17 @@ describe('Pi Conversation runtime', () => {
|
||||
await expect(runtime.getSnapshot(forkTarget.id)).rejects.toMatchObject({
|
||||
publicError: { code: 'CODING_CONVERSATION_NOT_FOUND' },
|
||||
});
|
||||
await runtime.prompt({
|
||||
clientRequestId: 'request-active-recover',
|
||||
conversationId: left.id,
|
||||
mode: 'prompt',
|
||||
text: 'Recover this active run',
|
||||
attachments: [],
|
||||
});
|
||||
expect(trackingHost.runs.get(left.id)?.runId).toBe('run-fixed');
|
||||
await runtime.recover(left.id);
|
||||
expect(trackingHost.runs.has(left.id)).toBe(false);
|
||||
expect((await runtime.getSnapshot(left.id)).run).toEqual({ status: 'idle' });
|
||||
unsubscribe();
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user