fix(coding): recover provider context failures

This commit is contained in:
2026-08-26 14:42:01 +08:00
parent 9f05e2d7e1
commit a09826676e
8 changed files with 349 additions and 9 deletions

View File

@@ -30,6 +30,7 @@ import {
import type {
ConversationSnapshot,
ConversationPatchEnvelope,
PrepareConversationInput,
PromptConversationInput,
} from '../../electron/coding-runtime/contracts';
import { archivePiConversationSession } from '../../electron/coding-runtime/pi/resource-loader';
@@ -175,7 +176,22 @@ describe('PI-100 coding core Host contract', () => {
mission: 'Implement', owns: [], boundaries: [], collaborators: [], principles: [],
},
});
const runtime = new InMemoryConversationRuntime();
class StrictResolvedModelRuntime extends InMemoryConversationRuntime {
readonly prepareInputs: PrepareConversationInput[] = [];
override async prepare(input: PrepareConversationInput) {
this.prepareInputs.push(structuredClone(input));
if (input.model.modelResolution !== 'resolved' || !input.model.model) {
throw new CodingRuntimeContractError(
'CODING_MIGRATION_MODEL_REQUIRED',
'A resolved model is required before preparation',
true,
);
}
return await super.prepare(input);
}
}
const runtime = new StrictResolvedModelRuntime();
const projects = new CodingProjectService(store);
const conversations = new CodingConversationService(projects, runtime);
const conversation = await conversations.createConversation({ agentId: 'builder', title: 'Resolve me' });
@@ -189,6 +205,10 @@ describe('PI-100 coding core Host contract', () => {
conversationId: conversation.id,
model: { model: MODEL, modelResolution: 'resolved' },
}));
expect(runtime.prepareInputs).toHaveLength(1);
expect(runtime.prepareInputs.every(({ model }) => (
model.modelResolution === 'resolved' && model.model !== null
))).toBe(true);
await expect(projects.conversationStore(root).get(conversation.id)).resolves.toMatchObject({
model: MODEL,
modelResolution: 'resolved',