Skip to content

Commit 825ca7b

Browse files
committed
Fragments: soft-track the originId for multi-origin fragments in messages
1 parent 5c2a8a4 commit 825ca7b

1 file changed

Lines changed: 25 additions & 9 deletions

File tree

src/common/stores/chat/chat.fragments.ts

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ type _DMessageFragmentWrapper<TFragment, TPart extends { pt: string }> = {
8282
ft: TFragment;
8383
fId: DMessageFragmentId;
8484
part: TPart;
85+
originId?: string; // optional, for multi-model, identifies which actor produced this fragment
8586
}
8687

8788

@@ -362,6 +363,9 @@ export function duplicateDMessageFragments(fragments: Readonly<DMessageFragment[
362363
: fragments.map(_duplicateFragment).filter(f => f.ft !== 'void');
363364
}
364365

366+
/**
367+
* NOTE: a duplicate fragment gets a new ID, and also loses any originId, if set (not sure why, but it's the way it is now)
368+
*/
365369
function _duplicateFragment(fragment: DMessageFragment): DMessageFragment {
366370
switch (fragment.ft) {
367371
case 'content':
@@ -554,6 +558,16 @@ function _duplicate_DataReference(ref: DMessageDataRef): DMessageDataRef {
554558

555559
/// Editor Helpers - Fragment Editing
556560

561+
/** Creates a new array of fragments with a specific originId assigned to each. */
562+
export function fragmentsSetOriginId(fragments: ReadonlyArray<Readonly<DMessageFragment>>, originId: string): Readonly<DMessageFragment>[] {
563+
564+
// shallow copy if empty or no originId
565+
if (!fragments.length || !originId) return [...fragments];
566+
567+
// shallow-copy + set origin
568+
return fragments.map(fragment => ({ ...fragment, originId: originId }));
569+
}
570+
557571
export function splitFragmentsByType(fragments: DMessageFragment[]) {
558572
// also see `useFragmentBuckets.ts` which inspired this function
559573
return fragments.reduce((acc, frag) => {
@@ -596,15 +610,16 @@ export function updateFragmentWithEditedText(
596610
// }
597611

598612
if (isContentFragment(fragment)) {
599-
const { fId, part } = fragment;
613+
const { fId, part, originId } = fragment;
614+
const preserveId = { fId, ...(originId && { originId }) } as const;
600615

601616
if (isTextPart(part)) {
602617
// Create a new text content fragment with the same fId and the edited text
603618
const newFragment = createTextContentFragment(editedText);
604-
return { ...newFragment, fId }; // Preserve original fId
619+
return { ...newFragment, ...preserveId };
605620
} else if (part.pt === 'error') {
606621
const newFragment = createErrorContentFragment(editedText);
607-
return { ...newFragment, fId }; // Preserve original fId
622+
return { ...newFragment, ...preserveId };
608623
} else if (part.pt === 'tool_invocation') {
609624
if (part.invocation.type === 'function_call') {
610625
// Create a new tool invocation fragment with the edited args
@@ -613,15 +628,15 @@ export function updateFragmentWithEditedText(
613628
part.invocation.name,
614629
editedText, // args (if empty, it calls the funciton without params)
615630
);
616-
return { ...newFragment, fId }; // Preserve original fId
631+
return { ...newFragment, ...preserveId };
617632
} else if (part.invocation.type === 'code_execution') {
618633
const newFragment = create_CodeExecutionInvocation_ContentFragment(
619634
part.id, // Keep same id
620635
part.invocation.language,
621636
editedText, // code
622637
part.invocation.author,
623638
);
624-
return { ...newFragment, fId };
639+
return { ...newFragment, ...preserveId };
625640
}
626641
} else if (part.pt === 'tool_response') {
627642
if (part.error) {
@@ -642,7 +657,7 @@ export function updateFragmentWithEditedText(
642657
editedText, // result
643658
part.environment,
644659
);
645-
return { ...newFragment, fId };
660+
return { ...newFragment, ...preserveId };
646661
} else if (response.type === 'code_execution') {
647662
const newFragment = create_CodeExecutionResponse_ContentFragment(
648663
part.id,
@@ -651,12 +666,13 @@ export function updateFragmentWithEditedText(
651666
response.executor,
652667
part.environment,
653668
);
654-
return { ...newFragment, fId };
669+
return { ...newFragment, ...preserveId };
655670
}
656671
}
657672
}
658673
} else if (isAttachmentFragment(fragment)) {
659-
const { fId, part, title, caption, liveFileId } = fragment;
674+
const { fId, part, title, caption, liveFileId, originId } = fragment;
675+
const preserveId = { fId, ...(originId && { originId }) } as const;
660676

661677
if (isDocPart(part)) {
662678
// Create a new doc attachment fragment with the edited text
@@ -674,7 +690,7 @@ export function updateFragmentWithEditedText(
674690
part.meta,
675691
liveFileId,
676692
);
677-
return { ...newFragment, fId }; // Preserve original fId
693+
return { ...newFragment, ...preserveId };
678694
}
679695
// Handle other attachment parts if needed
680696
}

0 commit comments

Comments
 (0)