fix(coding): close PI-100 review findings

This commit is contained in:
2026-08-23 20:55:49 +08:00
parent 22b4a9f9c4
commit 52b2467d5d
16 changed files with 679 additions and 122 deletions

View File

@@ -672,6 +672,15 @@ export class PiConversationRuntime implements CodingConversationRuntime {
}
}
async validateModel(model: ProductModelRef): Promise<ProductModelRef> {
const selection = await this.resolveModel(model);
return {
accountId: selection.accountId,
modelId: selection.modelId,
thinkingLevel: model.thinkingLevel,
};
}
async setModel(input: SetConversationModelInput): Promise<ConversationModelState> {
await this.waitForProjection(input.conversationId);
const snapshot = this.snapshot(input.conversationId);
@@ -957,19 +966,30 @@ export class PiConversationRuntime implements CodingConversationRuntime {
if (!this.isAuthenticationError || !this.refreshCredential || !input.model.model) {
return await this.pool.prepare(input);
}
return await this.providerRefresh.withSingleAuthRecovery({
accountId: input.model.model.accountId,
operation: async () => await this.pool.prepare(input),
isAuthenticationError: this.isAuthenticationError,
refreshCredential: async () => await this.refreshCredential!(input.model.model!.accountId),
reopenWorker: async () => {
if (!this.pool.getState(input.conversationId)) return;
const recovered = await this.pool.recover(input.conversationId);
if (this.states.has(input.conversationId)) {
await this.requestHydration(input.conversationId, recovered, false);
}
},
});
try {
return await this.providerRefresh.withSingleAuthRecovery({
accountId: input.model.model.accountId,
operation: async () => await this.pool.prepare(input),
isAuthenticationError: this.isAuthenticationError,
refreshCredential: async () => await this.refreshCredential!(input.model.model!.accountId),
reopenWorker: async () => {
if (!this.pool.getState(input.conversationId)) return;
const recovered = await this.pool.recover(input.conversationId);
if (this.states.has(input.conversationId)) {
await this.requestHydration(input.conversationId, recovered, false);
}
},
});
} catch (error) {
if (this.isAuthenticationError(error)) {
throw new CodingRuntimeContractError(
'CODING_PROVIDER_AUTH_REQUIRED',
'Provider authentication failed after one recovery attempt',
true,
);
}
throw error;
}
}
private async acceptPrompt(
@@ -1008,13 +1028,20 @@ export class PiConversationRuntime implements CodingConversationRuntime {
}, runId);
}
} catch (error) {
const failure = this.isAuthenticationError?.(error)
? new CodingRuntimeContractError(
'CODING_PROVIDER_AUTH_REQUIRED',
'Provider authentication failed after one recovery attempt',
true,
)
: error;
this.pool.failTopLevel(
conversationId,
runId,
error instanceof Error ? error : new Error('Prompt acceptance failed'),
failure instanceof Error ? failure : new Error('Prompt acceptance failed'),
);
this.failRun(conversationId, runId, error);
throw error;
this.failRun(conversationId, runId, failure);
throw failure;
}
}