@assistant-ui/core 0.2.12 → 0.2.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapters/thread-history.d.ts +3 -1
- package/dist/adapters/thread-history.d.ts.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js.map +1 -1
- package/dist/react/AssistantProvider.js +6 -1
- package/dist/react/AssistantProvider.js.map +1 -1
- package/dist/react/RuntimeAdapter.d.ts +1 -1
- package/dist/react/RuntimeAdapter.d.ts.map +1 -1
- package/dist/react/RuntimeAdapter.js +16 -6
- package/dist/react/RuntimeAdapter.js.map +1 -1
- package/dist/react/client/DataRenderers.d.ts +1 -8
- package/dist/react/client/DataRenderers.d.ts.map +1 -1
- package/dist/react/client/DataRenderers.js +3 -2
- package/dist/react/client/DataRenderers.js.map +1 -1
- package/dist/react/client/Interactables.d.ts +1 -1
- package/dist/react/client/Interactables.d.ts.map +1 -1
- package/dist/react/client/Interactables.js +4 -3
- package/dist/react/client/Interactables.js.map +1 -1
- package/dist/react/client/Tools.d.ts +2 -13
- package/dist/react/client/Tools.d.ts.map +1 -1
- package/dist/react/client/Tools.js +4 -3
- package/dist/react/client/Tools.js.map +1 -1
- package/dist/react/primitives/message/MessageGroupedParts.d.ts +3 -2
- package/dist/react/primitives/message/MessageGroupedParts.d.ts.map +1 -1
- package/dist/react/primitives/message/MessageGroupedParts.js +4 -4
- package/dist/react/primitives/message/MessageGroupedParts.js.map +1 -1
- package/dist/react/primitives/message/MessageParts.d.ts +28 -1
- package/dist/react/primitives/message/MessageParts.d.ts.map +1 -1
- package/dist/react/primitives/message/MessageParts.js +43 -9
- package/dist/react/primitives/message/MessageParts.js.map +1 -1
- package/dist/react/providers/TextMessagePartProvider.d.ts.map +1 -1
- package/dist/react/providers/TextMessagePartProvider.js +3 -2
- package/dist/react/providers/TextMessagePartProvider.js.map +1 -1
- package/dist/react/runtimes/RemoteThreadListHookInstanceManager.d.ts +2 -0
- package/dist/react/runtimes/RemoteThreadListHookInstanceManager.d.ts.map +1 -1
- package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts +2 -0
- package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts.map +1 -1
- package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js +1 -0
- package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js.map +1 -1
- package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.d.ts.map +1 -1
- package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.js +6 -0
- package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.js.map +1 -1
- package/dist/react/runtimes/cloud/useCloudThreadListAdapter.d.ts.map +1 -1
- package/dist/react/runtimes/cloud/useCloudThreadListAdapter.js +2 -0
- package/dist/react/runtimes/cloud/useCloudThreadListAdapter.js.map +1 -1
- package/dist/react/utils/groupParts.d.ts +13 -1
- package/dist/react/utils/groupParts.d.ts.map +1 -1
- package/dist/react/utils/groupParts.js +17 -5
- package/dist/react/utils/groupParts.js.map +1 -1
- package/dist/runtime/api/bindings.d.ts +1 -0
- package/dist/runtime/api/bindings.d.ts.map +1 -1
- package/dist/runtime/api/message-runtime.d.ts +2 -0
- package/dist/runtime/api/message-runtime.d.ts.map +1 -1
- package/dist/runtime/api/message-runtime.js +5 -0
- package/dist/runtime/api/message-runtime.js.map +1 -1
- package/dist/runtime/api/thread-list-runtime.d.ts.map +1 -1
- package/dist/runtime/api/thread-list-runtime.js +1 -0
- package/dist/runtime/api/thread-list-runtime.js.map +1 -1
- package/dist/runtime/api/thread-runtime.d.ts +3 -0
- package/dist/runtime/api/thread-runtime.d.ts.map +1 -1
- package/dist/runtime/api/thread-runtime.js +4 -0
- package/dist/runtime/api/thread-runtime.js.map +1 -1
- package/dist/runtime/base/base-thread-runtime-core.d.ts +1 -0
- package/dist/runtime/base/base-thread-runtime-core.d.ts.map +1 -1
- package/dist/runtime/base/base-thread-runtime-core.js.map +1 -1
- package/dist/runtime/branch/external-thread-branch-adapter.d.ts +30 -0
- package/dist/runtime/branch/external-thread-branch-adapter.d.ts.map +1 -0
- package/dist/runtime/branch/external-thread-branch-adapter.js +0 -0
- package/dist/runtime/interfaces/thread-list-runtime-core.d.ts +1 -0
- package/dist/runtime/interfaces/thread-list-runtime-core.d.ts.map +1 -1
- package/dist/runtime/interfaces/thread-runtime-core.d.ts +2 -0
- package/dist/runtime/interfaces/thread-runtime-core.d.ts.map +1 -1
- package/dist/runtimes/external-store/external-store-adapter.d.ts +1 -0
- package/dist/runtimes/external-store/external-store-adapter.d.ts.map +1 -1
- package/dist/runtimes/external-store/external-store-thread-runtime-core.d.ts +1 -0
- package/dist/runtimes/external-store/external-store-thread-runtime-core.d.ts.map +1 -1
- package/dist/runtimes/external-store/external-store-thread-runtime-core.js +13 -0
- package/dist/runtimes/external-store/external-store-thread-runtime-core.js.map +1 -1
- package/dist/runtimes/local/local-runtime-options.d.ts +1 -1
- package/dist/runtimes/local/local-thread-runtime-core.d.ts +8 -1
- package/dist/runtimes/local/local-thread-runtime-core.d.ts.map +1 -1
- package/dist/runtimes/local/local-thread-runtime-core.js +63 -5
- package/dist/runtimes/local/local-thread-runtime-core.js.map +1 -1
- package/dist/runtimes/local/should-continue.js +4 -2
- package/dist/runtimes/local/should-continue.js.map +1 -1
- package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.d.ts +2 -0
- package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.d.ts.map +1 -1
- package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.js +4 -0
- package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.js.map +1 -1
- package/dist/runtimes/remote-thread-list/empty-thread-core.d.ts.map +1 -1
- package/dist/runtimes/remote-thread-list/empty-thread-core.js +4 -0
- package/dist/runtimes/remote-thread-list/empty-thread-core.js.map +1 -1
- package/dist/runtimes/remote-thread-list/remote-thread-state.d.ts +1 -0
- package/dist/runtimes/remote-thread-list/remote-thread-state.d.ts.map +1 -1
- package/dist/runtimes/remote-thread-list/remote-thread-state.js +1 -0
- package/dist/runtimes/remote-thread-list/remote-thread-state.js.map +1 -1
- package/dist/runtimes/remote-thread-list/types.d.ts +1 -0
- package/dist/runtimes/remote-thread-list/types.d.ts.map +1 -1
- package/dist/store/clients/chain-of-thought-client.d.ts +2 -7
- package/dist/store/clients/chain-of-thought-client.d.ts.map +1 -1
- package/dist/store/clients/chain-of-thought-client.js +3 -2
- package/dist/store/clients/chain-of-thought-client.js.map +1 -1
- package/dist/store/clients/model-context-client.d.ts +1 -1
- package/dist/store/clients/model-context-client.d.ts.map +1 -1
- package/dist/store/clients/model-context-client.js +3 -2
- package/dist/store/clients/model-context-client.js.map +1 -1
- package/dist/store/clients/no-op-composer-client.d.ts +2 -4
- package/dist/store/clients/no-op-composer-client.d.ts.map +1 -1
- package/dist/store/clients/no-op-composer-client.js +3 -2
- package/dist/store/clients/no-op-composer-client.js.map +1 -1
- package/dist/store/clients/runtime-adapter.d.ts +1 -3
- package/dist/store/clients/runtime-adapter.d.ts.map +1 -1
- package/dist/store/clients/runtime-adapter.js +2 -15
- package/dist/store/clients/runtime-adapter.js.map +1 -1
- package/dist/store/clients/suggestions.d.ts +1 -4
- package/dist/store/clients/suggestions.d.ts.map +1 -1
- package/dist/store/clients/suggestions.js +6 -4
- package/dist/store/clients/suggestions.js.map +1 -1
- package/dist/store/clients/thread-message-client.d.ts +1 -1
- package/dist/store/clients/thread-message-client.d.ts.map +1 -1
- package/dist/store/clients/thread-message-client.js +14 -10
- package/dist/store/clients/thread-message-client.js.map +1 -1
- package/dist/store/internal.d.ts +2 -2
- package/dist/store/internal.js +2 -2
- package/dist/store/runtime-clients/attachment-runtime-client.d.ts +2 -4
- package/dist/store/runtime-clients/attachment-runtime-client.d.ts.map +1 -1
- package/dist/store/runtime-clients/attachment-runtime-client.js +3 -2
- package/dist/store/runtime-clients/attachment-runtime-client.js.map +1 -1
- package/dist/store/runtime-clients/composer-runtime-client.d.ts +2 -10
- package/dist/store/runtime-clients/composer-runtime-client.d.ts.map +1 -1
- package/dist/store/runtime-clients/composer-runtime-client.js +9 -6
- package/dist/store/runtime-clients/composer-runtime-client.js.map +1 -1
- package/dist/store/runtime-clients/message-part-runtime-client.d.ts +2 -4
- package/dist/store/runtime-clients/message-part-runtime-client.d.ts.map +1 -1
- package/dist/store/runtime-clients/message-part-runtime-client.js +3 -2
- package/dist/store/runtime-clients/message-part-runtime-client.js.map +1 -1
- package/dist/store/runtime-clients/message-runtime-client.d.ts +2 -7
- package/dist/store/runtime-clients/message-runtime-client.d.ts.map +1 -1
- package/dist/store/runtime-clients/message-runtime-client.js +10 -6
- package/dist/store/runtime-clients/message-runtime-client.js.map +1 -1
- package/dist/store/runtime-clients/thread-list-item-runtime-client.d.ts +2 -4
- package/dist/store/runtime-clients/thread-list-item-runtime-client.d.ts.map +1 -1
- package/dist/store/runtime-clients/thread-list-item-runtime-client.js +3 -2
- package/dist/store/runtime-clients/thread-list-item-runtime-client.js.map +1 -1
- package/dist/store/runtime-clients/thread-list-runtime-client.d.ts +2 -5
- package/dist/store/runtime-clients/thread-list-runtime-client.d.ts.map +1 -1
- package/dist/store/runtime-clients/thread-list-runtime-client.js +6 -4
- package/dist/store/runtime-clients/thread-list-runtime-client.js.map +1 -1
- package/dist/store/runtime-clients/thread-runtime-client.d.ts +2 -4
- package/dist/store/runtime-clients/thread-runtime-client.d.ts.map +1 -1
- package/dist/store/runtime-clients/thread-runtime-client.js +7 -4
- package/dist/store/runtime-clients/thread-runtime-client.js.map +1 -1
- package/dist/store/scopes/message.d.ts +1 -0
- package/dist/store/scopes/message.d.ts.map +1 -1
- package/dist/store/scopes/thread-list-item.d.ts +1 -0
- package/dist/store/scopes/thread-list-item.d.ts.map +1 -1
- package/dist/store/scopes/thread.d.ts +1 -0
- package/dist/store/scopes/thread.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/adapters/thread-history.ts +2 -0
- package/src/index.ts +1 -0
- package/src/react/AssistantProvider.tsx +3 -1
- package/src/react/RuntimeAdapter.ts +25 -8
- package/src/react/client/DataRenderers.ts +42 -45
- package/src/react/client/Interactables.ts +261 -261
- package/src/react/client/Tools.ts +6 -4
- package/src/react/primitives/message/MessageGroupedParts.tsx +19 -7
- package/src/react/primitives/message/MessageParts.tsx +64 -13
- package/src/react/providers/TextMessagePartProvider.tsx +5 -3
- package/src/react/runtimes/RemoteThreadListThreadListRuntimeCore.tsx +1 -0
- package/src/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.ts +11 -0
- package/src/react/runtimes/cloud/useCloudThreadListAdapter.tsx +6 -0
- package/src/react/utils/groupParts.ts +27 -0
- package/src/runtime/api/bindings.ts +1 -0
- package/src/runtime/api/message-runtime.ts +7 -0
- package/src/runtime/api/thread-list-runtime.ts +1 -0
- package/src/runtime/api/thread-runtime.ts +7 -0
- package/src/runtime/base/base-thread-runtime-core.ts +1 -0
- package/src/runtime/branch/external-thread-branch-adapter.ts +26 -0
- package/src/runtime/interfaces/thread-list-runtime-core.ts +1 -0
- package/src/runtime/interfaces/thread-runtime-core.ts +2 -0
- package/src/runtimes/external-store/external-store-adapter.ts +1 -0
- package/src/runtimes/external-store/external-store-thread-runtime-core.ts +24 -0
- package/src/runtimes/local/local-runtime-options.ts +1 -1
- package/src/runtimes/local/local-thread-runtime-core.test.ts +311 -0
- package/src/runtimes/local/local-thread-runtime-core.ts +104 -7
- package/src/runtimes/local/should-continue.ts +23 -13
- package/src/runtimes/readonly/ReadonlyThreadRuntimeCore.ts +5 -0
- package/src/runtimes/remote-thread-list/empty-thread-core.ts +5 -0
- package/src/runtimes/remote-thread-list/remote-thread-state.ts +2 -0
- package/src/runtimes/remote-thread-list/types.ts +1 -0
- package/src/store/clients/chain-of-thought-client.ts +5 -3
- package/src/store/clients/model-context-client.test.ts +5 -4
- package/src/store/clients/model-context-client.ts +21 -21
- package/src/store/clients/no-op-composer-client.ts +5 -3
- package/src/store/clients/runtime-adapter.ts +0 -24
- package/src/store/clients/suggestions.ts +9 -18
- package/src/store/clients/thread-message-client.ts +29 -26
- package/src/store/internal.ts +1 -4
- package/src/store/runtime-clients/attachment-runtime-client.ts +14 -14
- package/src/store/runtime-clients/composer-runtime-client.ts +30 -24
- package/src/store/runtime-clients/message-part-runtime-client.ts +5 -3
- package/src/store/runtime-clients/message-runtime-client.ts +26 -19
- package/src/store/runtime-clients/thread-list-item-runtime-client.ts +5 -3
- package/src/store/runtime-clients/thread-list-runtime-client.ts +10 -6
- package/src/store/runtime-clients/thread-runtime-client.ts +11 -6
- package/src/store/scopes/message.ts +1 -0
- package/src/store/scopes/thread-list-item.ts +1 -0
- package/src/store/scopes/thread.ts +1 -0
- package/src/tests/external-store-thread-runtime-core.test.ts +57 -0
- package/src/tests/groupMessageParts.test.ts +84 -0
- package/src/tests/groupParts.test.ts +55 -0
|
@@ -44,9 +44,24 @@ import { useShallow } from "zustand/shallow";
|
|
|
44
44
|
|
|
45
45
|
type MessagePartRange =
|
|
46
46
|
| { type: "single"; index: number }
|
|
47
|
-
| {
|
|
48
|
-
|
|
49
|
-
|
|
47
|
+
| {
|
|
48
|
+
type: "toolGroup";
|
|
49
|
+
startIndex: number;
|
|
50
|
+
endIndex: number;
|
|
51
|
+
idKey?: string | undefined;
|
|
52
|
+
}
|
|
53
|
+
| {
|
|
54
|
+
type: "reasoningGroup";
|
|
55
|
+
startIndex: number;
|
|
56
|
+
endIndex: number;
|
|
57
|
+
idKey?: string | undefined;
|
|
58
|
+
}
|
|
59
|
+
| {
|
|
60
|
+
type: "chainOfThoughtGroup";
|
|
61
|
+
startIndex: number;
|
|
62
|
+
endIndex: number;
|
|
63
|
+
idKey?: string | undefined;
|
|
64
|
+
};
|
|
50
65
|
|
|
51
66
|
/**
|
|
52
67
|
* Creates a group state manager for a specific part type.
|
|
@@ -91,10 +106,13 @@ const createGroupState = <
|
|
|
91
106
|
* Groups consecutive tool-call and reasoning message parts into ranges.
|
|
92
107
|
* Always groups tool calls and reasoning parts, even if there's only one.
|
|
93
108
|
* When useChainOfThought is true, groups tool-call and reasoning parts together.
|
|
109
|
+
* `partIds[i]` optionally carries a stable identity for part `i`; group
|
|
110
|
+
* ranges derive an `idKey` from their first part's id (first claim wins).
|
|
94
111
|
*/
|
|
95
|
-
const groupMessageParts = (
|
|
112
|
+
export const groupMessageParts = (
|
|
96
113
|
messageTypes: readonly string[],
|
|
97
114
|
useChainOfThought: boolean,
|
|
115
|
+
partIds?: readonly (string | undefined)[],
|
|
98
116
|
): MessagePartRange[] => {
|
|
99
117
|
const ranges: MessagePartRange[] = [];
|
|
100
118
|
|
|
@@ -137,22 +155,44 @@ const groupMessageParts = (
|
|
|
137
155
|
reasoningGroup.finalize(messageTypes.length - 1, ranges);
|
|
138
156
|
}
|
|
139
157
|
|
|
158
|
+
if (partIds) {
|
|
159
|
+
const claimed = new Set<string>();
|
|
160
|
+
for (const range of ranges) {
|
|
161
|
+
if (range.type === "single") continue;
|
|
162
|
+
const id = partIds[range.startIndex];
|
|
163
|
+
if (id !== undefined && !claimed.has(id)) {
|
|
164
|
+
claimed.add(id);
|
|
165
|
+
range.idKey = `id:${id}`;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
140
170
|
return ranges;
|
|
141
171
|
};
|
|
142
172
|
|
|
143
173
|
const useMessagePartsGroups = (
|
|
144
174
|
useChainOfThought: boolean,
|
|
145
|
-
): MessagePartRange[] => {
|
|
175
|
+
): { ranges: MessagePartRange[]; partIds: (string | undefined)[] } => {
|
|
146
176
|
const messageTypes = useAuiState(
|
|
147
177
|
useShallow((s) => s.message.parts.map((c: any) => c.type)),
|
|
148
178
|
);
|
|
179
|
+
const partIds = useAuiState(
|
|
180
|
+
useShallow((s) =>
|
|
181
|
+
s.message.parts.map((c: any) =>
|
|
182
|
+
c.type === "tool-call" ? c.toolCallId : undefined,
|
|
183
|
+
),
|
|
184
|
+
),
|
|
185
|
+
);
|
|
149
186
|
|
|
150
187
|
return useMemo(() => {
|
|
151
188
|
if (messageTypes.length === 0) {
|
|
152
|
-
return [];
|
|
189
|
+
return { ranges: [], partIds };
|
|
153
190
|
}
|
|
154
|
-
return
|
|
155
|
-
|
|
191
|
+
return {
|
|
192
|
+
ranges: groupMessageParts(messageTypes, useChainOfThought, partIds),
|
|
193
|
+
partIds,
|
|
194
|
+
};
|
|
195
|
+
}, [messageTypes, partIds, useChainOfThought]);
|
|
156
196
|
};
|
|
157
197
|
|
|
158
198
|
export namespace MessagePrimitiveParts {
|
|
@@ -795,13 +835,24 @@ const MessagePrimitivePartsCompat: FC<{
|
|
|
795
835
|
}> = ({ components, unstable_showEmptyOnNonTextEnd }) => {
|
|
796
836
|
const contentLength = useAuiState((s) => s.message.parts.length);
|
|
797
837
|
const useChainOfThought = !!components?.ChainOfThought;
|
|
798
|
-
const messageRanges =
|
|
838
|
+
const { ranges: messageRanges, partIds } =
|
|
839
|
+
useMessagePartsGroups(useChainOfThought);
|
|
799
840
|
|
|
800
841
|
const partsElements = useMemo(() => {
|
|
801
842
|
if (contentLength === 0) {
|
|
802
843
|
return <EmptyParts components={components} />;
|
|
803
844
|
}
|
|
804
845
|
|
|
846
|
+
const claimed = new Set<string>();
|
|
847
|
+
const toolLeafKey = (partIndex: number) => {
|
|
848
|
+
const id = partIds[partIndex];
|
|
849
|
+
if (id !== undefined && !claimed.has(id)) {
|
|
850
|
+
claimed.add(id);
|
|
851
|
+
return `part-id:${id}`;
|
|
852
|
+
}
|
|
853
|
+
return `part-${partIndex}`;
|
|
854
|
+
};
|
|
855
|
+
|
|
805
856
|
return messageRanges.map((range) => {
|
|
806
857
|
if (range.type === "single") {
|
|
807
858
|
return (
|
|
@@ -816,7 +867,7 @@ const MessagePrimitivePartsCompat: FC<{
|
|
|
816
867
|
if (!ChainOfThoughtComponent) return null;
|
|
817
868
|
return (
|
|
818
869
|
<ChainOfThoughtByIndicesProvider
|
|
819
|
-
key={`chainOfThought-${range.startIndex}`}
|
|
870
|
+
key={`chainOfThought-${range.idKey ?? range.startIndex}`}
|
|
820
871
|
startIndex={range.startIndex}
|
|
821
872
|
endIndex={range.endIndex}
|
|
822
873
|
>
|
|
@@ -828,7 +879,7 @@ const MessagePrimitivePartsCompat: FC<{
|
|
|
828
879
|
components?.ToolGroup ?? defaultComponents.ToolGroup;
|
|
829
880
|
return (
|
|
830
881
|
<ToolGroupComponent
|
|
831
|
-
key={`tool-${range.startIndex}`}
|
|
882
|
+
key={`tool-${range.idKey ?? range.startIndex}`}
|
|
832
883
|
startIndex={range.startIndex}
|
|
833
884
|
endIndex={range.endIndex}
|
|
834
885
|
>
|
|
@@ -838,7 +889,7 @@ const MessagePrimitivePartsCompat: FC<{
|
|
|
838
889
|
const partIndex = range.startIndex + i;
|
|
839
890
|
return (
|
|
840
891
|
<MessagePrimitivePartByIndex
|
|
841
|
-
key={
|
|
892
|
+
key={toolLeafKey(partIndex)}
|
|
842
893
|
index={partIndex}
|
|
843
894
|
components={components}
|
|
844
895
|
/>
|
|
@@ -874,7 +925,7 @@ const MessagePrimitivePartsCompat: FC<{
|
|
|
874
925
|
);
|
|
875
926
|
}
|
|
876
927
|
});
|
|
877
|
-
}, [messageRanges, components, contentLength]);
|
|
928
|
+
}, [messageRanges, partIds, components, contentLength]);
|
|
878
929
|
|
|
879
930
|
return (
|
|
880
931
|
<>
|
|
@@ -4,13 +4,13 @@ import type { PartState } from "../../store/scopes/part";
|
|
|
4
4
|
|
|
5
5
|
import { resource } from "@assistant-ui/tap";
|
|
6
6
|
|
|
7
|
-
const
|
|
7
|
+
const useTextMessagePartClient = ({
|
|
8
8
|
text,
|
|
9
9
|
isRunning,
|
|
10
10
|
}: {
|
|
11
11
|
text: string;
|
|
12
12
|
isRunning: boolean;
|
|
13
|
-
}): ClientOutput<"part"> {
|
|
13
|
+
}): ClientOutput<"part"> => {
|
|
14
14
|
const state = useMemo<PartState>(
|
|
15
15
|
() => ({
|
|
16
16
|
type: "text",
|
|
@@ -32,7 +32,9 @@ const TextMessagePartClient = resource(function TextMessagePartClient({
|
|
|
32
32
|
throw new Error("Not supported");
|
|
33
33
|
},
|
|
34
34
|
};
|
|
35
|
-
}
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const TextMessagePartClient = resource(useTextMessagePartClient);
|
|
36
38
|
|
|
37
39
|
export const TextMessagePartProvider: FC<
|
|
38
40
|
PropsWithChildren<{
|
|
@@ -296,6 +296,7 @@ export class RemoteThreadListThreadListRuntimeCore
|
|
|
296
296
|
externalId: remoteMetadata.externalId,
|
|
297
297
|
status: remoteMetadata.status,
|
|
298
298
|
title: remoteMetadata.title,
|
|
299
|
+
lastMessageAt: remoteMetadata.lastMessageAt,
|
|
299
300
|
custom: remoteMetadata.custom,
|
|
300
301
|
} as RemoteThreadData,
|
|
301
302
|
};
|
|
@@ -57,6 +57,11 @@ class AssistantCloudThreadHistoryAdapter implements ThreadHistoryAdapter {
|
|
|
57
57
|
if (!remoteId) return;
|
|
58
58
|
await formatted.update?.(remoteId, item, localMessageId);
|
|
59
59
|
},
|
|
60
|
+
async delete() {
|
|
61
|
+
throw new Error(
|
|
62
|
+
"Assistant Cloud does not support deleting thread messages yet.",
|
|
63
|
+
);
|
|
64
|
+
},
|
|
60
65
|
reportTelemetry(
|
|
61
66
|
items: MessageFormatItem<TMessage>[],
|
|
62
67
|
options?: {
|
|
@@ -97,6 +102,12 @@ class AssistantCloudThreadHistoryAdapter implements ThreadHistoryAdapter {
|
|
|
97
102
|
}
|
|
98
103
|
}
|
|
99
104
|
|
|
105
|
+
async delete() {
|
|
106
|
+
throw new Error(
|
|
107
|
+
"Assistant Cloud does not support deleting thread messages yet.",
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
|
|
100
111
|
async load() {
|
|
101
112
|
const remoteId = this.aui.threadListItem().getState().remoteId;
|
|
102
113
|
if (!remoteId) return { messages: [] };
|
|
@@ -94,6 +94,9 @@ export const useCloudThreadListAdapter = (
|
|
|
94
94
|
status: t.is_archived ? "archived" : "regular",
|
|
95
95
|
remoteId: t.id,
|
|
96
96
|
title: t.title,
|
|
97
|
+
lastMessageAt: t.last_message_at
|
|
98
|
+
? new Date(t.last_message_at)
|
|
99
|
+
: undefined,
|
|
97
100
|
externalId: t.external_id ?? undefined,
|
|
98
101
|
custom: toCustom(t.metadata),
|
|
99
102
|
})),
|
|
@@ -153,6 +156,9 @@ export const useCloudThreadListAdapter = (
|
|
|
153
156
|
status: thread.is_archived ? "archived" : "regular",
|
|
154
157
|
remoteId: thread.id,
|
|
155
158
|
title: thread.title,
|
|
159
|
+
lastMessageAt: thread.last_message_at
|
|
160
|
+
? new Date(thread.last_message_at)
|
|
161
|
+
: undefined,
|
|
156
162
|
externalId: thread.external_id ?? undefined,
|
|
157
163
|
custom: toCustom(thread.metadata),
|
|
158
164
|
};
|
|
@@ -119,6 +119,11 @@ export interface GroupNodeGroup {
|
|
|
119
119
|
readonly key: string;
|
|
120
120
|
/** Structural React key: sibling-index path, e.g. `"0.1.0"`. */
|
|
121
121
|
readonly nodeKey: string;
|
|
122
|
+
/**
|
|
123
|
+
* Identity key (`"id:<partId>"`) from the group's first part; undefined
|
|
124
|
+
* when absent or already claimed by an earlier sibling.
|
|
125
|
+
*/
|
|
126
|
+
readonly idKey: string | undefined;
|
|
122
127
|
/** Indices of parts in this subtree, in order. */
|
|
123
128
|
readonly indices: readonly number[];
|
|
124
129
|
readonly children: readonly GroupNode[];
|
|
@@ -130,6 +135,11 @@ export interface GroupNodePart {
|
|
|
130
135
|
readonly index: number;
|
|
131
136
|
/** Structural React key: sibling-index path within parent. */
|
|
132
137
|
readonly nodeKey: string;
|
|
138
|
+
/**
|
|
139
|
+
* Identity key (`"id:<partId>"`); undefined when absent or already
|
|
140
|
+
* claimed by an earlier sibling.
|
|
141
|
+
*/
|
|
142
|
+
readonly idKey: string | undefined;
|
|
133
143
|
}
|
|
134
144
|
|
|
135
145
|
interface BuildFrame {
|
|
@@ -138,6 +148,7 @@ interface BuildFrame {
|
|
|
138
148
|
indices: number[];
|
|
139
149
|
children: GroupNode[];
|
|
140
150
|
nextChildIdx: number;
|
|
151
|
+
claimed: Set<string>;
|
|
141
152
|
}
|
|
142
153
|
|
|
143
154
|
const makeChildNodeKey = (parent: BuildFrame): string => {
|
|
@@ -145,13 +156,25 @@ const makeChildNodeKey = (parent: BuildFrame): string => {
|
|
|
145
156
|
return parent.nodeKey === "" ? String(idx) : `${parent.nodeKey}.${idx}`;
|
|
146
157
|
};
|
|
147
158
|
|
|
159
|
+
const claimIdKey = (
|
|
160
|
+
frame: BuildFrame,
|
|
161
|
+
id: string | undefined,
|
|
162
|
+
): string | undefined => {
|
|
163
|
+
if (id === undefined || frame.claimed.has(id)) return undefined;
|
|
164
|
+
frame.claimed.add(id);
|
|
165
|
+
return `id:${id}`;
|
|
166
|
+
};
|
|
167
|
+
|
|
148
168
|
/**
|
|
149
169
|
* Build the group tree from an array of normalized group paths.
|
|
150
170
|
* `paths[i]` is the path for part `i`. The output tree contains one
|
|
151
171
|
* `part` node per part and one `group` node per coalesced run.
|
|
172
|
+
* `partIds[i]` optionally carries a stable identity for part `i` (e.g. a
|
|
173
|
+
* tool call id), from which nodes derive an `idKey`.
|
|
152
174
|
*/
|
|
153
175
|
export const buildGroupTree = (
|
|
154
176
|
paths: readonly (readonly string[])[],
|
|
177
|
+
partIds?: readonly (string | undefined)[],
|
|
155
178
|
): readonly GroupNode[] => {
|
|
156
179
|
const root: BuildFrame = {
|
|
157
180
|
key: "",
|
|
@@ -159,6 +182,7 @@ export const buildGroupTree = (
|
|
|
159
182
|
indices: [],
|
|
160
183
|
children: [],
|
|
161
184
|
nextChildIdx: 0,
|
|
185
|
+
claimed: new Set(),
|
|
162
186
|
};
|
|
163
187
|
const stack: BuildFrame[] = [root];
|
|
164
188
|
|
|
@@ -169,6 +193,7 @@ export const buildGroupTree = (
|
|
|
169
193
|
type: "group",
|
|
170
194
|
key: closing.key,
|
|
171
195
|
nodeKey: closing.nodeKey,
|
|
196
|
+
idKey: claimIdKey(parent, partIds?.[closing.indices[0]!]),
|
|
172
197
|
indices: closing.indices,
|
|
173
198
|
children: closing.children,
|
|
174
199
|
});
|
|
@@ -202,6 +227,7 @@ export const buildGroupTree = (
|
|
|
202
227
|
indices: [],
|
|
203
228
|
children: [],
|
|
204
229
|
nextChildIdx: 0,
|
|
230
|
+
claimed: new Set(),
|
|
205
231
|
});
|
|
206
232
|
}
|
|
207
233
|
|
|
@@ -211,6 +237,7 @@ export const buildGroupTree = (
|
|
|
211
237
|
type: "part",
|
|
212
238
|
index: i,
|
|
213
239
|
nodeKey: makeChildNodeKey(top),
|
|
240
|
+
idKey: claimIdKey(top, partIds?.[i]),
|
|
214
241
|
});
|
|
215
242
|
|
|
216
243
|
// Record the part index in every open ancestor group.
|
|
@@ -42,5 +42,6 @@ export type ThreadListItemState = {
|
|
|
42
42
|
readonly externalId: string | undefined;
|
|
43
43
|
readonly status: import("../interfaces/thread-list-runtime-core").ThreadListItemStatus;
|
|
44
44
|
readonly title?: string | undefined;
|
|
45
|
+
readonly lastMessageAt?: Date | undefined;
|
|
45
46
|
readonly custom?: Record<string, unknown> | undefined;
|
|
46
47
|
};
|
|
@@ -101,6 +101,7 @@ export type MessageRuntime = {
|
|
|
101
101
|
readonly composer: EditComposerRuntime;
|
|
102
102
|
|
|
103
103
|
getState(): MessageState;
|
|
104
|
+
delete(): void | Promise<void>;
|
|
104
105
|
reload(config?: ReloadConfig): void;
|
|
105
106
|
/**
|
|
106
107
|
* @deprecated This API is still under active development and might change without notice.
|
|
@@ -155,6 +156,7 @@ export class MessageRuntimeImpl implements MessageRuntime {
|
|
|
155
156
|
|
|
156
157
|
protected __internal_bindMethods() {
|
|
157
158
|
this.reload = this.reload.bind(this);
|
|
159
|
+
this.delete = this.delete.bind(this);
|
|
158
160
|
this.getState = this.getState.bind(this);
|
|
159
161
|
this.subscribe = this.subscribe.bind(this);
|
|
160
162
|
this.getMessagePartByIndex = this.getMessagePartByIndex.bind(this);
|
|
@@ -180,6 +182,11 @@ export class MessageRuntimeImpl implements MessageRuntime {
|
|
|
180
182
|
return this._core.getState();
|
|
181
183
|
}
|
|
182
184
|
|
|
185
|
+
public delete() {
|
|
186
|
+
const state = this._core.getState();
|
|
187
|
+
return this._threadBinding.getState().deleteMessage(state.id);
|
|
188
|
+
}
|
|
189
|
+
|
|
183
190
|
public reload(reloadConfig: ReloadConfig = {}) {
|
|
184
191
|
const editComposerRuntimeCore = this._getEditComposerRuntimeCore();
|
|
185
192
|
const composerRuntimeCore =
|
|
@@ -88,6 +88,7 @@ const getThreadListItemState = (
|
|
|
88
88
|
externalId: threadData.externalId,
|
|
89
89
|
title: threadData.title,
|
|
90
90
|
status: threadData.status,
|
|
91
|
+
lastMessageAt: threadData.lastMessageAt,
|
|
91
92
|
custom: threadData.custom,
|
|
92
93
|
isMain: threadData.id === threadList.mainThreadId,
|
|
93
94
|
};
|
|
@@ -252,6 +252,8 @@ export type ThreadRuntime = {
|
|
|
252
252
|
*/
|
|
253
253
|
append(message: CreateAppendMessage): void;
|
|
254
254
|
|
|
255
|
+
deleteMessage(messageId: string): void | Promise<void>;
|
|
256
|
+
|
|
255
257
|
/**
|
|
256
258
|
* Start a new run with the given configuration.
|
|
257
259
|
* @param config The configuration for starting the run
|
|
@@ -374,6 +376,7 @@ export class ThreadRuntimeImpl implements ThreadRuntime {
|
|
|
374
376
|
|
|
375
377
|
protected __internal_bindMethods() {
|
|
376
378
|
this.append = this.append.bind(this);
|
|
379
|
+
this.deleteMessage = this.deleteMessage.bind(this);
|
|
377
380
|
this.resumeRun = this.resumeRun.bind(this);
|
|
378
381
|
this.importExternalState = this.importExternalState.bind(this);
|
|
379
382
|
this.exportExternalState = this.exportExternalState.bind(this);
|
|
@@ -411,6 +414,10 @@ export class ThreadRuntimeImpl implements ThreadRuntime {
|
|
|
411
414
|
);
|
|
412
415
|
}
|
|
413
416
|
|
|
417
|
+
public deleteMessage(messageId: string) {
|
|
418
|
+
return this._threadBinding.getState().deleteMessage(messageId);
|
|
419
|
+
}
|
|
420
|
+
|
|
414
421
|
public subscribe(callback: () => void) {
|
|
415
422
|
return this._threadBinding.subscribe(callback);
|
|
416
423
|
}
|
|
@@ -56,6 +56,7 @@ export abstract class BaseThreadRuntimeCore implements ThreadRuntimeCore {
|
|
|
56
56
|
|
|
57
57
|
public abstract get capabilities(): RuntimeCapabilities;
|
|
58
58
|
public abstract append(message: AppendMessage): void;
|
|
59
|
+
public abstract deleteMessage(messageId: string): void | Promise<void>;
|
|
59
60
|
public abstract startRun(config: StartRunConfig): void;
|
|
60
61
|
public abstract resumeRun(config: ResumeRunConfig): void;
|
|
61
62
|
public abstract addToolResult(options: AddToolResultOptions): void;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The branch surface a runtime exposes so the branch picker can navigate
|
|
3
|
+
* between sibling variants of a message. Read during render; recreate the
|
|
4
|
+
* adapter object when branch data changes.
|
|
5
|
+
*
|
|
6
|
+
* Editing a message creates a branch only if the `onEdit` handler creates a
|
|
7
|
+
* sibling and `getBranches` reports it. Note that `ExternalThread`'s edit
|
|
8
|
+
* payload carries the edited message's own id as both `parentId` and
|
|
9
|
+
* `sourceId`.
|
|
10
|
+
*/
|
|
11
|
+
export type ExternalThreadBranchAdapter = {
|
|
12
|
+
/**
|
|
13
|
+
* Returns the sibling branch ids for a message in display order, including
|
|
14
|
+
* the message's own id. Return an empty array for messages without
|
|
15
|
+
* alternative branches.
|
|
16
|
+
*/
|
|
17
|
+
getBranches: (messageId: string) => readonly string[];
|
|
18
|
+
/**
|
|
19
|
+
* Makes the given branch the visible one. The runtime is expected to swap
|
|
20
|
+
* the `messages` array to the selected branch. May be invoked
|
|
21
|
+
* programmatically while a run is in progress; pending queue items are not
|
|
22
|
+
* cleared, and reconciling them with the new branch is the runtime's
|
|
23
|
+
* responsibility.
|
|
24
|
+
*/
|
|
25
|
+
switchToBranch: (branchId: string) => void;
|
|
26
|
+
};
|
|
@@ -10,6 +10,7 @@ export type ThreadListItemCoreState = {
|
|
|
10
10
|
|
|
11
11
|
readonly status: ThreadListItemStatus;
|
|
12
12
|
readonly title?: string | undefined;
|
|
13
|
+
readonly lastMessageAt?: Date | undefined;
|
|
13
14
|
readonly custom?: Record<string, unknown> | undefined;
|
|
14
15
|
|
|
15
16
|
readonly runtime?: ThreadRuntimeCore | undefined;
|
|
@@ -23,6 +23,7 @@ export type RuntimeCapabilities = {
|
|
|
23
23
|
readonly switchBranchDuringRun: boolean;
|
|
24
24
|
readonly edit: boolean;
|
|
25
25
|
readonly reload: boolean;
|
|
26
|
+
readonly delete: boolean;
|
|
26
27
|
readonly cancel: boolean;
|
|
27
28
|
readonly unstable_copy: boolean;
|
|
28
29
|
readonly speech: boolean;
|
|
@@ -146,6 +147,7 @@ export type ThreadRuntimeCore = Readonly<{
|
|
|
146
147
|
switchToBranch: (branchId: string) => void;
|
|
147
148
|
|
|
148
149
|
append: (message: AppendMessage) => void;
|
|
150
|
+
deleteMessage: (messageId: string) => void | Promise<void>;
|
|
149
151
|
startRun: (config: StartRunConfig) => void;
|
|
150
152
|
resumeRun: (config: ResumeRunConfig) => void;
|
|
151
153
|
cancelRun: () => void;
|
|
@@ -109,6 +109,7 @@ type ExternalStoreAdapterBase<T> = {
|
|
|
109
109
|
/** Opt in to message queuing. Typically produced by `createMessageQueue`. */
|
|
110
110
|
queue?: ExternalThreadQueueAdapter | undefined;
|
|
111
111
|
onEdit?: ((message: AppendMessage) => Promise<void>) | undefined;
|
|
112
|
+
onDelete?: ((messageId: string) => Promise<void> | void) | undefined;
|
|
112
113
|
onReload?: // TODO: remove parentId in 0.12.0
|
|
113
114
|
| ((parentId: string | null, config: StartRunConfig) => Promise<void>)
|
|
114
115
|
| undefined;
|
|
@@ -60,6 +60,7 @@ export class ExternalStoreThreadRuntimeCore
|
|
|
60
60
|
switchToBranch: false,
|
|
61
61
|
switchBranchDuringRun: false,
|
|
62
62
|
edit: false,
|
|
63
|
+
delete: false,
|
|
63
64
|
reload: false,
|
|
64
65
|
cancel: false,
|
|
65
66
|
unstable_copy: false,
|
|
@@ -148,6 +149,9 @@ export class ExternalStoreThreadRuntimeCore
|
|
|
148
149
|
switchToBranch: this._store.setMessages !== undefined,
|
|
149
150
|
switchBranchDuringRun: false,
|
|
150
151
|
edit: this._store.onEdit !== undefined,
|
|
152
|
+
delete:
|
|
153
|
+
this._store.onDelete !== undefined ||
|
|
154
|
+
this._store.setMessages !== undefined,
|
|
151
155
|
reload: this._store.onReload !== undefined,
|
|
152
156
|
cancel: this._store.onCancel !== undefined,
|
|
153
157
|
speech: this._store.adapters?.speech !== undefined,
|
|
@@ -419,6 +423,26 @@ export class ExternalStoreThreadRuntimeCore
|
|
|
419
423
|
}
|
|
420
424
|
}
|
|
421
425
|
|
|
426
|
+
public async deleteMessage(messageId: string): Promise<void> {
|
|
427
|
+
if (this._store.onDelete) {
|
|
428
|
+
await this._store.onDelete(messageId);
|
|
429
|
+
return;
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
if (!this._store.setMessages)
|
|
433
|
+
throw new Error("Runtime does not support deleting messages.");
|
|
434
|
+
|
|
435
|
+
if (this._store.isRunning) {
|
|
436
|
+
await this._toolInvocations?.abort();
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
const messages = this.repository.getMessages();
|
|
440
|
+
const messageIndex = messages.findIndex((m) => m.id === messageId);
|
|
441
|
+
if (messageIndex === -1) throw new Error("Message not found.");
|
|
442
|
+
|
|
443
|
+
this.updateMessages(messages.filter((message) => message.id !== messageId));
|
|
444
|
+
}
|
|
445
|
+
|
|
422
446
|
public getQueueItems() {
|
|
423
447
|
// The composer reads this during base-thread construction, before the
|
|
424
448
|
// constructor assigns `_store`, so guard against the unset field.
|
|
@@ -23,7 +23,7 @@ export type LocalRuntimeOptionsBase = {
|
|
|
23
23
|
};
|
|
24
24
|
|
|
25
25
|
/**
|
|
26
|
-
* Names of tools that
|
|
26
|
+
* Names of tools that pause the run until a result is supplied via `addToolResult`.
|
|
27
27
|
*/
|
|
28
28
|
unstable_humanToolNames?: string[] | undefined;
|
|
29
29
|
|