@assistant-ui/react 0.10.25 → 0.10.27
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/primitives/message/MessagePartsGroupedByParentId.d.ts +122 -0
- package/dist/primitives/message/MessagePartsGroupedByParentId.d.ts.map +1 -0
- package/dist/primitives/message/MessagePartsGroupedByParentId.js +184 -0
- package/dist/primitives/message/MessagePartsGroupedByParentId.js.map +1 -0
- package/dist/primitives/message/index.d.ts +1 -0
- package/dist/primitives/message/index.d.ts.map +1 -1
- package/dist/primitives/message/index.js +3 -1
- package/dist/primitives/message/index.js.map +1 -1
- package/dist/runtimes/external-store/ExternalStoreThreadRuntimeCore.d.ts.map +1 -1
- package/dist/runtimes/external-store/ExternalStoreThreadRuntimeCore.js +0 -8
- package/dist/runtimes/external-store/ExternalStoreThreadRuntimeCore.js.map +1 -1
- package/dist/runtimes/external-store/ThreadMessageLike.d.ts +1 -0
- package/dist/runtimes/external-store/ThreadMessageLike.d.ts.map +1 -1
- package/dist/runtimes/external-store/ThreadMessageLike.js +9 -5
- package/dist/runtimes/external-store/ThreadMessageLike.js.map +1 -1
- package/dist/types/AssistantTypes.d.ts +4 -0
- package/dist/types/AssistantTypes.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/primitives/message/MessagePartsGroupedByParentId.tsx +415 -0
- package/src/primitives/message/index.ts +1 -0
- package/src/runtimes/external-store/ExternalStoreThreadRuntimeCore.tsx +0 -8
- package/src/runtimes/external-store/ThreadMessageLike.tsx +11 -5
- package/src/types/AssistantTypes.ts +4 -0
@@ -0,0 +1,122 @@
|
|
1
|
+
import { type ComponentType, type FC, PropsWithChildren } from "react";
|
2
|
+
import type { Unstable_AudioMessagePartComponent, EmptyMessagePartComponent, TextMessagePartComponent, ImageMessagePartComponent, SourceMessagePartComponent, ToolCallMessagePartComponent, ToolCallMessagePartProps, FileMessagePartComponent, ReasoningMessagePartComponent } from "../../types/MessagePartComponentTypes";
|
3
|
+
export declare namespace MessagePrimitiveUnstable_PartsGroupedByParentId {
|
4
|
+
type Props = {
|
5
|
+
/**
|
6
|
+
* Component configuration for rendering different types of message content.
|
7
|
+
*
|
8
|
+
* You can provide custom components for each content type (text, image, file, etc.)
|
9
|
+
* and configure tool rendering behavior. If not provided, default components will be used.
|
10
|
+
*/
|
11
|
+
components?: {
|
12
|
+
/** Component for rendering empty messages */
|
13
|
+
Empty?: EmptyMessagePartComponent | undefined;
|
14
|
+
/** Component for rendering text content */
|
15
|
+
Text?: TextMessagePartComponent | undefined;
|
16
|
+
/** Component for rendering reasoning content (typically hidden) */
|
17
|
+
Reasoning?: ReasoningMessagePartComponent | undefined;
|
18
|
+
/** Component for rendering source content */
|
19
|
+
Source?: SourceMessagePartComponent | undefined;
|
20
|
+
/** Component for rendering image content */
|
21
|
+
Image?: ImageMessagePartComponent | undefined;
|
22
|
+
/** Component for rendering file content */
|
23
|
+
File?: FileMessagePartComponent | undefined;
|
24
|
+
/** Component for rendering audio content (experimental) */
|
25
|
+
Unstable_Audio?: Unstable_AudioMessagePartComponent | undefined;
|
26
|
+
/** Configuration for tool call rendering */
|
27
|
+
tools?: {
|
28
|
+
/** Map of tool names to their specific components */
|
29
|
+
by_name?: Record<string, ToolCallMessagePartComponent | undefined> | undefined;
|
30
|
+
/** Fallback component for unregistered tools */
|
31
|
+
Fallback?: ComponentType<ToolCallMessagePartProps> | undefined;
|
32
|
+
} | {
|
33
|
+
/** Override component that handles all tool calls */
|
34
|
+
Override: ComponentType<ToolCallMessagePartProps>;
|
35
|
+
} | undefined;
|
36
|
+
/**
|
37
|
+
* Component for rendering grouped message parts with the same parent ID.
|
38
|
+
*
|
39
|
+
* When provided, this component will automatically wrap message parts that share
|
40
|
+
* the same parent ID, allowing you to create collapsible sections, custom styling,
|
41
|
+
* or other grouped presentations.
|
42
|
+
*
|
43
|
+
* The component receives:
|
44
|
+
* - `parentId`: The parent ID shared by all parts in the group (or undefined for ungrouped parts)
|
45
|
+
* - `indices`: Array of indices for the parts in this group
|
46
|
+
* - `children`: The rendered message part components
|
47
|
+
*
|
48
|
+
* @example
|
49
|
+
* ```tsx
|
50
|
+
* // Collapsible parent ID group
|
51
|
+
* Group: ({ parentId, indices, children }) => {
|
52
|
+
* if (!parentId) return <>{children}</>;
|
53
|
+
* return (
|
54
|
+
* <details className="parent-group">
|
55
|
+
* <summary>
|
56
|
+
* Group {parentId} ({indices.length} parts)
|
57
|
+
* </summary>
|
58
|
+
* <div className="parent-group-content">
|
59
|
+
* {children}
|
60
|
+
* </div>
|
61
|
+
* </details>
|
62
|
+
* );
|
63
|
+
* }
|
64
|
+
* ```
|
65
|
+
*
|
66
|
+
* @example
|
67
|
+
* ```tsx
|
68
|
+
* // Custom styled parent ID group
|
69
|
+
* Group: ({ parentId, indices, children }) => {
|
70
|
+
* if (!parentId) return <>{children}</>;
|
71
|
+
* return (
|
72
|
+
* <div className="border rounded-lg p-4 my-2">
|
73
|
+
* <div className="text-sm text-gray-600 mb-2">
|
74
|
+
* Related content ({parentId})
|
75
|
+
* </div>
|
76
|
+
* <div className="space-y-2">
|
77
|
+
* {children}
|
78
|
+
* </div>
|
79
|
+
* </div>
|
80
|
+
* );
|
81
|
+
* }
|
82
|
+
* ```
|
83
|
+
*
|
84
|
+
* @param parentId - The parent ID shared by all parts in this group (undefined for ungrouped parts)
|
85
|
+
* @param indices - Array of indices for the parts in this group
|
86
|
+
* @param children - Rendered message part components to display within the group
|
87
|
+
*/
|
88
|
+
Group?: ComponentType<PropsWithChildren<{
|
89
|
+
parentId: string | undefined;
|
90
|
+
indices: number[];
|
91
|
+
}>>;
|
92
|
+
} | undefined;
|
93
|
+
};
|
94
|
+
}
|
95
|
+
/**
|
96
|
+
* Renders the parts of a message grouped by their parent ID.
|
97
|
+
*
|
98
|
+
* This component automatically groups message parts that share the same parent ID,
|
99
|
+
* allowing you to create hierarchical or related content presentations. Parts without
|
100
|
+
* a parent ID appear after grouped parts and remain ungrouped.
|
101
|
+
*
|
102
|
+
* @example
|
103
|
+
* ```tsx
|
104
|
+
* <MessagePrimitive.Unstable_PartsGroupedByParentId
|
105
|
+
* components={{
|
106
|
+
* Text: ({ text }) => <p className="message-text">{text}</p>,
|
107
|
+
* Image: ({ image }) => <img src={image} alt="Message image" />,
|
108
|
+
* Group: ({ parentId, indices, children }) => {
|
109
|
+
* if (!parentId) return <>{children}</>;
|
110
|
+
* return (
|
111
|
+
* <div className="parent-group border rounded p-4">
|
112
|
+
* <h4>Related Content</h4>
|
113
|
+
* {children}
|
114
|
+
* </div>
|
115
|
+
* );
|
116
|
+
* }
|
117
|
+
* }}
|
118
|
+
* />
|
119
|
+
* ```
|
120
|
+
*/
|
121
|
+
export declare const MessagePrimitiveUnstable_PartsGroupedByParentId: FC<MessagePrimitiveUnstable_PartsGroupedByParentId.Props>;
|
122
|
+
//# sourceMappingURL=MessagePartsGroupedByParentId.d.ts.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"MessagePartsGroupedByParentId.d.ts","sourceRoot":"","sources":["../../../src/primitives/message/MessagePartsGroupedByParentId.tsx"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,aAAa,EAClB,KAAK,EAAE,EAEP,iBAAiB,EAElB,MAAM,OAAO,CAAC;AAcf,OAAO,KAAK,EACV,kCAAkC,EAClC,yBAAyB,EACzB,wBAAwB,EACxB,yBAAyB,EACzB,0BAA0B,EAC1B,4BAA4B,EAC5B,wBAAwB,EACxB,wBAAwB,EACxB,6BAA6B,EAC9B,MAAM,uCAAuC,CAAC;AA+D/C,yBAAiB,+CAA+C,CAAC;IAC/D,KAAY,KAAK,GAAG;QAClB;;;;;WAKG;QACH,UAAU,CAAC,EACP;YACE,6CAA6C;YAC7C,KAAK,CAAC,EAAE,yBAAyB,GAAG,SAAS,CAAC;YAC9C,2CAA2C;YAC3C,IAAI,CAAC,EAAE,wBAAwB,GAAG,SAAS,CAAC;YAC5C,mEAAmE;YACnE,SAAS,CAAC,EAAE,6BAA6B,GAAG,SAAS,CAAC;YACtD,6CAA6C;YAC7C,MAAM,CAAC,EAAE,0BAA0B,GAAG,SAAS,CAAC;YAChD,4CAA4C;YAC5C,KAAK,CAAC,EAAE,yBAAyB,GAAG,SAAS,CAAC;YAC9C,2CAA2C;YAC3C,IAAI,CAAC,EAAE,wBAAwB,GAAG,SAAS,CAAC;YAC5C,2DAA2D;YAC3D,cAAc,CAAC,EAAE,kCAAkC,GAAG,SAAS,CAAC;YAChE,4CAA4C;YAC5C,KAAK,CAAC,EACF;gBACE,qDAAqD;gBACrD,OAAO,CAAC,EACJ,MAAM,CAAC,MAAM,EAAE,4BAA4B,GAAG,SAAS,CAAC,GACxD,SAAS,CAAC;gBACd,gDAAgD;gBAChD,QAAQ,CAAC,EAAE,aAAa,CAAC,wBAAwB,CAAC,GAAG,SAAS,CAAC;aAChE,GACD;gBACE,qDAAqD;gBACrD,QAAQ,EAAE,aAAa,CAAC,wBAAwB,CAAC,CAAC;aACnD,GACD,SAAS,CAAC;YAEd;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;eAmDG;YACH,KAAK,CAAC,EAAE,aAAa,CACnB,iBAAiB,CAAC;gBAChB,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;gBAC7B,OAAO,EAAE,MAAM,EAAE,CAAC;aACnB,CAAC,CACH,CAAC;SACH,GACD,SAAS,CAAC;KACf,CAAC;CACH;AA4JD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,eAAO,MAAM,+CAA+C,EAAE,EAAE,CAC9D,+CAA+C,CAAC,KAAK,CAgCtD,CAAC"}
|
@@ -0,0 +1,184 @@
|
|
1
|
+
"use client";
|
2
|
+
|
3
|
+
// src/primitives/message/MessagePartsGroupedByParentId.tsx
|
4
|
+
import {
|
5
|
+
memo,
|
6
|
+
useMemo
|
7
|
+
} from "react";
|
8
|
+
import {
|
9
|
+
TextMessagePartProvider,
|
10
|
+
useMessagePart,
|
11
|
+
useMessagePartRuntime,
|
12
|
+
useToolUIs
|
13
|
+
} from "../../context/index.js";
|
14
|
+
import {
|
15
|
+
useMessage,
|
16
|
+
useMessageRuntime
|
17
|
+
} from "../../context/react/MessageContext.js";
|
18
|
+
import { MessagePartRuntimeProvider } from "../../context/providers/MessagePartRuntimeProvider.js";
|
19
|
+
import { MessagePartPrimitiveText } from "../messagePart/MessagePartText.js";
|
20
|
+
import { MessagePartPrimitiveImage } from "../messagePart/MessagePartImage.js";
|
21
|
+
import { MessagePartPrimitiveInProgress } from "../messagePart/MessagePartInProgress.js";
|
22
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
23
|
+
var groupMessagePartsByParentId = (parts) => {
|
24
|
+
const groups = [];
|
25
|
+
const parentIdToGroupIndex = /* @__PURE__ */ new Map();
|
26
|
+
const processedIndices = /* @__PURE__ */ new Set();
|
27
|
+
for (let i = 0; i < parts.length; i++) {
|
28
|
+
const part = parts[i];
|
29
|
+
const parentId = part?.parentId;
|
30
|
+
if (parentId !== void 0) {
|
31
|
+
let groupIndex = parentIdToGroupIndex.get(parentId);
|
32
|
+
if (groupIndex === void 0) {
|
33
|
+
groupIndex = groups.length;
|
34
|
+
groups.push({ parentId, indices: [] });
|
35
|
+
parentIdToGroupIndex.set(parentId, groupIndex);
|
36
|
+
}
|
37
|
+
groups[groupIndex].indices.push(i);
|
38
|
+
processedIndices.add(i);
|
39
|
+
}
|
40
|
+
}
|
41
|
+
for (let i = 0; i < parts.length; i++) {
|
42
|
+
if (!processedIndices.has(i)) {
|
43
|
+
groups.push({ parentId: void 0, indices: [i] });
|
44
|
+
}
|
45
|
+
}
|
46
|
+
return groups;
|
47
|
+
};
|
48
|
+
var useMessagePartsGroupedByParentId = () => {
|
49
|
+
const parts = useMessage((m) => m.content);
|
50
|
+
return useMemo(() => {
|
51
|
+
if (parts.length === 0) {
|
52
|
+
return [];
|
53
|
+
}
|
54
|
+
return groupMessagePartsByParentId(parts);
|
55
|
+
}, [parts]);
|
56
|
+
};
|
57
|
+
var ToolUIDisplay = ({
|
58
|
+
Fallback,
|
59
|
+
...props
|
60
|
+
}) => {
|
61
|
+
const Render = useToolUIs((s) => s.getToolUI(props.toolName)) ?? Fallback;
|
62
|
+
if (!Render) return null;
|
63
|
+
return /* @__PURE__ */ jsx(Render, { ...props });
|
64
|
+
};
|
65
|
+
var defaultComponents = {
|
66
|
+
Text: () => /* @__PURE__ */ jsxs("p", { style: { whiteSpace: "pre-line" }, children: [
|
67
|
+
/* @__PURE__ */ jsx(MessagePartPrimitiveText, {}),
|
68
|
+
/* @__PURE__ */ jsx(MessagePartPrimitiveInProgress, { children: /* @__PURE__ */ jsx("span", { style: { fontFamily: "revert" }, children: " \u25CF" }) })
|
69
|
+
] }),
|
70
|
+
Reasoning: () => null,
|
71
|
+
Source: () => null,
|
72
|
+
Image: () => /* @__PURE__ */ jsx(MessagePartPrimitiveImage, {}),
|
73
|
+
File: () => null,
|
74
|
+
Unstable_Audio: () => null,
|
75
|
+
Group: ({ children }) => children
|
76
|
+
};
|
77
|
+
var MessagePartComponent = ({
|
78
|
+
components: {
|
79
|
+
Text = defaultComponents.Text,
|
80
|
+
Reasoning = defaultComponents.Reasoning,
|
81
|
+
Image = defaultComponents.Image,
|
82
|
+
Source = defaultComponents.Source,
|
83
|
+
File = defaultComponents.File,
|
84
|
+
Unstable_Audio: Audio = defaultComponents.Unstable_Audio,
|
85
|
+
tools = {}
|
86
|
+
} = {}
|
87
|
+
}) => {
|
88
|
+
const MessagePartRuntime = useMessagePartRuntime();
|
89
|
+
const part = useMessagePart();
|
90
|
+
const type = part.type;
|
91
|
+
if (type === "tool-call") {
|
92
|
+
const addResult = (result) => MessagePartRuntime.addToolResult(result);
|
93
|
+
if ("Override" in tools)
|
94
|
+
return /* @__PURE__ */ jsx(tools.Override, { ...part, addResult });
|
95
|
+
const Tool = tools.by_name?.[part.toolName] ?? tools.Fallback;
|
96
|
+
return /* @__PURE__ */ jsx(ToolUIDisplay, { ...part, Fallback: Tool, addResult });
|
97
|
+
}
|
98
|
+
if (part.status.type === "requires-action")
|
99
|
+
throw new Error("Encountered unexpected requires-action status");
|
100
|
+
switch (type) {
|
101
|
+
case "text":
|
102
|
+
return /* @__PURE__ */ jsx(Text, { ...part });
|
103
|
+
case "reasoning":
|
104
|
+
return /* @__PURE__ */ jsx(Reasoning, { ...part });
|
105
|
+
case "source":
|
106
|
+
return /* @__PURE__ */ jsx(Source, { ...part });
|
107
|
+
case "image":
|
108
|
+
return /* @__PURE__ */ jsx(Image, { ...part });
|
109
|
+
case "file":
|
110
|
+
return /* @__PURE__ */ jsx(File, { ...part });
|
111
|
+
case "audio":
|
112
|
+
return /* @__PURE__ */ jsx(Audio, { ...part });
|
113
|
+
default:
|
114
|
+
const unhandledType = type;
|
115
|
+
throw new Error(`Unknown message part type: ${unhandledType}`);
|
116
|
+
}
|
117
|
+
};
|
118
|
+
var MessagePartImpl = ({ partIndex, components }) => {
|
119
|
+
const messageRuntime = useMessageRuntime();
|
120
|
+
const runtime = useMemo(
|
121
|
+
() => messageRuntime.getMessagePartByIndex(partIndex),
|
122
|
+
[messageRuntime, partIndex]
|
123
|
+
);
|
124
|
+
return /* @__PURE__ */ jsx(MessagePartRuntimeProvider, { runtime, children: /* @__PURE__ */ jsx(MessagePartComponent, { components }) });
|
125
|
+
};
|
126
|
+
var MessagePart = memo(
|
127
|
+
MessagePartImpl,
|
128
|
+
(prev, next) => prev.partIndex === next.partIndex && prev.components?.Text === next.components?.Text && prev.components?.Reasoning === next.components?.Reasoning && prev.components?.Source === next.components?.Source && prev.components?.Image === next.components?.Image && prev.components?.File === next.components?.File && prev.components?.Unstable_Audio === next.components?.Unstable_Audio && prev.components?.tools === next.components?.tools && prev.components?.Group === next.components?.Group
|
129
|
+
);
|
130
|
+
var COMPLETE_STATUS = Object.freeze({
|
131
|
+
type: "complete"
|
132
|
+
});
|
133
|
+
var EmptyPartFallback = ({ status, component: Component }) => {
|
134
|
+
return /* @__PURE__ */ jsx(TextMessagePartProvider, { text: "", isRunning: status.type === "running", children: /* @__PURE__ */ jsx(Component, { type: "text", text: "", status }) });
|
135
|
+
};
|
136
|
+
var EmptyPartsImpl = ({ components }) => {
|
137
|
+
const status = useMessage((s) => s.status) ?? COMPLETE_STATUS;
|
138
|
+
if (components?.Empty) return /* @__PURE__ */ jsx(components.Empty, { status });
|
139
|
+
return /* @__PURE__ */ jsx(
|
140
|
+
EmptyPartFallback,
|
141
|
+
{
|
142
|
+
status,
|
143
|
+
component: components?.Text ?? defaultComponents.Text
|
144
|
+
}
|
145
|
+
);
|
146
|
+
};
|
147
|
+
var EmptyParts = memo(
|
148
|
+
EmptyPartsImpl,
|
149
|
+
(prev, next) => prev.components?.Empty === next.components?.Empty && prev.components?.Text === next.components?.Text
|
150
|
+
);
|
151
|
+
var MessagePrimitiveUnstable_PartsGroupedByParentId = ({ components }) => {
|
152
|
+
const contentLength = useMessage((s) => s.content.length);
|
153
|
+
const messageGroups = useMessagePartsGroupedByParentId();
|
154
|
+
const partsElements = useMemo(() => {
|
155
|
+
if (contentLength === 0) {
|
156
|
+
return /* @__PURE__ */ jsx(EmptyParts, { components });
|
157
|
+
}
|
158
|
+
return messageGroups.map((group, groupIndex) => {
|
159
|
+
const GroupComponent = components?.Group ?? defaultComponents.Group;
|
160
|
+
return /* @__PURE__ */ jsx(
|
161
|
+
GroupComponent,
|
162
|
+
{
|
163
|
+
parentId: group.parentId,
|
164
|
+
indices: group.indices,
|
165
|
+
children: group.indices.map((partIndex) => /* @__PURE__ */ jsx(
|
166
|
+
MessagePart,
|
167
|
+
{
|
168
|
+
partIndex,
|
169
|
+
components
|
170
|
+
},
|
171
|
+
partIndex
|
172
|
+
))
|
173
|
+
},
|
174
|
+
`group-${groupIndex}-${group.parentId ?? "ungrouped"}`
|
175
|
+
);
|
176
|
+
});
|
177
|
+
}, [messageGroups, components, contentLength]);
|
178
|
+
return /* @__PURE__ */ jsx(Fragment, { children: partsElements });
|
179
|
+
};
|
180
|
+
MessagePrimitiveUnstable_PartsGroupedByParentId.displayName = "MessagePrimitive.Unstable_PartsGroupedByParentId";
|
181
|
+
export {
|
182
|
+
MessagePrimitiveUnstable_PartsGroupedByParentId
|
183
|
+
};
|
184
|
+
//# sourceMappingURL=MessagePartsGroupedByParentId.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"sources":["../../../src/primitives/message/MessagePartsGroupedByParentId.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n type ComponentType,\n type FC,\n memo,\n PropsWithChildren,\n useMemo,\n} from \"react\";\nimport {\n TextMessagePartProvider,\n useMessagePart,\n useMessagePartRuntime,\n useToolUIs,\n} from \"../../context\";\nimport {\n useMessage,\n useMessageRuntime,\n} from \"../../context/react/MessageContext\";\nimport { MessagePartRuntimeProvider } from \"../../context/providers/MessagePartRuntimeProvider\";\nimport { MessagePartPrimitiveText } from \"../messagePart/MessagePartText\";\nimport { MessagePartPrimitiveImage } from \"../messagePart/MessagePartImage\";\nimport type {\n Unstable_AudioMessagePartComponent,\n EmptyMessagePartComponent,\n TextMessagePartComponent,\n ImageMessagePartComponent,\n SourceMessagePartComponent,\n ToolCallMessagePartComponent,\n ToolCallMessagePartProps,\n FileMessagePartComponent,\n ReasoningMessagePartComponent,\n} from \"../../types/MessagePartComponentTypes\";\nimport { MessagePartPrimitiveInProgress } from \"../messagePart/MessagePartInProgress\";\nimport { MessagePartStatus } from \"../../types/AssistantTypes\";\n\ntype MessagePartGroup = {\n parentId: string | undefined;\n indices: number[];\n};\n\n/**\n * Groups message parts by their parent ID.\n * Parts without a parent ID appear after grouped parts and remain ungrouped.\n * The position of groups is based on the first occurrence of each parent ID.\n */\nconst groupMessagePartsByParentId = (\n parts: readonly any[],\n): MessagePartGroup[] => {\n const groups: MessagePartGroup[] = [];\n const parentIdToGroupIndex = new Map<string | undefined, number>();\n const processedIndices = new Set<number>();\n\n // First pass: process all parts with parent IDs\n for (let i = 0; i < parts.length; i++) {\n const part = parts[i];\n const parentId = part?.parentId as string | undefined;\n\n if (parentId !== undefined) {\n let groupIndex = parentIdToGroupIndex.get(parentId);\n\n if (groupIndex === undefined) {\n // Create new group for this parent ID\n groupIndex = groups.length;\n groups.push({ parentId, indices: [] });\n parentIdToGroupIndex.set(parentId, groupIndex);\n }\n\n groups[groupIndex]!.indices.push(i);\n processedIndices.add(i);\n }\n }\n\n // Second pass: add ungrouped parts (those without parent ID)\n for (let i = 0; i < parts.length; i++) {\n if (!processedIndices.has(i)) {\n // Add individual group for parts without parent ID\n groups.push({ parentId: undefined, indices: [i] });\n }\n }\n\n return groups;\n};\n\nconst useMessagePartsGroupedByParentId = (): MessagePartGroup[] => {\n const parts = useMessage((m) => m.content);\n\n return useMemo(() => {\n if (parts.length === 0) {\n return [];\n }\n return groupMessagePartsByParentId(parts);\n }, [parts]);\n};\n\nexport namespace MessagePrimitiveUnstable_PartsGroupedByParentId {\n export type Props = {\n /**\n * Component configuration for rendering different types of message content.\n *\n * You can provide custom components for each content type (text, image, file, etc.)\n * and configure tool rendering behavior. If not provided, default components will be used.\n */\n components?:\n | {\n /** Component for rendering empty messages */\n Empty?: EmptyMessagePartComponent | undefined;\n /** Component for rendering text content */\n Text?: TextMessagePartComponent | undefined;\n /** Component for rendering reasoning content (typically hidden) */\n Reasoning?: ReasoningMessagePartComponent | undefined;\n /** Component for rendering source content */\n Source?: SourceMessagePartComponent | undefined;\n /** Component for rendering image content */\n Image?: ImageMessagePartComponent | undefined;\n /** Component for rendering file content */\n File?: FileMessagePartComponent | undefined;\n /** Component for rendering audio content (experimental) */\n Unstable_Audio?: Unstable_AudioMessagePartComponent | undefined;\n /** Configuration for tool call rendering */\n tools?:\n | {\n /** Map of tool names to their specific components */\n by_name?:\n | Record<string, ToolCallMessagePartComponent | undefined>\n | undefined;\n /** Fallback component for unregistered tools */\n Fallback?: ComponentType<ToolCallMessagePartProps> | undefined;\n }\n | {\n /** Override component that handles all tool calls */\n Override: ComponentType<ToolCallMessagePartProps>;\n }\n | undefined;\n\n /**\n * Component for rendering grouped message parts with the same parent ID.\n *\n * When provided, this component will automatically wrap message parts that share\n * the same parent ID, allowing you to create collapsible sections, custom styling,\n * or other grouped presentations.\n *\n * The component receives:\n * - `parentId`: The parent ID shared by all parts in the group (or undefined for ungrouped parts)\n * - `indices`: Array of indices for the parts in this group\n * - `children`: The rendered message part components\n *\n * @example\n * ```tsx\n * // Collapsible parent ID group\n * Group: ({ parentId, indices, children }) => {\n * if (!parentId) return <>{children}</>;\n * return (\n * <details className=\"parent-group\">\n * <summary>\n * Group {parentId} ({indices.length} parts)\n * </summary>\n * <div className=\"parent-group-content\">\n * {children}\n * </div>\n * </details>\n * );\n * }\n * ```\n *\n * @example\n * ```tsx\n * // Custom styled parent ID group\n * Group: ({ parentId, indices, children }) => {\n * if (!parentId) return <>{children}</>;\n * return (\n * <div className=\"border rounded-lg p-4 my-2\">\n * <div className=\"text-sm text-gray-600 mb-2\">\n * Related content ({parentId})\n * </div>\n * <div className=\"space-y-2\">\n * {children}\n * </div>\n * </div>\n * );\n * }\n * ```\n *\n * @param parentId - The parent ID shared by all parts in this group (undefined for ungrouped parts)\n * @param indices - Array of indices for the parts in this group\n * @param children - Rendered message part components to display within the group\n */\n Group?: ComponentType<\n PropsWithChildren<{\n parentId: string | undefined;\n indices: number[];\n }>\n >;\n }\n | undefined;\n };\n}\n\nconst ToolUIDisplay = ({\n Fallback,\n ...props\n}: {\n Fallback: ToolCallMessagePartComponent | undefined;\n} & ToolCallMessagePartProps) => {\n const Render = useToolUIs((s) => s.getToolUI(props.toolName)) ?? Fallback;\n if (!Render) return null;\n return <Render {...props} />;\n};\n\nconst defaultComponents = {\n Text: () => (\n <p style={{ whiteSpace: \"pre-line\" }}>\n <MessagePartPrimitiveText />\n <MessagePartPrimitiveInProgress>\n <span style={{ fontFamily: \"revert\" }}>{\" \\u25CF\"}</span>\n </MessagePartPrimitiveInProgress>\n </p>\n ),\n Reasoning: () => null,\n Source: () => null,\n Image: () => <MessagePartPrimitiveImage />,\n File: () => null,\n Unstable_Audio: () => null,\n Group: ({ children }) => children,\n} satisfies MessagePrimitiveUnstable_PartsGroupedByParentId.Props[\"components\"];\n\ntype MessagePartComponentProps = {\n components: MessagePrimitiveUnstable_PartsGroupedByParentId.Props[\"components\"];\n};\n\nconst MessagePartComponent: FC<MessagePartComponentProps> = ({\n components: {\n Text = defaultComponents.Text,\n Reasoning = defaultComponents.Reasoning,\n Image = defaultComponents.Image,\n Source = defaultComponents.Source,\n File = defaultComponents.File,\n Unstable_Audio: Audio = defaultComponents.Unstable_Audio,\n tools = {},\n } = {},\n}) => {\n const MessagePartRuntime = useMessagePartRuntime();\n\n const part = useMessagePart();\n\n const type = part.type;\n if (type === \"tool-call\") {\n const addResult = (result: any) => MessagePartRuntime.addToolResult(result);\n if (\"Override\" in tools)\n return <tools.Override {...part} addResult={addResult} />;\n const Tool = tools.by_name?.[part.toolName] ?? tools.Fallback;\n return <ToolUIDisplay {...part} Fallback={Tool} addResult={addResult} />;\n }\n\n if (part.status.type === \"requires-action\")\n throw new Error(\"Encountered unexpected requires-action status\");\n\n switch (type) {\n case \"text\":\n return <Text {...part} />;\n\n case \"reasoning\":\n return <Reasoning {...part} />;\n\n case \"source\":\n return <Source {...part} />;\n\n case \"image\":\n // eslint-disable-next-line jsx-a11y/alt-text\n return <Image {...part} />;\n\n case \"file\":\n return <File {...part} />;\n\n case \"audio\":\n return <Audio {...part} />;\n\n default:\n const unhandledType: never = type;\n throw new Error(`Unknown message part type: ${unhandledType}`);\n }\n};\n\ntype MessagePartProps = {\n partIndex: number;\n components: MessagePrimitiveUnstable_PartsGroupedByParentId.Props[\"components\"];\n};\n\nconst MessagePartImpl: FC<MessagePartProps> = ({ partIndex, components }) => {\n const messageRuntime = useMessageRuntime();\n const runtime = useMemo(\n () => messageRuntime.getMessagePartByIndex(partIndex),\n [messageRuntime, partIndex],\n );\n\n return (\n <MessagePartRuntimeProvider runtime={runtime}>\n <MessagePartComponent components={components} />\n </MessagePartRuntimeProvider>\n );\n};\n\nconst MessagePart = memo(\n MessagePartImpl,\n (prev, next) =>\n prev.partIndex === next.partIndex &&\n prev.components?.Text === next.components?.Text &&\n prev.components?.Reasoning === next.components?.Reasoning &&\n prev.components?.Source === next.components?.Source &&\n prev.components?.Image === next.components?.Image &&\n prev.components?.File === next.components?.File &&\n prev.components?.Unstable_Audio === next.components?.Unstable_Audio &&\n prev.components?.tools === next.components?.tools &&\n prev.components?.Group === next.components?.Group,\n);\n\nconst COMPLETE_STATUS: MessagePartStatus = Object.freeze({\n type: \"complete\",\n});\n\nconst EmptyPartFallback: FC<{\n status: MessagePartStatus;\n component: TextMessagePartComponent;\n}> = ({ status, component: Component }) => {\n return (\n <TextMessagePartProvider text=\"\" isRunning={status.type === \"running\"}>\n <Component type=\"text\" text=\"\" status={status} />\n </TextMessagePartProvider>\n );\n};\n\nconst EmptyPartsImpl: FC<MessagePartComponentProps> = ({ components }) => {\n const status =\n useMessage((s) => s.status as MessagePartStatus) ?? COMPLETE_STATUS;\n\n if (components?.Empty) return <components.Empty status={status} />;\n\n return (\n <EmptyPartFallback\n status={status}\n component={components?.Text ?? defaultComponents.Text}\n />\n );\n};\n\nconst EmptyParts = memo(\n EmptyPartsImpl,\n (prev, next) =>\n prev.components?.Empty === next.components?.Empty &&\n prev.components?.Text === next.components?.Text,\n);\n\n/**\n * Renders the parts of a message grouped by their parent ID.\n *\n * This component automatically groups message parts that share the same parent ID,\n * allowing you to create hierarchical or related content presentations. Parts without\n * a parent ID appear after grouped parts and remain ungrouped.\n *\n * @example\n * ```tsx\n * <MessagePrimitive.Unstable_PartsGroupedByParentId\n * components={{\n * Text: ({ text }) => <p className=\"message-text\">{text}</p>,\n * Image: ({ image }) => <img src={image} alt=\"Message image\" />,\n * Group: ({ parentId, indices, children }) => {\n * if (!parentId) return <>{children}</>;\n * return (\n * <div className=\"parent-group border rounded p-4\">\n * <h4>Related Content</h4>\n * {children}\n * </div>\n * );\n * }\n * }}\n * />\n * ```\n */\nexport const MessagePrimitiveUnstable_PartsGroupedByParentId: FC<\n MessagePrimitiveUnstable_PartsGroupedByParentId.Props\n> = ({ components }) => {\n const contentLength = useMessage((s) => s.content.length);\n const messageGroups = useMessagePartsGroupedByParentId();\n\n const partsElements = useMemo(() => {\n if (contentLength === 0) {\n return <EmptyParts components={components} />;\n }\n\n return messageGroups.map((group, groupIndex) => {\n const GroupComponent = components?.Group ?? defaultComponents.Group;\n\n return (\n <GroupComponent\n key={`group-${groupIndex}-${group.parentId ?? \"ungrouped\"}`}\n parentId={group.parentId}\n indices={group.indices}\n >\n {group.indices.map((partIndex) => (\n <MessagePart\n key={partIndex}\n partIndex={partIndex}\n components={components}\n />\n ))}\n </GroupComponent>\n );\n });\n }, [messageGroups, components, contentLength]);\n\n return <>{partsElements}</>;\n};\n\nMessagePrimitiveUnstable_PartsGroupedByParentId.displayName =\n \"MessagePrimitive.Unstable_PartsGroupedByParentId\";\n"],"mappings":"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","names":[]}
|
@@ -4,4 +4,5 @@ export { MessagePrimitiveParts as Content } from "./MessageParts";
|
|
4
4
|
export { MessagePrimitiveIf as If } from "./MessageIf";
|
5
5
|
export { MessagePrimitiveAttachments as Attachments } from "./MessageAttachments";
|
6
6
|
export { MessagePrimitiveError as Error } from "./MessageError";
|
7
|
+
export { MessagePrimitiveUnstable_PartsGroupedByParentId as Unstable_PartsGroupedByParentId } from "./MessagePartsGroupedByParentId";
|
7
8
|
//# sourceMappingURL=index.d.ts.map
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/primitives/message/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,IAAI,IAAI,EAAE,MAAM,eAAe,CAAC;AAC7D,OAAO,EAAE,qBAAqB,IAAI,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAChE,OAAO,EAAE,qBAAqB,IAAI,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAClE,OAAO,EAAE,kBAAkB,IAAI,EAAE,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,EAAE,2BAA2B,IAAI,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAClF,OAAO,EAAE,qBAAqB,IAAI,KAAK,EAAE,MAAM,gBAAgB,CAAC"}
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/primitives/message/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,IAAI,IAAI,EAAE,MAAM,eAAe,CAAC;AAC7D,OAAO,EAAE,qBAAqB,IAAI,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAChE,OAAO,EAAE,qBAAqB,IAAI,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAClE,OAAO,EAAE,kBAAkB,IAAI,EAAE,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,EAAE,2BAA2B,IAAI,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAClF,OAAO,EAAE,qBAAqB,IAAI,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAChE,OAAO,EAAE,+CAA+C,IAAI,+BAA+B,EAAE,MAAM,iCAAiC,CAAC"}
|
@@ -5,12 +5,14 @@ import { MessagePrimitiveParts as MessagePrimitiveParts2 } from "./MessageParts.
|
|
5
5
|
import { MessagePrimitiveIf } from "./MessageIf.js";
|
6
6
|
import { MessagePrimitiveAttachments } from "./MessageAttachments.js";
|
7
7
|
import { MessagePrimitiveError } from "./MessageError.js";
|
8
|
+
import { MessagePrimitiveUnstable_PartsGroupedByParentId } from "./MessagePartsGroupedByParentId.js";
|
8
9
|
export {
|
9
10
|
MessagePrimitiveAttachments as Attachments,
|
10
11
|
MessagePrimitiveParts2 as Content,
|
11
12
|
MessagePrimitiveError as Error,
|
12
13
|
MessagePrimitiveIf as If,
|
13
14
|
MessagePrimitiveParts as Parts,
|
14
|
-
MessagePrimitiveRoot as Root
|
15
|
+
MessagePrimitiveRoot as Root,
|
16
|
+
MessagePrimitiveUnstable_PartsGroupedByParentId as Unstable_PartsGroupedByParentId
|
15
17
|
};
|
16
18
|
//# sourceMappingURL=index.js.map
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["../../../src/primitives/message/index.ts"],"sourcesContent":["export { MessagePrimitiveRoot as Root } from \"./MessageRoot\";\nexport { MessagePrimitiveParts as Parts } from \"./MessageParts\";\nexport { MessagePrimitiveParts as Content } from \"./MessageParts\";\nexport { MessagePrimitiveIf as If } from \"./MessageIf\";\nexport { MessagePrimitiveAttachments as Attachments } from \"./MessageAttachments\";\nexport { MessagePrimitiveError as Error } from \"./MessageError\";\n"],"mappings":";AAAA,SAAiC,4BAAY;AAC7C,SAAkC,6BAAa;AAC/C,SAAkC,yBAAzBA,8BAAwC;AACjD,SAA+B,0BAAU;AACzC,SAAwC,mCAAmB;AAC3D,SAAkC,6BAAa;","names":["MessagePrimitiveParts"]}
|
1
|
+
{"version":3,"sources":["../../../src/primitives/message/index.ts"],"sourcesContent":["export { MessagePrimitiveRoot as Root } from \"./MessageRoot\";\nexport { MessagePrimitiveParts as Parts } from \"./MessageParts\";\nexport { MessagePrimitiveParts as Content } from \"./MessageParts\";\nexport { MessagePrimitiveIf as If } from \"./MessageIf\";\nexport { MessagePrimitiveAttachments as Attachments } from \"./MessageAttachments\";\nexport { MessagePrimitiveError as Error } from \"./MessageError\";\nexport { MessagePrimitiveUnstable_PartsGroupedByParentId as Unstable_PartsGroupedByParentId } from \"./MessagePartsGroupedByParentId\";\n"],"mappings":";AAAA,SAAiC,4BAAY;AAC7C,SAAkC,6BAAa;AAC/C,SAAkC,yBAAzBA,8BAAwC;AACjD,SAA+B,0BAAU;AACzC,SAAwC,mCAAmB;AAC3D,SAAkC,6BAAa;AAC/C,SAA4D,uDAAuC;","names":["MessagePrimitiveParts"]}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"ExternalStoreThreadRuntimeCore.d.ts","sourceRoot":"","sources":["../../../src/runtimes/external-store/ExternalStoreThreadRuntimeCore.tsx"],"names":[],"mappings":"AAAA,OAAO,EACL,oBAAoB,EACpB,cAAc,EACd,gBAAgB,EACjB,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC3D,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAS9D,OAAO,EACL,mBAAmB,EACnB,iBAAiB,EAClB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AACtE,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAI3D,eAAO,MAAM,kBAAkB,GAC7B,WAAW,OAAO,EAClB,UAAU,SAAS,aAAa,EAAE,YAGnC,CAAC;AAEF,qBAAa,8BACX,SAAQ,qBACR,YAAW,iBAAiB;IAE5B,OAAO,CAAC,qBAAqB,CAAuB;IAEpD,OAAO,CAAC,aAAa,CASnB;IAEF,IAAW,YAAY,wBAEtB;IAED,OAAO,CAAC,SAAS,CAA4B;IACtC,UAAU,EAAG,OAAO,CAAC;IAC5B,IAAW,SAAS,YAEnB;IAED,IAAoB,QAAQ,6BAE3B;IAED,IAAW,QAAQ;;;;;kBAElB;IAEM,WAAW,EAAE,SAAS,gBAAgB,EAAE,CAAM;IAC9C,MAAM,EAAE,OAAO,CAAa;IAEnC,OAAO,CAAC,UAAU,CAAgC;IAElD,OAAO,CAAC,MAAM,CAA6B;IAE3B,SAAS,CAAC,SAAS,EAAE,MAAM;gBAQzC,eAAe,EAAE,oBAAoB,EACrC,KAAK,EAAE,oBAAoB,CAAC,GAAG,CAAC;IAM3B,qBAAqB,CAAC,KAAK,EAAE,oBAAoB,CAAC,GAAG,CAAC;IAoG7C,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAQzC,MAAM,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAU7C,QAAQ,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAO/C,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IAIhC,SAAS,IAAI,IAAI;IAiCjB,aAAa,CAAC,OAAO,EAAE,oBAAoB;
|
1
|
+
{"version":3,"file":"ExternalStoreThreadRuntimeCore.d.ts","sourceRoot":"","sources":["../../../src/runtimes/external-store/ExternalStoreThreadRuntimeCore.tsx"],"names":[],"mappings":"AAAA,OAAO,EACL,oBAAoB,EACpB,cAAc,EACd,gBAAgB,EACjB,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC3D,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAS9D,OAAO,EACL,mBAAmB,EACnB,iBAAiB,EAClB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AACtE,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAI3D,eAAO,MAAM,kBAAkB,GAC7B,WAAW,OAAO,EAClB,UAAU,SAAS,aAAa,EAAE,YAGnC,CAAC;AAEF,qBAAa,8BACX,SAAQ,qBACR,YAAW,iBAAiB;IAE5B,OAAO,CAAC,qBAAqB,CAAuB;IAEpD,OAAO,CAAC,aAAa,CASnB;IAEF,IAAW,YAAY,wBAEtB;IAED,OAAO,CAAC,SAAS,CAA4B;IACtC,UAAU,EAAG,OAAO,CAAC;IAC5B,IAAW,SAAS,YAEnB;IAED,IAAoB,QAAQ,6BAE3B;IAED,IAAW,QAAQ;;;;;kBAElB;IAEM,WAAW,EAAE,SAAS,gBAAgB,EAAE,CAAM;IAC9C,MAAM,EAAE,OAAO,CAAa;IAEnC,OAAO,CAAC,UAAU,CAAgC;IAElD,OAAO,CAAC,MAAM,CAA6B;IAE3B,SAAS,CAAC,SAAS,EAAE,MAAM;gBAQzC,eAAe,EAAE,oBAAoB,EACrC,KAAK,EAAE,oBAAoB,CAAC,GAAG,CAAC;IAM3B,qBAAqB,CAAC,KAAK,EAAE,oBAAoB,CAAC,GAAG,CAAC;IAoG7C,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAQzC,MAAM,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAU7C,QAAQ,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAO/C,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IAIhC,SAAS,IAAI,IAAI;IAiCjB,aAAa,CAAC,OAAO,EAAE,oBAAoB;IAMlD,OAAO,CAAC,cAAc,CAUpB;CACH"}
|
@@ -174,14 +174,6 @@ var ExternalStoreThreadRuntimeCore = class extends BaseThreadRuntimeCore {
|
|
174
174
|
addToolResult(options) {
|
175
175
|
if (!this._store.onAddToolResult && !this._store.onAddToolResult)
|
176
176
|
throw new Error("Runtime does not support tool results.");
|
177
|
-
this._store.onAddToolResult?.({
|
178
|
-
messageId: options.messageId,
|
179
|
-
toolName: options.toolName,
|
180
|
-
toolCallId: options.toolCallId,
|
181
|
-
result: options.result,
|
182
|
-
isError: options.isError,
|
183
|
-
artifact: options.artifact
|
184
|
-
});
|
185
177
|
this._store.onAddToolResult?.(options);
|
186
178
|
}
|
187
179
|
updateMessages = (messages) => {
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["../../../src/runtimes/external-store/ExternalStoreThreadRuntimeCore.tsx"],"sourcesContent":["import {\n AddToolResultOptions,\n StartRunConfig,\n ThreadSuggestion,\n} from \"../core/ThreadRuntimeCore\";\n\nimport { AppendMessage, ThreadMessage } from \"../../types\";\nimport { ExternalStoreAdapter } from \"./ExternalStoreAdapter\";\nimport {\n getExternalStoreMessage,\n symbolInnerMessage,\n} from \"./getExternalStoreMessage\";\nimport { ThreadMessageConverter } from \"./ThreadMessageConverter\";\nimport { getAutoStatus, isAutoStatus } from \"./auto-status\";\nimport { fromThreadMessageLike } from \"./ThreadMessageLike\";\nimport { getThreadMessageText } from \"../../utils/getThreadMessageText\";\nimport {\n RuntimeCapabilities,\n ThreadRuntimeCore,\n} from \"../core/ThreadRuntimeCore\";\nimport { BaseThreadRuntimeCore } from \"../core/BaseThreadRuntimeCore\";\nimport { ModelContextProvider } from \"../../model-context\";\n\nconst EMPTY_ARRAY = Object.freeze([]);\n\nexport const hasUpcomingMessage = (\n isRunning: boolean,\n messages: readonly ThreadMessage[],\n) => {\n return isRunning && messages[messages.length - 1]?.role !== \"assistant\";\n};\n\nexport class ExternalStoreThreadRuntimeCore\n extends BaseThreadRuntimeCore\n implements ThreadRuntimeCore\n{\n private assistantOptimisticId: string | null = null;\n\n private _capabilities: RuntimeCapabilities = {\n switchToBranch: false,\n edit: false,\n reload: false,\n cancel: false,\n unstable_copy: false,\n speech: false,\n attachments: false,\n feedback: false,\n };\n\n public get capabilities() {\n return this._capabilities;\n }\n\n private _messages!: readonly ThreadMessage[];\n public isDisabled!: boolean;\n public get isLoading() {\n return this._store.isLoading ?? false;\n }\n\n public override get messages() {\n return this._messages;\n }\n\n public get adapters() {\n return this._store.adapters;\n }\n\n public suggestions: readonly ThreadSuggestion[] = [];\n public extras: unknown = undefined;\n\n private _converter = new ThreadMessageConverter();\n\n private _store!: ExternalStoreAdapter<any>;\n\n public override beginEdit(messageId: string) {\n if (!this._store.onEdit)\n throw new Error(\"Runtime does not support editing.\");\n\n super.beginEdit(messageId);\n }\n\n constructor(\n contextProvider: ModelContextProvider,\n store: ExternalStoreAdapter<any>,\n ) {\n super(contextProvider);\n this.__internal_setAdapter(store);\n }\n\n public __internal_setAdapter(store: ExternalStoreAdapter<any>) {\n if (this._store === store) return;\n\n const isRunning = store.isRunning ?? false;\n this.isDisabled = store.isDisabled ?? false;\n\n const oldStore = this._store as ExternalStoreAdapter<any> | undefined;\n this._store = store;\n this.extras = store.extras;\n this.suggestions = store.suggestions ?? EMPTY_ARRAY;\n this._capabilities = {\n switchToBranch: this._store.setMessages !== undefined,\n edit: this._store.onEdit !== undefined,\n reload: this._store.onReload !== undefined,\n cancel: this._store.onCancel !== undefined,\n speech: this._store.adapters?.speech !== undefined,\n unstable_copy: this._store.unstable_capabilities?.copy !== false, // default true\n attachments: !!this._store.adapters?.attachments,\n feedback: !!this._store.adapters?.feedback,\n };\n\n if (oldStore) {\n // flush the converter cache when the convertMessage prop changes\n if (oldStore.convertMessage !== store.convertMessage) {\n this._converter = new ThreadMessageConverter();\n } else if (\n oldStore.isRunning === store.isRunning &&\n oldStore.messages === store.messages\n ) {\n this._notifySubscribers();\n // no conversion update\n return;\n }\n }\n\n const messages = !store.convertMessage\n ? store.messages\n : this._converter.convertMessages(store.messages, (cache, m, idx) => {\n if (!store.convertMessage) return m;\n\n const isLast = idx === store.messages.length - 1;\n const autoStatus = getAutoStatus(isLast, isRunning);\n\n if (\n cache &&\n (cache.role !== \"assistant\" ||\n !isAutoStatus(cache.status) ||\n cache.status === autoStatus)\n )\n return cache;\n\n const messageLike = store.convertMessage(m, idx);\n const newMessage = fromThreadMessageLike(\n messageLike,\n idx.toString(),\n autoStatus,\n );\n (newMessage as any)[symbolInnerMessage] = m;\n return newMessage;\n });\n\n if (messages.length > 0) this.ensureInitialized();\n\n if (oldStore?.isRunning ?? false !== store.isRunning ?? false) {\n if (store.isRunning) {\n this._notifyEventSubscribers(\"run-start\");\n } else {\n this._notifyEventSubscribers(\"run-end\");\n }\n }\n\n for (let i = 0; i < messages.length; i++) {\n const message = messages[i]!;\n const parent = messages[i - 1];\n this.repository.addOrUpdateMessage(parent?.id ?? null, message);\n }\n\n if (this.assistantOptimisticId) {\n this.repository.deleteMessage(this.assistantOptimisticId);\n this.assistantOptimisticId = null;\n }\n\n if (hasUpcomingMessage(isRunning, messages)) {\n this.assistantOptimisticId = this.repository.appendOptimisticMessage(\n messages.at(-1)?.id ?? null,\n {\n role: \"assistant\",\n content: [],\n },\n );\n }\n\n this.repository.resetHead(\n this.assistantOptimisticId ?? messages.at(-1)?.id ?? null,\n );\n\n this._messages = this.repository.getMessages();\n this._notifySubscribers();\n }\n\n public override switchToBranch(branchId: string): void {\n if (!this._store.setMessages)\n throw new Error(\"Runtime does not support switching branches.\");\n\n this.repository.switchToBranch(branchId);\n this.updateMessages(this.repository.getMessages());\n }\n\n public async append(message: AppendMessage): Promise<void> {\n if (message.parentId !== (this.messages.at(-1)?.id ?? null)) {\n if (!this._store.onEdit)\n throw new Error(\"Runtime does not support editing messages.\");\n await this._store.onEdit(message);\n } else {\n await this._store.onNew(message);\n }\n }\n\n public async startRun(config: StartRunConfig): Promise<void> {\n if (!this._store.onReload)\n throw new Error(\"Runtime does not support reloading messages.\");\n\n await this._store.onReload(config.parentId, config);\n }\n\n public async resumeRun(): Promise<void> {\n throw new Error(\"Runtime does not support resuming runs.\");\n }\n\n public cancelRun(): void {\n if (!this._store.onCancel)\n throw new Error(\"Runtime does not support cancelling runs.\");\n\n this._store.onCancel();\n\n if (this.assistantOptimisticId) {\n this.repository.deleteMessage(this.assistantOptimisticId);\n this.assistantOptimisticId = null;\n }\n\n let messages = this.repository.getMessages();\n const previousMessage = messages[messages.length - 1];\n if (\n previousMessage?.role === \"user\" &&\n previousMessage.id === messages.at(-1)?.id // ensure the previous message is a leaf node\n ) {\n this.repository.deleteMessage(previousMessage.id);\n if (!this.composer.text.trim()) {\n this.composer.setText(getThreadMessageText(previousMessage));\n }\n\n messages = this.repository.getMessages();\n } else {\n this._notifySubscribers();\n }\n\n // resync messages (for reloading, to restore the previous branch)\n setTimeout(() => {\n this.updateMessages(messages);\n }, 0);\n }\n\n public addToolResult(options: AddToolResultOptions) {\n if (!this._store.onAddToolResult && !this._store.onAddToolResult)\n throw new Error(\"Runtime does not support tool results.\");\n this._store.onAddToolResult?.({\n messageId: options.messageId,\n toolName: options.toolName,\n toolCallId: options.toolCallId,\n result: options.result,\n isError: options.isError,\n artifact: options.artifact,\n });\n this._store.onAddToolResult?.(options);\n }\n\n private updateMessages = (messages: readonly ThreadMessage[]) => {\n const hasConverter = this._store.convertMessage !== undefined;\n if (hasConverter) {\n this._store.setMessages?.(\n messages.flatMap(getExternalStoreMessage).filter((m) => m != null),\n );\n } else {\n // TODO mark this as readonly in v0.8.0\n this._store.setMessages?.(messages as ThreadMessage[]);\n }\n };\n}\n"],"mappings":"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","names":[]}
|
1
|
+
{"version":3,"sources":["../../../src/runtimes/external-store/ExternalStoreThreadRuntimeCore.tsx"],"sourcesContent":["import {\n AddToolResultOptions,\n StartRunConfig,\n ThreadSuggestion,\n} from \"../core/ThreadRuntimeCore\";\n\nimport { AppendMessage, ThreadMessage } from \"../../types\";\nimport { ExternalStoreAdapter } from \"./ExternalStoreAdapter\";\nimport {\n getExternalStoreMessage,\n symbolInnerMessage,\n} from \"./getExternalStoreMessage\";\nimport { ThreadMessageConverter } from \"./ThreadMessageConverter\";\nimport { getAutoStatus, isAutoStatus } from \"./auto-status\";\nimport { fromThreadMessageLike } from \"./ThreadMessageLike\";\nimport { getThreadMessageText } from \"../../utils/getThreadMessageText\";\nimport {\n RuntimeCapabilities,\n ThreadRuntimeCore,\n} from \"../core/ThreadRuntimeCore\";\nimport { BaseThreadRuntimeCore } from \"../core/BaseThreadRuntimeCore\";\nimport { ModelContextProvider } from \"../../model-context\";\n\nconst EMPTY_ARRAY = Object.freeze([]);\n\nexport const hasUpcomingMessage = (\n isRunning: boolean,\n messages: readonly ThreadMessage[],\n) => {\n return isRunning && messages[messages.length - 1]?.role !== \"assistant\";\n};\n\nexport class ExternalStoreThreadRuntimeCore\n extends BaseThreadRuntimeCore\n implements ThreadRuntimeCore\n{\n private assistantOptimisticId: string | null = null;\n\n private _capabilities: RuntimeCapabilities = {\n switchToBranch: false,\n edit: false,\n reload: false,\n cancel: false,\n unstable_copy: false,\n speech: false,\n attachments: false,\n feedback: false,\n };\n\n public get capabilities() {\n return this._capabilities;\n }\n\n private _messages!: readonly ThreadMessage[];\n public isDisabled!: boolean;\n public get isLoading() {\n return this._store.isLoading ?? false;\n }\n\n public override get messages() {\n return this._messages;\n }\n\n public get adapters() {\n return this._store.adapters;\n }\n\n public suggestions: readonly ThreadSuggestion[] = [];\n public extras: unknown = undefined;\n\n private _converter = new ThreadMessageConverter();\n\n private _store!: ExternalStoreAdapter<any>;\n\n public override beginEdit(messageId: string) {\n if (!this._store.onEdit)\n throw new Error(\"Runtime does not support editing.\");\n\n super.beginEdit(messageId);\n }\n\n constructor(\n contextProvider: ModelContextProvider,\n store: ExternalStoreAdapter<any>,\n ) {\n super(contextProvider);\n this.__internal_setAdapter(store);\n }\n\n public __internal_setAdapter(store: ExternalStoreAdapter<any>) {\n if (this._store === store) return;\n\n const isRunning = store.isRunning ?? false;\n this.isDisabled = store.isDisabled ?? false;\n\n const oldStore = this._store as ExternalStoreAdapter<any> | undefined;\n this._store = store;\n this.extras = store.extras;\n this.suggestions = store.suggestions ?? EMPTY_ARRAY;\n this._capabilities = {\n switchToBranch: this._store.setMessages !== undefined,\n edit: this._store.onEdit !== undefined,\n reload: this._store.onReload !== undefined,\n cancel: this._store.onCancel !== undefined,\n speech: this._store.adapters?.speech !== undefined,\n unstable_copy: this._store.unstable_capabilities?.copy !== false, // default true\n attachments: !!this._store.adapters?.attachments,\n feedback: !!this._store.adapters?.feedback,\n };\n\n if (oldStore) {\n // flush the converter cache when the convertMessage prop changes\n if (oldStore.convertMessage !== store.convertMessage) {\n this._converter = new ThreadMessageConverter();\n } else if (\n oldStore.isRunning === store.isRunning &&\n oldStore.messages === store.messages\n ) {\n this._notifySubscribers();\n // no conversion update\n return;\n }\n }\n\n const messages = !store.convertMessage\n ? store.messages\n : this._converter.convertMessages(store.messages, (cache, m, idx) => {\n if (!store.convertMessage) return m;\n\n const isLast = idx === store.messages.length - 1;\n const autoStatus = getAutoStatus(isLast, isRunning);\n\n if (\n cache &&\n (cache.role !== \"assistant\" ||\n !isAutoStatus(cache.status) ||\n cache.status === autoStatus)\n )\n return cache;\n\n const messageLike = store.convertMessage(m, idx);\n const newMessage = fromThreadMessageLike(\n messageLike,\n idx.toString(),\n autoStatus,\n );\n (newMessage as any)[symbolInnerMessage] = m;\n return newMessage;\n });\n\n if (messages.length > 0) this.ensureInitialized();\n\n if (oldStore?.isRunning ?? false !== store.isRunning ?? false) {\n if (store.isRunning) {\n this._notifyEventSubscribers(\"run-start\");\n } else {\n this._notifyEventSubscribers(\"run-end\");\n }\n }\n\n for (let i = 0; i < messages.length; i++) {\n const message = messages[i]!;\n const parent = messages[i - 1];\n this.repository.addOrUpdateMessage(parent?.id ?? null, message);\n }\n\n if (this.assistantOptimisticId) {\n this.repository.deleteMessage(this.assistantOptimisticId);\n this.assistantOptimisticId = null;\n }\n\n if (hasUpcomingMessage(isRunning, messages)) {\n this.assistantOptimisticId = this.repository.appendOptimisticMessage(\n messages.at(-1)?.id ?? null,\n {\n role: \"assistant\",\n content: [],\n },\n );\n }\n\n this.repository.resetHead(\n this.assistantOptimisticId ?? messages.at(-1)?.id ?? null,\n );\n\n this._messages = this.repository.getMessages();\n this._notifySubscribers();\n }\n\n public override switchToBranch(branchId: string): void {\n if (!this._store.setMessages)\n throw new Error(\"Runtime does not support switching branches.\");\n\n this.repository.switchToBranch(branchId);\n this.updateMessages(this.repository.getMessages());\n }\n\n public async append(message: AppendMessage): Promise<void> {\n if (message.parentId !== (this.messages.at(-1)?.id ?? null)) {\n if (!this._store.onEdit)\n throw new Error(\"Runtime does not support editing messages.\");\n await this._store.onEdit(message);\n } else {\n await this._store.onNew(message);\n }\n }\n\n public async startRun(config: StartRunConfig): Promise<void> {\n if (!this._store.onReload)\n throw new Error(\"Runtime does not support reloading messages.\");\n\n await this._store.onReload(config.parentId, config);\n }\n\n public async resumeRun(): Promise<void> {\n throw new Error(\"Runtime does not support resuming runs.\");\n }\n\n public cancelRun(): void {\n if (!this._store.onCancel)\n throw new Error(\"Runtime does not support cancelling runs.\");\n\n this._store.onCancel();\n\n if (this.assistantOptimisticId) {\n this.repository.deleteMessage(this.assistantOptimisticId);\n this.assistantOptimisticId = null;\n }\n\n let messages = this.repository.getMessages();\n const previousMessage = messages[messages.length - 1];\n if (\n previousMessage?.role === \"user\" &&\n previousMessage.id === messages.at(-1)?.id // ensure the previous message is a leaf node\n ) {\n this.repository.deleteMessage(previousMessage.id);\n if (!this.composer.text.trim()) {\n this.composer.setText(getThreadMessageText(previousMessage));\n }\n\n messages = this.repository.getMessages();\n } else {\n this._notifySubscribers();\n }\n\n // resync messages (for reloading, to restore the previous branch)\n setTimeout(() => {\n this.updateMessages(messages);\n }, 0);\n }\n\n public addToolResult(options: AddToolResultOptions) {\n if (!this._store.onAddToolResult && !this._store.onAddToolResult)\n throw new Error(\"Runtime does not support tool results.\");\n this._store.onAddToolResult?.(options);\n }\n\n private updateMessages = (messages: readonly ThreadMessage[]) => {\n const hasConverter = this._store.convertMessage !== undefined;\n if (hasConverter) {\n this._store.setMessages?.(\n messages.flatMap(getExternalStoreMessage).filter((m) => m != null),\n );\n } else {\n // TODO mark this as readonly in v0.8.0\n this._store.setMessages?.(messages as ThreadMessage[]);\n }\n };\n}\n"],"mappings":"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","names":[]}
|
@@ -12,6 +12,7 @@ export type ThreadMessageLike = {
|
|
12
12
|
readonly artifact?: any;
|
13
13
|
readonly result?: any | undefined;
|
14
14
|
readonly isError?: boolean | undefined;
|
15
|
+
readonly parentId?: string | undefined;
|
15
16
|
})[];
|
16
17
|
readonly id?: string | undefined;
|
17
18
|
readonly createdAt?: Date | undefined;
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"ThreadMessageLike.d.ts","sourceRoot":"","sources":["../../../src/runtimes/external-store/ThreadMessageLike.tsx"],"names":[],"mappings":"AAEA,OAAO,EACL,aAAa,EACb,eAAe,EACf,gBAAgB,EAChB,aAAa,EAMb,kBAAkB,EAClB,eAAe,EACf,yBAAyB,EAC1B,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,oBAAoB,EACpB,iBAAiB,EACjB,UAAU,EACX,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAE/E,MAAM,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,CAAC,IAAI,EAAE,WAAW,GAAG,MAAM,GAAG,QAAQ,CAAC;IAC/C,QAAQ,CAAC,OAAO,EACZ,MAAM,GACN,SAAS,CACL,eAAe,GACf,oBAAoB,GACpB,iBAAiB,GACjB,gBAAgB,GAChB,eAAe,GACf,yBAAyB,GACzB;QACE,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;QAC3B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;QAC7B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;QAC1B,QAAQ,CAAC,IAAI,CAAC,EAAE,kBAAkB,CAAC;QACnC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAC3B,QAAQ,CAAC,QAAQ,CAAC,EAAE,GAAG,CAAC;QACxB,QAAQ,CAAC,MAAM,CAAC,EAAE,GAAG,GAAG,SAAS,CAAC;QAClC,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;KACxC,CACJ,EAAE,CAAC;IACR,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,QAAQ,CAAC,SAAS,CAAC,EAAE,IAAI,GAAG,SAAS,CAAC;IACtC,QAAQ,CAAC,MAAM,CAAC,EAAE,aAAa,GAAG,SAAS,CAAC;IAC5C,QAAQ,CAAC,WAAW,CAAC,EAAE,SAAS,kBAAkB,EAAE,GAAG,SAAS,CAAC;IACjE,QAAQ,CAAC,QAAQ,CAAC,EACd;QACE,QAAQ,CAAC,cAAc,CAAC,EAAE,iBAAiB,CAAC;QAC5C,QAAQ,CAAC,oBAAoB,CAAC,EAC1B,SAAS,iBAAiB,EAAE,GAC5B,SAAS,CAAC;QACd,QAAQ,CAAC,aAAa,CAAC,EAAE,SAAS,iBAAiB,EAAE,GAAG,SAAS,CAAC;QAClE,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,UAAU,EAAE,GAAG,SAAS,CAAC;QACnD,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;KACvD,GACD,SAAS,CAAC;CACf,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAChC,MAAM,iBAAiB,EACvB,YAAY,MAAM,EAClB,gBAAgB,aAAa,KAC5B,
|
1
|
+
{"version":3,"file":"ThreadMessageLike.d.ts","sourceRoot":"","sources":["../../../src/runtimes/external-store/ThreadMessageLike.tsx"],"names":[],"mappings":"AAEA,OAAO,EACL,aAAa,EACb,eAAe,EACf,gBAAgB,EAChB,aAAa,EAMb,kBAAkB,EAClB,eAAe,EACf,yBAAyB,EAC1B,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,oBAAoB,EACpB,iBAAiB,EACjB,UAAU,EACX,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAE/E,MAAM,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,CAAC,IAAI,EAAE,WAAW,GAAG,MAAM,GAAG,QAAQ,CAAC;IAC/C,QAAQ,CAAC,OAAO,EACZ,MAAM,GACN,SAAS,CACL,eAAe,GACf,oBAAoB,GACpB,iBAAiB,GACjB,gBAAgB,GAChB,eAAe,GACf,yBAAyB,GACzB;QACE,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;QAC3B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;QAC7B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;QAC1B,QAAQ,CAAC,IAAI,CAAC,EAAE,kBAAkB,CAAC;QACnC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAC3B,QAAQ,CAAC,QAAQ,CAAC,EAAE,GAAG,CAAC;QACxB,QAAQ,CAAC,MAAM,CAAC,EAAE,GAAG,GAAG,SAAS,CAAC;QAClC,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;QACvC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;KACxC,CACJ,EAAE,CAAC;IACR,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,QAAQ,CAAC,SAAS,CAAC,EAAE,IAAI,GAAG,SAAS,CAAC;IACtC,QAAQ,CAAC,MAAM,CAAC,EAAE,aAAa,GAAG,SAAS,CAAC;IAC5C,QAAQ,CAAC,WAAW,CAAC,EAAE,SAAS,kBAAkB,EAAE,GAAG,SAAS,CAAC;IACjE,QAAQ,CAAC,QAAQ,CAAC,EACd;QACE,QAAQ,CAAC,cAAc,CAAC,EAAE,iBAAiB,CAAC;QAC5C,QAAQ,CAAC,oBAAoB,CAAC,EAC1B,SAAS,iBAAiB,EAAE,GAC5B,SAAS,CAAC;QACd,QAAQ,CAAC,aAAa,CAAC,EAAE,SAAS,iBAAiB,EAAE,GAAG,SAAS,CAAC;QAClE,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,UAAU,EAAE,GAAG,SAAS,CAAC;QACnD,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;KACvD,GACD,SAAS,CAAC;CACf,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAChC,MAAM,iBAAiB,EACvB,YAAY,MAAM,EAClB,gBAAgB,aAAa,KAC5B,aAkIF,CAAC"}
|
@@ -1,6 +1,6 @@
|
|
1
1
|
// src/runtimes/external-store/ThreadMessageLike.tsx
|
2
2
|
import { parsePartialJsonObject } from "assistant-stream/utils";
|
3
|
-
import { generateId } from "../../
|
3
|
+
import { generateId } from "../../utils/idUtils.js";
|
4
4
|
var fromThreadMessageLike = (like, fallbackId, fallbackStatus) => {
|
5
5
|
const { role, id, createdAt, attachments, status, metadata } = like;
|
6
6
|
const common = {
|
@@ -30,17 +30,21 @@ var fromThreadMessageLike = (like, fallbackId, fallbackStatus) => {
|
|
30
30
|
case "source":
|
31
31
|
return part;
|
32
32
|
case "tool-call": {
|
33
|
+
const { parentId, ...basePart } = part;
|
34
|
+
const commonProps = {
|
35
|
+
...basePart,
|
36
|
+
toolCallId: part.toolCallId ?? "tool-" + generateId(),
|
37
|
+
...parentId !== void 0 && { parentId }
|
38
|
+
};
|
33
39
|
if (part.args) {
|
34
40
|
return {
|
35
|
-
...
|
36
|
-
toolCallId: part.toolCallId ?? "tool-" + generateId(),
|
41
|
+
...commonProps,
|
37
42
|
args: part.args,
|
38
43
|
argsText: JSON.stringify(part.args)
|
39
44
|
};
|
40
45
|
}
|
41
46
|
return {
|
42
|
-
...
|
43
|
-
toolCallId: part.toolCallId ?? "tool-" + generateId(),
|
47
|
+
...commonProps,
|
44
48
|
args: part.args ?? parsePartialJsonObject(part.argsText ?? "") ?? {},
|
45
49
|
argsText: part.argsText ?? ""
|
46
50
|
};
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["../../../src/runtimes/external-store/ThreadMessageLike.tsx"],"sourcesContent":["import { parsePartialJsonObject } from \"assistant-stream/utils\";\nimport { generateId } from \"../../
|
1
|
+
{"version":3,"sources":["../../../src/runtimes/external-store/ThreadMessageLike.tsx"],"sourcesContent":["import { parsePartialJsonObject } from \"assistant-stream/utils\";\nimport { generateId } from \"../../utils/idUtils\";\nimport {\n MessageStatus,\n TextMessagePart,\n ImageMessagePart,\n ThreadMessage,\n ThreadAssistantMessagePart,\n ThreadAssistantMessage,\n ThreadUserMessagePart,\n ThreadUserMessage,\n ThreadSystemMessage,\n CompleteAttachment,\n FileMessagePart,\n Unstable_AudioMessagePart,\n} from \"../../types\";\nimport {\n ReasoningMessagePart,\n SourceMessagePart,\n ThreadStep,\n} from \"../../types/AssistantTypes\";\nimport { ReadonlyJSONObject, ReadonlyJSONValue } from \"assistant-stream/utils\";\n\nexport type ThreadMessageLike = {\n readonly role: \"assistant\" | \"user\" | \"system\";\n readonly content:\n | string\n | readonly (\n | TextMessagePart\n | ReasoningMessagePart\n | SourceMessagePart\n | ImageMessagePart\n | FileMessagePart\n | Unstable_AudioMessagePart\n | {\n readonly type: \"tool-call\";\n readonly toolCallId?: string;\n readonly toolName: string;\n readonly args?: ReadonlyJSONObject;\n readonly argsText?: string;\n readonly artifact?: any;\n readonly result?: any | undefined;\n readonly isError?: boolean | undefined;\n readonly parentId?: string | undefined;\n }\n )[];\n readonly id?: string | undefined;\n readonly createdAt?: Date | undefined;\n readonly status?: MessageStatus | undefined;\n readonly attachments?: readonly CompleteAttachment[] | undefined;\n readonly metadata?:\n | {\n readonly unstable_state?: ReadonlyJSONValue;\n readonly unstable_annotations?:\n | readonly ReadonlyJSONValue[]\n | undefined;\n readonly unstable_data?: readonly ReadonlyJSONValue[] | undefined;\n readonly steps?: readonly ThreadStep[] | undefined;\n readonly custom?: Record<string, unknown> | undefined;\n }\n | undefined;\n};\n\nexport const fromThreadMessageLike = (\n like: ThreadMessageLike,\n fallbackId: string,\n fallbackStatus: MessageStatus,\n): ThreadMessage => {\n const { role, id, createdAt, attachments, status, metadata } = like;\n const common = {\n id: id ?? fallbackId,\n createdAt: createdAt ?? new Date(),\n };\n\n const content =\n typeof like.content === \"string\"\n ? [{ type: \"text\" as const, text: like.content }]\n : like.content;\n\n if (role !== \"user\" && attachments?.length)\n throw new Error(\"attachments are only supported for user messages\");\n\n if (role !== \"assistant\" && status)\n throw new Error(\"status is only supported for assistant messages\");\n\n if (role !== \"assistant\" && metadata?.steps)\n throw new Error(\"metadata.steps is only supported for assistant messages\");\n\n switch (role) {\n case \"assistant\":\n return {\n ...common,\n role,\n content: content\n .map((part): ThreadAssistantMessagePart | null => {\n const type = part.type;\n switch (type) {\n case \"text\":\n case \"reasoning\":\n if (part.text.trim().length === 0) return null;\n return part;\n\n case \"file\":\n case \"source\":\n return part;\n\n case \"tool-call\": {\n const { parentId, ...basePart } = part;\n const commonProps = {\n ...basePart,\n toolCallId: part.toolCallId ?? \"tool-\" + generateId(),\n ...(parentId !== undefined && { parentId }),\n };\n\n if (part.args) {\n return {\n ...commonProps,\n args: part.args,\n argsText: JSON.stringify(part.args),\n };\n }\n return {\n ...commonProps,\n args:\n part.args ??\n parsePartialJsonObject(part.argsText ?? \"\") ??\n {},\n argsText: part.argsText ?? \"\",\n };\n }\n\n default: {\n const unhandledType: \"image\" | \"audio\" = type;\n throw new Error(\n `Unsupported assistant message part type: ${unhandledType}`,\n );\n }\n }\n })\n .filter((c) => !!c),\n status: status ?? fallbackStatus,\n metadata: {\n unstable_state: metadata?.unstable_state ?? null,\n unstable_annotations: metadata?.unstable_annotations ?? [],\n unstable_data: metadata?.unstable_data ?? [],\n custom: metadata?.custom ?? {},\n steps: metadata?.steps ?? [],\n },\n } satisfies ThreadAssistantMessage;\n\n case \"user\":\n return {\n ...common,\n role,\n content: content.map((part): ThreadUserMessagePart => {\n const type = part.type;\n switch (type) {\n case \"text\":\n case \"image\":\n case \"audio\":\n case \"file\":\n return part;\n\n default: {\n const unhandledType: \"tool-call\" | \"reasoning\" | \"source\" = type;\n throw new Error(\n `Unsupported user message part type: ${unhandledType}`,\n );\n }\n }\n }),\n attachments: attachments ?? [],\n metadata: {\n custom: metadata?.custom ?? {},\n },\n } satisfies ThreadUserMessage;\n\n case \"system\":\n if (content.length !== 1 || content[0]!.type !== \"text\")\n throw new Error(\n \"System messages must have exactly one text message part.\",\n );\n\n return {\n ...common,\n role,\n content: content as [TextMessagePart],\n metadata: {\n custom: metadata?.custom ?? {},\n },\n } satisfies ThreadSystemMessage;\n\n default: {\n const unsupportedRole: never = role;\n throw new Error(`Unknown message role: ${unsupportedRole}`);\n }\n }\n};\n"],"mappings":"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","names":[]}
|
@@ -4,10 +4,12 @@ export type MessageRole = ThreadMessage["role"];
|
|
4
4
|
export type TextMessagePart = {
|
5
5
|
readonly type: "text";
|
6
6
|
readonly text: string;
|
7
|
+
readonly parentId?: string;
|
7
8
|
};
|
8
9
|
export type ReasoningMessagePart = {
|
9
10
|
readonly type: "reasoning";
|
10
11
|
readonly text: string;
|
12
|
+
readonly parentId?: string;
|
11
13
|
};
|
12
14
|
export type SourceMessagePart = {
|
13
15
|
readonly type: "source";
|
@@ -15,6 +17,7 @@ export type SourceMessagePart = {
|
|
15
17
|
readonly id: string;
|
16
18
|
readonly url: string;
|
17
19
|
readonly title?: string;
|
20
|
+
readonly parentId?: string;
|
18
21
|
};
|
19
22
|
export type ImageMessagePart = {
|
20
23
|
readonly type: "image";
|
@@ -41,6 +44,7 @@ export type ToolCallMessagePart<TArgs = ReadonlyJSONObject, TResult = unknown> =
|
|
41
44
|
readonly isError?: boolean | undefined;
|
42
45
|
readonly argsText: string;
|
43
46
|
readonly artifact?: unknown;
|
47
|
+
readonly parentId?: string;
|
44
48
|
};
|
45
49
|
export type ThreadUserMessagePart = TextMessagePart | ImageMessagePart | FileMessagePart | Unstable_AudioMessagePart;
|
46
50
|
export type ThreadAssistantMessagePart = TextMessagePart | ReasoningMessagePart | ToolCallMessagePart | SourceMessagePart | FileMessagePart;
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"AssistantTypes.d.ts","sourceRoot":"","sources":["../../src/types/AssistantTypes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAE/E,MAAM,MAAM,WAAW,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;AAEhD,MAAM,MAAM,eAAe,GAAG;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;
|
1
|
+
{"version":3,"file":"AssistantTypes.d.ts","sourceRoot":"","sources":["../../src/types/AssistantTypes.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
@@ -28,7 +28,7 @@
|
|
28
28
|
"conversational-ui",
|
29
29
|
"conversational-ai"
|
30
30
|
],
|
31
|
-
"version": "0.10.
|
31
|
+
"version": "0.10.27",
|
32
32
|
"license": "MIT",
|
33
33
|
"type": "module",
|
34
34
|
"exports": {
|
@@ -57,7 +57,7 @@
|
|
57
57
|
"@radix-ui/react-use-callback-ref": "^1.1.1",
|
58
58
|
"@radix-ui/react-use-escape-keydown": "^1.1.1",
|
59
59
|
"@standard-schema/spec": "^1.0.0",
|
60
|
-
"assistant-stream": "^0.2.
|
60
|
+
"assistant-stream": "^0.2.20",
|
61
61
|
"json-schema": "^0.4.0",
|
62
62
|
"nanoid": "5.1.5",
|
63
63
|
"react-textarea-autosize": "^8.5.9",
|
@@ -0,0 +1,415 @@
|
|
1
|
+
"use client";
|
2
|
+
|
3
|
+
import {
|
4
|
+
type ComponentType,
|
5
|
+
type FC,
|
6
|
+
memo,
|
7
|
+
PropsWithChildren,
|
8
|
+
useMemo,
|
9
|
+
} from "react";
|
10
|
+
import {
|
11
|
+
TextMessagePartProvider,
|
12
|
+
useMessagePart,
|
13
|
+
useMessagePartRuntime,
|
14
|
+
useToolUIs,
|
15
|
+
} from "../../context";
|
16
|
+
import {
|
17
|
+
useMessage,
|
18
|
+
useMessageRuntime,
|
19
|
+
} from "../../context/react/MessageContext";
|
20
|
+
import { MessagePartRuntimeProvider } from "../../context/providers/MessagePartRuntimeProvider";
|
21
|
+
import { MessagePartPrimitiveText } from "../messagePart/MessagePartText";
|
22
|
+
import { MessagePartPrimitiveImage } from "../messagePart/MessagePartImage";
|
23
|
+
import type {
|
24
|
+
Unstable_AudioMessagePartComponent,
|
25
|
+
EmptyMessagePartComponent,
|
26
|
+
TextMessagePartComponent,
|
27
|
+
ImageMessagePartComponent,
|
28
|
+
SourceMessagePartComponent,
|
29
|
+
ToolCallMessagePartComponent,
|
30
|
+
ToolCallMessagePartProps,
|
31
|
+
FileMessagePartComponent,
|
32
|
+
ReasoningMessagePartComponent,
|
33
|
+
} from "../../types/MessagePartComponentTypes";
|
34
|
+
import { MessagePartPrimitiveInProgress } from "../messagePart/MessagePartInProgress";
|
35
|
+
import { MessagePartStatus } from "../../types/AssistantTypes";
|
36
|
+
|
37
|
+
type MessagePartGroup = {
|
38
|
+
parentId: string | undefined;
|
39
|
+
indices: number[];
|
40
|
+
};
|
41
|
+
|
42
|
+
/**
|
43
|
+
* Groups message parts by their parent ID.
|
44
|
+
* Parts without a parent ID appear after grouped parts and remain ungrouped.
|
45
|
+
* The position of groups is based on the first occurrence of each parent ID.
|
46
|
+
*/
|
47
|
+
const groupMessagePartsByParentId = (
|
48
|
+
parts: readonly any[],
|
49
|
+
): MessagePartGroup[] => {
|
50
|
+
const groups: MessagePartGroup[] = [];
|
51
|
+
const parentIdToGroupIndex = new Map<string | undefined, number>();
|
52
|
+
const processedIndices = new Set<number>();
|
53
|
+
|
54
|
+
// First pass: process all parts with parent IDs
|
55
|
+
for (let i = 0; i < parts.length; i++) {
|
56
|
+
const part = parts[i];
|
57
|
+
const parentId = part?.parentId as string | undefined;
|
58
|
+
|
59
|
+
if (parentId !== undefined) {
|
60
|
+
let groupIndex = parentIdToGroupIndex.get(parentId);
|
61
|
+
|
62
|
+
if (groupIndex === undefined) {
|
63
|
+
// Create new group for this parent ID
|
64
|
+
groupIndex = groups.length;
|
65
|
+
groups.push({ parentId, indices: [] });
|
66
|
+
parentIdToGroupIndex.set(parentId, groupIndex);
|
67
|
+
}
|
68
|
+
|
69
|
+
groups[groupIndex]!.indices.push(i);
|
70
|
+
processedIndices.add(i);
|
71
|
+
}
|
72
|
+
}
|
73
|
+
|
74
|
+
// Second pass: add ungrouped parts (those without parent ID)
|
75
|
+
for (let i = 0; i < parts.length; i++) {
|
76
|
+
if (!processedIndices.has(i)) {
|
77
|
+
// Add individual group for parts without parent ID
|
78
|
+
groups.push({ parentId: undefined, indices: [i] });
|
79
|
+
}
|
80
|
+
}
|
81
|
+
|
82
|
+
return groups;
|
83
|
+
};
|
84
|
+
|
85
|
+
const useMessagePartsGroupedByParentId = (): MessagePartGroup[] => {
|
86
|
+
const parts = useMessage((m) => m.content);
|
87
|
+
|
88
|
+
return useMemo(() => {
|
89
|
+
if (parts.length === 0) {
|
90
|
+
return [];
|
91
|
+
}
|
92
|
+
return groupMessagePartsByParentId(parts);
|
93
|
+
}, [parts]);
|
94
|
+
};
|
95
|
+
|
96
|
+
export namespace MessagePrimitiveUnstable_PartsGroupedByParentId {
|
97
|
+
export type Props = {
|
98
|
+
/**
|
99
|
+
* Component configuration for rendering different types of message content.
|
100
|
+
*
|
101
|
+
* You can provide custom components for each content type (text, image, file, etc.)
|
102
|
+
* and configure tool rendering behavior. If not provided, default components will be used.
|
103
|
+
*/
|
104
|
+
components?:
|
105
|
+
| {
|
106
|
+
/** Component for rendering empty messages */
|
107
|
+
Empty?: EmptyMessagePartComponent | undefined;
|
108
|
+
/** Component for rendering text content */
|
109
|
+
Text?: TextMessagePartComponent | undefined;
|
110
|
+
/** Component for rendering reasoning content (typically hidden) */
|
111
|
+
Reasoning?: ReasoningMessagePartComponent | undefined;
|
112
|
+
/** Component for rendering source content */
|
113
|
+
Source?: SourceMessagePartComponent | undefined;
|
114
|
+
/** Component for rendering image content */
|
115
|
+
Image?: ImageMessagePartComponent | undefined;
|
116
|
+
/** Component for rendering file content */
|
117
|
+
File?: FileMessagePartComponent | undefined;
|
118
|
+
/** Component for rendering audio content (experimental) */
|
119
|
+
Unstable_Audio?: Unstable_AudioMessagePartComponent | undefined;
|
120
|
+
/** Configuration for tool call rendering */
|
121
|
+
tools?:
|
122
|
+
| {
|
123
|
+
/** Map of tool names to their specific components */
|
124
|
+
by_name?:
|
125
|
+
| Record<string, ToolCallMessagePartComponent | undefined>
|
126
|
+
| undefined;
|
127
|
+
/** Fallback component for unregistered tools */
|
128
|
+
Fallback?: ComponentType<ToolCallMessagePartProps> | undefined;
|
129
|
+
}
|
130
|
+
| {
|
131
|
+
/** Override component that handles all tool calls */
|
132
|
+
Override: ComponentType<ToolCallMessagePartProps>;
|
133
|
+
}
|
134
|
+
| undefined;
|
135
|
+
|
136
|
+
/**
|
137
|
+
* Component for rendering grouped message parts with the same parent ID.
|
138
|
+
*
|
139
|
+
* When provided, this component will automatically wrap message parts that share
|
140
|
+
* the same parent ID, allowing you to create collapsible sections, custom styling,
|
141
|
+
* or other grouped presentations.
|
142
|
+
*
|
143
|
+
* The component receives:
|
144
|
+
* - `parentId`: The parent ID shared by all parts in the group (or undefined for ungrouped parts)
|
145
|
+
* - `indices`: Array of indices for the parts in this group
|
146
|
+
* - `children`: The rendered message part components
|
147
|
+
*
|
148
|
+
* @example
|
149
|
+
* ```tsx
|
150
|
+
* // Collapsible parent ID group
|
151
|
+
* Group: ({ parentId, indices, children }) => {
|
152
|
+
* if (!parentId) return <>{children}</>;
|
153
|
+
* return (
|
154
|
+
* <details className="parent-group">
|
155
|
+
* <summary>
|
156
|
+
* Group {parentId} ({indices.length} parts)
|
157
|
+
* </summary>
|
158
|
+
* <div className="parent-group-content">
|
159
|
+
* {children}
|
160
|
+
* </div>
|
161
|
+
* </details>
|
162
|
+
* );
|
163
|
+
* }
|
164
|
+
* ```
|
165
|
+
*
|
166
|
+
* @example
|
167
|
+
* ```tsx
|
168
|
+
* // Custom styled parent ID group
|
169
|
+
* Group: ({ parentId, indices, children }) => {
|
170
|
+
* if (!parentId) return <>{children}</>;
|
171
|
+
* return (
|
172
|
+
* <div className="border rounded-lg p-4 my-2">
|
173
|
+
* <div className="text-sm text-gray-600 mb-2">
|
174
|
+
* Related content ({parentId})
|
175
|
+
* </div>
|
176
|
+
* <div className="space-y-2">
|
177
|
+
* {children}
|
178
|
+
* </div>
|
179
|
+
* </div>
|
180
|
+
* );
|
181
|
+
* }
|
182
|
+
* ```
|
183
|
+
*
|
184
|
+
* @param parentId - The parent ID shared by all parts in this group (undefined for ungrouped parts)
|
185
|
+
* @param indices - Array of indices for the parts in this group
|
186
|
+
* @param children - Rendered message part components to display within the group
|
187
|
+
*/
|
188
|
+
Group?: ComponentType<
|
189
|
+
PropsWithChildren<{
|
190
|
+
parentId: string | undefined;
|
191
|
+
indices: number[];
|
192
|
+
}>
|
193
|
+
>;
|
194
|
+
}
|
195
|
+
| undefined;
|
196
|
+
};
|
197
|
+
}
|
198
|
+
|
199
|
+
const ToolUIDisplay = ({
|
200
|
+
Fallback,
|
201
|
+
...props
|
202
|
+
}: {
|
203
|
+
Fallback: ToolCallMessagePartComponent | undefined;
|
204
|
+
} & ToolCallMessagePartProps) => {
|
205
|
+
const Render = useToolUIs((s) => s.getToolUI(props.toolName)) ?? Fallback;
|
206
|
+
if (!Render) return null;
|
207
|
+
return <Render {...props} />;
|
208
|
+
};
|
209
|
+
|
210
|
+
const defaultComponents = {
|
211
|
+
Text: () => (
|
212
|
+
<p style={{ whiteSpace: "pre-line" }}>
|
213
|
+
<MessagePartPrimitiveText />
|
214
|
+
<MessagePartPrimitiveInProgress>
|
215
|
+
<span style={{ fontFamily: "revert" }}>{" \u25CF"}</span>
|
216
|
+
</MessagePartPrimitiveInProgress>
|
217
|
+
</p>
|
218
|
+
),
|
219
|
+
Reasoning: () => null,
|
220
|
+
Source: () => null,
|
221
|
+
Image: () => <MessagePartPrimitiveImage />,
|
222
|
+
File: () => null,
|
223
|
+
Unstable_Audio: () => null,
|
224
|
+
Group: ({ children }) => children,
|
225
|
+
} satisfies MessagePrimitiveUnstable_PartsGroupedByParentId.Props["components"];
|
226
|
+
|
227
|
+
type MessagePartComponentProps = {
|
228
|
+
components: MessagePrimitiveUnstable_PartsGroupedByParentId.Props["components"];
|
229
|
+
};
|
230
|
+
|
231
|
+
const MessagePartComponent: FC<MessagePartComponentProps> = ({
|
232
|
+
components: {
|
233
|
+
Text = defaultComponents.Text,
|
234
|
+
Reasoning = defaultComponents.Reasoning,
|
235
|
+
Image = defaultComponents.Image,
|
236
|
+
Source = defaultComponents.Source,
|
237
|
+
File = defaultComponents.File,
|
238
|
+
Unstable_Audio: Audio = defaultComponents.Unstable_Audio,
|
239
|
+
tools = {},
|
240
|
+
} = {},
|
241
|
+
}) => {
|
242
|
+
const MessagePartRuntime = useMessagePartRuntime();
|
243
|
+
|
244
|
+
const part = useMessagePart();
|
245
|
+
|
246
|
+
const type = part.type;
|
247
|
+
if (type === "tool-call") {
|
248
|
+
const addResult = (result: any) => MessagePartRuntime.addToolResult(result);
|
249
|
+
if ("Override" in tools)
|
250
|
+
return <tools.Override {...part} addResult={addResult} />;
|
251
|
+
const Tool = tools.by_name?.[part.toolName] ?? tools.Fallback;
|
252
|
+
return <ToolUIDisplay {...part} Fallback={Tool} addResult={addResult} />;
|
253
|
+
}
|
254
|
+
|
255
|
+
if (part.status.type === "requires-action")
|
256
|
+
throw new Error("Encountered unexpected requires-action status");
|
257
|
+
|
258
|
+
switch (type) {
|
259
|
+
case "text":
|
260
|
+
return <Text {...part} />;
|
261
|
+
|
262
|
+
case "reasoning":
|
263
|
+
return <Reasoning {...part} />;
|
264
|
+
|
265
|
+
case "source":
|
266
|
+
return <Source {...part} />;
|
267
|
+
|
268
|
+
case "image":
|
269
|
+
// eslint-disable-next-line jsx-a11y/alt-text
|
270
|
+
return <Image {...part} />;
|
271
|
+
|
272
|
+
case "file":
|
273
|
+
return <File {...part} />;
|
274
|
+
|
275
|
+
case "audio":
|
276
|
+
return <Audio {...part} />;
|
277
|
+
|
278
|
+
default:
|
279
|
+
const unhandledType: never = type;
|
280
|
+
throw new Error(`Unknown message part type: ${unhandledType}`);
|
281
|
+
}
|
282
|
+
};
|
283
|
+
|
284
|
+
type MessagePartProps = {
|
285
|
+
partIndex: number;
|
286
|
+
components: MessagePrimitiveUnstable_PartsGroupedByParentId.Props["components"];
|
287
|
+
};
|
288
|
+
|
289
|
+
const MessagePartImpl: FC<MessagePartProps> = ({ partIndex, components }) => {
|
290
|
+
const messageRuntime = useMessageRuntime();
|
291
|
+
const runtime = useMemo(
|
292
|
+
() => messageRuntime.getMessagePartByIndex(partIndex),
|
293
|
+
[messageRuntime, partIndex],
|
294
|
+
);
|
295
|
+
|
296
|
+
return (
|
297
|
+
<MessagePartRuntimeProvider runtime={runtime}>
|
298
|
+
<MessagePartComponent components={components} />
|
299
|
+
</MessagePartRuntimeProvider>
|
300
|
+
);
|
301
|
+
};
|
302
|
+
|
303
|
+
const MessagePart = memo(
|
304
|
+
MessagePartImpl,
|
305
|
+
(prev, next) =>
|
306
|
+
prev.partIndex === next.partIndex &&
|
307
|
+
prev.components?.Text === next.components?.Text &&
|
308
|
+
prev.components?.Reasoning === next.components?.Reasoning &&
|
309
|
+
prev.components?.Source === next.components?.Source &&
|
310
|
+
prev.components?.Image === next.components?.Image &&
|
311
|
+
prev.components?.File === next.components?.File &&
|
312
|
+
prev.components?.Unstable_Audio === next.components?.Unstable_Audio &&
|
313
|
+
prev.components?.tools === next.components?.tools &&
|
314
|
+
prev.components?.Group === next.components?.Group,
|
315
|
+
);
|
316
|
+
|
317
|
+
const COMPLETE_STATUS: MessagePartStatus = Object.freeze({
|
318
|
+
type: "complete",
|
319
|
+
});
|
320
|
+
|
321
|
+
const EmptyPartFallback: FC<{
|
322
|
+
status: MessagePartStatus;
|
323
|
+
component: TextMessagePartComponent;
|
324
|
+
}> = ({ status, component: Component }) => {
|
325
|
+
return (
|
326
|
+
<TextMessagePartProvider text="" isRunning={status.type === "running"}>
|
327
|
+
<Component type="text" text="" status={status} />
|
328
|
+
</TextMessagePartProvider>
|
329
|
+
);
|
330
|
+
};
|
331
|
+
|
332
|
+
const EmptyPartsImpl: FC<MessagePartComponentProps> = ({ components }) => {
|
333
|
+
const status =
|
334
|
+
useMessage((s) => s.status as MessagePartStatus) ?? COMPLETE_STATUS;
|
335
|
+
|
336
|
+
if (components?.Empty) return <components.Empty status={status} />;
|
337
|
+
|
338
|
+
return (
|
339
|
+
<EmptyPartFallback
|
340
|
+
status={status}
|
341
|
+
component={components?.Text ?? defaultComponents.Text}
|
342
|
+
/>
|
343
|
+
);
|
344
|
+
};
|
345
|
+
|
346
|
+
const EmptyParts = memo(
|
347
|
+
EmptyPartsImpl,
|
348
|
+
(prev, next) =>
|
349
|
+
prev.components?.Empty === next.components?.Empty &&
|
350
|
+
prev.components?.Text === next.components?.Text,
|
351
|
+
);
|
352
|
+
|
353
|
+
/**
|
354
|
+
* Renders the parts of a message grouped by their parent ID.
|
355
|
+
*
|
356
|
+
* This component automatically groups message parts that share the same parent ID,
|
357
|
+
* allowing you to create hierarchical or related content presentations. Parts without
|
358
|
+
* a parent ID appear after grouped parts and remain ungrouped.
|
359
|
+
*
|
360
|
+
* @example
|
361
|
+
* ```tsx
|
362
|
+
* <MessagePrimitive.Unstable_PartsGroupedByParentId
|
363
|
+
* components={{
|
364
|
+
* Text: ({ text }) => <p className="message-text">{text}</p>,
|
365
|
+
* Image: ({ image }) => <img src={image} alt="Message image" />,
|
366
|
+
* Group: ({ parentId, indices, children }) => {
|
367
|
+
* if (!parentId) return <>{children}</>;
|
368
|
+
* return (
|
369
|
+
* <div className="parent-group border rounded p-4">
|
370
|
+
* <h4>Related Content</h4>
|
371
|
+
* {children}
|
372
|
+
* </div>
|
373
|
+
* );
|
374
|
+
* }
|
375
|
+
* }}
|
376
|
+
* />
|
377
|
+
* ```
|
378
|
+
*/
|
379
|
+
export const MessagePrimitiveUnstable_PartsGroupedByParentId: FC<
|
380
|
+
MessagePrimitiveUnstable_PartsGroupedByParentId.Props
|
381
|
+
> = ({ components }) => {
|
382
|
+
const contentLength = useMessage((s) => s.content.length);
|
383
|
+
const messageGroups = useMessagePartsGroupedByParentId();
|
384
|
+
|
385
|
+
const partsElements = useMemo(() => {
|
386
|
+
if (contentLength === 0) {
|
387
|
+
return <EmptyParts components={components} />;
|
388
|
+
}
|
389
|
+
|
390
|
+
return messageGroups.map((group, groupIndex) => {
|
391
|
+
const GroupComponent = components?.Group ?? defaultComponents.Group;
|
392
|
+
|
393
|
+
return (
|
394
|
+
<GroupComponent
|
395
|
+
key={`group-${groupIndex}-${group.parentId ?? "ungrouped"}`}
|
396
|
+
parentId={group.parentId}
|
397
|
+
indices={group.indices}
|
398
|
+
>
|
399
|
+
{group.indices.map((partIndex) => (
|
400
|
+
<MessagePart
|
401
|
+
key={partIndex}
|
402
|
+
partIndex={partIndex}
|
403
|
+
components={components}
|
404
|
+
/>
|
405
|
+
))}
|
406
|
+
</GroupComponent>
|
407
|
+
);
|
408
|
+
});
|
409
|
+
}, [messageGroups, components, contentLength]);
|
410
|
+
|
411
|
+
return <>{partsElements}</>;
|
412
|
+
};
|
413
|
+
|
414
|
+
MessagePrimitiveUnstable_PartsGroupedByParentId.displayName =
|
415
|
+
"MessagePrimitive.Unstable_PartsGroupedByParentId";
|
@@ -4,3 +4,4 @@ export { MessagePrimitiveParts as Content } from "./MessageParts";
|
|
4
4
|
export { MessagePrimitiveIf as If } from "./MessageIf";
|
5
5
|
export { MessagePrimitiveAttachments as Attachments } from "./MessageAttachments";
|
6
6
|
export { MessagePrimitiveError as Error } from "./MessageError";
|
7
|
+
export { MessagePrimitiveUnstable_PartsGroupedByParentId as Unstable_PartsGroupedByParentId } from "./MessagePartsGroupedByParentId";
|
@@ -252,14 +252,6 @@ export class ExternalStoreThreadRuntimeCore
|
|
252
252
|
public addToolResult(options: AddToolResultOptions) {
|
253
253
|
if (!this._store.onAddToolResult && !this._store.onAddToolResult)
|
254
254
|
throw new Error("Runtime does not support tool results.");
|
255
|
-
this._store.onAddToolResult?.({
|
256
|
-
messageId: options.messageId,
|
257
|
-
toolName: options.toolName,
|
258
|
-
toolCallId: options.toolCallId,
|
259
|
-
result: options.result,
|
260
|
-
isError: options.isError,
|
261
|
-
artifact: options.artifact,
|
262
|
-
});
|
263
255
|
this._store.onAddToolResult?.(options);
|
264
256
|
}
|
265
257
|
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import { parsePartialJsonObject } from "assistant-stream/utils";
|
2
|
-
import { generateId } from "../../
|
2
|
+
import { generateId } from "../../utils/idUtils";
|
3
3
|
import {
|
4
4
|
MessageStatus,
|
5
5
|
TextMessagePart,
|
@@ -41,6 +41,7 @@ export type ThreadMessageLike = {
|
|
41
41
|
readonly artifact?: any;
|
42
42
|
readonly result?: any | undefined;
|
43
43
|
readonly isError?: boolean | undefined;
|
44
|
+
readonly parentId?: string | undefined;
|
44
45
|
}
|
45
46
|
)[];
|
46
47
|
readonly id?: string | undefined;
|
@@ -104,17 +105,22 @@ export const fromThreadMessageLike = (
|
|
104
105
|
return part;
|
105
106
|
|
106
107
|
case "tool-call": {
|
108
|
+
const { parentId, ...basePart } = part;
|
109
|
+
const commonProps = {
|
110
|
+
...basePart,
|
111
|
+
toolCallId: part.toolCallId ?? "tool-" + generateId(),
|
112
|
+
...(parentId !== undefined && { parentId }),
|
113
|
+
};
|
114
|
+
|
107
115
|
if (part.args) {
|
108
116
|
return {
|
109
|
-
...
|
110
|
-
toolCallId: part.toolCallId ?? "tool-" + generateId(),
|
117
|
+
...commonProps,
|
111
118
|
args: part.args,
|
112
119
|
argsText: JSON.stringify(part.args),
|
113
120
|
};
|
114
121
|
}
|
115
122
|
return {
|
116
|
-
...
|
117
|
-
toolCallId: part.toolCallId ?? "tool-" + generateId(),
|
123
|
+
...commonProps,
|
118
124
|
args:
|
119
125
|
part.args ??
|
120
126
|
parsePartialJsonObject(part.argsText ?? "") ??
|
@@ -6,11 +6,13 @@ export type MessageRole = ThreadMessage["role"];
|
|
6
6
|
export type TextMessagePart = {
|
7
7
|
readonly type: "text";
|
8
8
|
readonly text: string;
|
9
|
+
readonly parentId?: string;
|
9
10
|
};
|
10
11
|
|
11
12
|
export type ReasoningMessagePart = {
|
12
13
|
readonly type: "reasoning";
|
13
14
|
readonly text: string;
|
15
|
+
readonly parentId?: string;
|
14
16
|
};
|
15
17
|
|
16
18
|
export type SourceMessagePart = {
|
@@ -19,6 +21,7 @@ export type SourceMessagePart = {
|
|
19
21
|
readonly id: string;
|
20
22
|
readonly url: string;
|
21
23
|
readonly title?: string;
|
24
|
+
readonly parentId?: string;
|
22
25
|
};
|
23
26
|
|
24
27
|
export type ImageMessagePart = {
|
@@ -52,6 +55,7 @@ export type ToolCallMessagePart<
|
|
52
55
|
readonly isError?: boolean | undefined;
|
53
56
|
readonly argsText: string;
|
54
57
|
readonly artifact?: unknown;
|
58
|
+
readonly parentId?: string;
|
55
59
|
};
|
56
60
|
|
57
61
|
export type ThreadUserMessagePart =
|