fix(pi): validate user-entry conversation forks

This commit is contained in:
2026-08-25 17:48:31 +08:00
parent 941b015330
commit 8ba2a6055c
10 changed files with 767 additions and 13 deletions

View File

@@ -491,7 +491,27 @@ export class CodingConversationService {
}
async fork(sourceConversationId: string, sourceEntryId?: string): Promise<CodingConversationV2> {
const entryId = requiredString(sourceEntryId, 'Fork source entry id', 256);
const prepared = await this.ensurePrepared(sourceConversationId);
let sourceSnapshot: ConversationSnapshot;
try {
sourceSnapshot = await this.runtime.getSnapshot(sourceConversationId);
} catch (error) {
runtimeError(error);
}
const sourceNode = sourceSnapshot.nodes.find((node) => (
node.kind === 'message'
&& node.sourceEntryId === entryId
&& node.role === 'user'
&& node.status !== 'optimistic'
));
if (!sourceNode) {
throw new CodingConversationServiceError(
400,
'CODING_CONVERSATION_REQUEST_INVALID',
'Fork source must be a durable user message on the active Conversation path',
);
}
const source = await this.projects.findActiveConversation(sourceConversationId);
const store = this.projects.conversationStore(source.project.path);
const created = await persist(() => store.create({
@@ -503,7 +523,7 @@ export class CodingConversationService {
try {
await this.runtime.fork({
sourceConversationId,
...(sourceEntryId ? { sourceEntryId } : {}),
sourceEntryId: entryId,
conversation: {
...prepared,
conversationId: created.id,