basalt-ui 1.10.0 → 1.11.0
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/AGENTS.md +2 -2
- package/CHANGELOG.md +10 -0
- package/dist/agent/ai-sdk-transport.d.ts +3 -52
- package/dist/agent/ai-sdk-transport.d.ts.map +1 -1
- package/dist/agent/ai-sdk-transport.js +108 -24
- package/dist/agent/coalesce.d.ts +26 -0
- package/dist/agent/coalesce.d.ts.map +1 -0
- package/dist/agent/coalesce.js +69 -0
- package/dist/agent/foreign.d.ts +97 -0
- package/dist/agent/foreign.d.ts.map +1 -0
- package/dist/agent/foreign.js +18 -0
- package/dist/agent/history.d.ts +2 -0
- package/dist/agent/history.d.ts.map +1 -1
- package/dist/agent/id.d.ts +35 -0
- package/dist/agent/id.d.ts.map +1 -0
- package/dist/agent/id.js +14 -0
- package/dist/agent/index.d.ts +9 -4
- package/dist/agent/index.d.ts.map +1 -1
- package/dist/agent/index.js +15 -3
- package/dist/agent/merge.d.ts +8 -0
- package/dist/agent/merge.d.ts.map +1 -0
- package/dist/agent/merge.js +23 -0
- package/dist/agent/part-list.d.ts.map +1 -1
- package/dist/agent/part-list.js +16 -6
- package/dist/agent/parts.d.ts +100 -21
- package/dist/agent/parts.d.ts.map +1 -1
- package/dist/agent/parts.js +128 -11
- package/dist/agent/transport.d.ts +39 -3
- package/dist/agent/transport.d.ts.map +1 -1
- package/dist/agent/transport.js +20 -17
- package/dist/agent/use-agent-stream.d.ts +2 -1
- package/dist/agent/use-agent-stream.d.ts.map +1 -1
- package/dist/agent/use-agent-stream.js +5 -2
- package/dist/agent/use-agent-thread-runs.d.ts +9 -3
- package/dist/agent/use-agent-thread-runs.d.ts.map +1 -1
- package/dist/agent/use-agent-thread-runs.js +75 -23
- package/dist/agent-chat/index.d.ts +2 -0
- package/dist/agent-chat/index.d.ts.map +1 -1
- package/dist/agent-chat/index.js +2 -0
- package/dist/agent-chat/thread-message.d.ts +24 -7
- package/dist/agent-chat/thread-message.d.ts.map +1 -1
- package/dist/agent-chat/thread-message.js +102 -43
- package/dist/agent-chat/tool-chip.d.ts +21 -0
- package/dist/agent-chat/tool-chip.d.ts.map +1 -0
- package/dist/agent-chat/tool-chip.js +120 -0
- package/dist/guard/index.d.ts.map +1 -1
- package/dist/guard/index.js +1 -3
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/surfaces.d.ts +2 -2
- package/dist/surfaces.js +2 -2
- package/llms.txt +4 -4
- package/package.json +1 -1
- package/src/agent/ai-sdk-transport.test.ts +338 -40
- package/src/agent/ai-sdk-transport.ts +206 -53
- package/src/agent/coalesce.test.ts +194 -0
- package/src/agent/coalesce.ts +118 -0
- package/src/agent/foreign.test.ts +47 -0
- package/src/agent/foreign.ts +140 -0
- package/src/agent/history.ts +2 -0
- package/src/agent/id.test.ts +71 -0
- package/src/agent/id.ts +43 -0
- package/src/agent/index.ts +26 -3
- package/src/agent/merge.test.ts +119 -0
- package/src/agent/merge.ts +67 -0
- package/src/agent/part-list.test.tsx +82 -0
- package/src/agent/part-list.tsx +31 -6
- package/src/agent/parts.test.ts +401 -59
- package/src/agent/parts.ts +262 -32
- package/src/agent/transport.test.ts +70 -0
- package/src/agent/transport.ts +72 -20
- package/src/agent/use-agent-stream.test.tsx +47 -17
- package/src/agent/use-agent-stream.ts +13 -3
- package/src/agent/use-agent-thread-runs.foreign.test.tsx +133 -0
- package/src/agent/use-agent-thread-runs.resume.test.tsx +34 -6
- package/src/agent/use-agent-thread-runs.test.tsx +397 -14
- package/src/agent/use-agent-thread-runs.ts +170 -26
- package/src/agent/use-agent-thread-runs.wedge.test.tsx +4 -2
- package/src/agent-chat/index.ts +4 -0
- package/src/agent-chat/thread-message.test.tsx +211 -0
- package/src/agent-chat/thread-message.tsx +235 -62
- package/src/agent-chat/tool-chip.test.tsx +139 -0
- package/src/agent-chat/tool-chip.tsx +219 -0
- package/src/guard/check-source.test.ts +8 -4
- package/src/guard/index.ts +1 -3
- package/src/index.ts +2 -0
- package/src/surfaces.ts +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-agent-stream.d.ts","sourceRoot":"","sources":["../../src/agent/use-agent-stream.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"use-agent-stream.d.ts","sourceRoot":"","sources":["../../src/agent/use-agent-stream.ts"],"names":[],"mappings":"AAgCA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AACvC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AACxC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAIjD,iDAAiD;AACjD,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,WAAW,GAAG,MAAM,GAAG,OAAO,CAAA;AAIlE,MAAM,MAAM,oBAAoB,CAAC,KAAK,EAAE,MAAM,IAAI;IAChD,qEAAqE;IACrE,QAAQ,CAAC,KAAK,EAAE,KAAK,EAAE,CAAA;IACvB,gCAAgC;IAChC,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAA;IAC7B,oEAAoE;IACpE,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;IACvB;;;OAGG;IACH,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAC/C,4DAA4D;IAC5D,QAAQ,CAAC,IAAI,EAAE,MAAM,IAAI,CAAA;IACzB,kEAAkE;IAClE,QAAQ,CAAC,UAAU,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CACzC,CAAA;AAID;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,KAAK,SAAS,QAAQ,GAAG,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,EAClF,SAAS,GACV,EAAE;IACD,SAAS,EAAE,cAAc,CAAC,KAAK,EAAE,MAAM,CAAC,CAAA;CACzC,GAAG,oBAAoB,CAAC,KAAK,EAAE,MAAM,CAAC,CA0EtC"}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { useCallback, useEffect, useRef, useState } from "react";
|
|
2
|
+
import { withPartIds } from "./id.js";
|
|
2
3
|
import { isStartPart } from "./parts.js";
|
|
4
|
+
import { mergePart } from "./merge.js";
|
|
3
5
|
function useAgentStream({
|
|
4
6
|
transport
|
|
5
7
|
}) {
|
|
@@ -23,12 +25,13 @@ function useAgentStream({
|
|
|
23
25
|
setParts([]);
|
|
24
26
|
setError(void 0);
|
|
25
27
|
setStatus("streaming");
|
|
28
|
+
const runId = crypto.randomUUID();
|
|
26
29
|
try {
|
|
27
|
-
for await (const part of transport.stream(input, controller.signal)) {
|
|
30
|
+
for await (const part of withPartIds(runId, transport.stream(input, controller.signal))) {
|
|
28
31
|
if (controllerRef.current !== controller) return;
|
|
29
32
|
if (controller.signal.aborted) break;
|
|
30
33
|
if (isStartPart(part)) continue;
|
|
31
|
-
setParts((prev) =>
|
|
34
|
+
setParts((prev) => mergePart(prev, part));
|
|
32
35
|
}
|
|
33
36
|
if (controllerRef.current === controller && !controller.signal.aborted) setStatus("done");
|
|
34
37
|
} catch (err) {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { PartLike } from './merge.js';
|
|
1
2
|
import type { OutcomeResolver } from './outcome.js';
|
|
2
3
|
import type { AgentPart } from './parts.js';
|
|
3
4
|
import type { ThreadsStore } from './thread.js';
|
|
@@ -52,9 +53,14 @@ export type UseAgentThreadRunsReturn<TPart = AgentPart> = {
|
|
|
52
53
|
* `threadId` has never had a turn started, or already has one in flight.
|
|
53
54
|
*/
|
|
54
55
|
readonly retry: (threadId: string) => void;
|
|
55
|
-
/**
|
|
56
|
+
/**
|
|
57
|
+
* Abort the in-flight stream for `threadId` (no-op if idle). Preserves whatever content had
|
|
58
|
+
* already arrived: if the run had accumulated any parts, they're persisted as an assistant
|
|
59
|
+
* ChatMessage with `finish: 'stopped'` (unless that message already landed — see finalizeStop),
|
|
60
|
+
* then distilled into an outcome and the thread is settled to 'done'.
|
|
61
|
+
*/
|
|
56
62
|
readonly stop: (threadId: string) => void;
|
|
57
|
-
/** Abort every in-flight stream across all threads. */
|
|
63
|
+
/** Abort every in-flight stream across all threads, settling each the same way stop() would. */
|
|
58
64
|
readonly stopAll: () => void;
|
|
59
65
|
};
|
|
60
66
|
/**
|
|
@@ -68,5 +74,5 @@ export type UseAgentThreadRunsReturn<TPart = AgentPart> = {
|
|
|
68
74
|
* start(threadB, 'What changed in the last release?')
|
|
69
75
|
* // both stream concurrently; runs.get(threadA) / runs.get(threadB) update independently
|
|
70
76
|
*/
|
|
71
|
-
export declare function useAgentThreadRuns<TPart = AgentPart>({ transport, store, resolveOutcome, toUserParts, }: UseAgentThreadRunsArgs<TPart>): UseAgentThreadRunsReturn<TPart>;
|
|
77
|
+
export declare function useAgentThreadRuns<TPart extends PartLike = AgentPart>({ transport, store, resolveOutcome, toUserParts, }: UseAgentThreadRunsArgs<TPart>): UseAgentThreadRunsReturn<TPart>;
|
|
72
78
|
//# sourceMappingURL=use-agent-thread-runs.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-agent-thread-runs.d.ts","sourceRoot":"","sources":["../../src/agent/use-agent-thread-runs.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"use-agent-thread-runs.d.ts","sourceRoot":"","sources":["../../src/agent/use-agent-thread-runs.ts"],"names":[],"mappings":"AA4CA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AACvC,OAAO,KAAK,EAAgB,eAAe,EAAE,MAAM,WAAW,CAAA;AAE9D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AACxC,OAAO,KAAK,EAA6B,YAAY,EAAE,MAAM,UAAU,CAAA;AAEvE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAIjD;;;;;;;;;;GAUG;AACH,MAAM,MAAM,cAAc,CAAC,KAAK,GAAG,SAAS,IAAI;IAC9C,yFAAyF;IACzF,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAA;IAC5B,iEAAiE;IACjE,QAAQ,CAAC,KAAK,EAAE,KAAK,EAAE,CAAA;CACxB,CAAA;AAID,MAAM,MAAM,sBAAsB,CAAC,KAAK,GAAG,SAAS,IAAI;IACtD;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,SAAS,EACd,cAAc,CAAC,KAAK,EAAE,MAAM,CAAC,GAC7B,CAAC,CAAC,QAAQ,EAAE,MAAM,KAAK,cAAc,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAA;IACzD,8EAA8E;IAC9E,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAC,KAAK,CAAC,CAAA;IACnC,uFAAuF;IACvF,QAAQ,CAAC,cAAc,EAAE,eAAe,CAAC,KAAK,CAAC,CAAA;IAC/C;;;OAGG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,KAAK,EAAE,CAAA;CAClD,CAAA;AAID,MAAM,MAAM,wBAAwB,CAAC,KAAK,GAAG,SAAS,IAAI;IACxD,6FAA6F;IAC7F,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC,MAAM,EAAE,cAAc,CAAC,KAAK,CAAC,CAAC,CAAA;IACzD,2FAA2F;IAC3F,QAAQ,CAAC,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IACzD;;;OAGG;IACH,QAAQ,CAAC,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAA;IAC1C;;;;;OAKG;IACH,QAAQ,CAAC,IAAI,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAA;IACzC,gGAAgG;IAChG,QAAQ,CAAC,OAAO,EAAE,MAAM,IAAI,CAAA;CAC7B,CAAA;AAkND;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,SAAS,QAAQ,GAAG,SAAS,EAAE,EACrE,SAAS,EACT,KAAK,EACL,cAAc,EACd,WAAW,GACZ,EAAE,sBAAsB,CAAC,KAAK,CAAC,GAAG,wBAAwB,CAAC,KAAK,CAAC,CAkPjE"}
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { useCallback, useEffect, useRef, useState } from "react";
|
|
2
|
+
import { withPartIds } from "./id.js";
|
|
3
|
+
import { mergePart } from "./merge.js";
|
|
2
4
|
import { isStartPart } from "./parts.js";
|
|
5
|
+
import { isResumable } from "./transport.js";
|
|
3
6
|
function defaultToUserParts(input) {
|
|
4
|
-
return [{ type: "text", text: input }];
|
|
7
|
+
return [{ id: crypto.randomUUID(), type: "text", text: input }];
|
|
5
8
|
}
|
|
6
9
|
function buildDoneSnapshot(priorThread, threadId, userMessage, assistantMessage) {
|
|
7
10
|
const updatedAt = Date.now();
|
|
@@ -30,12 +33,13 @@ async function consumeAndFinalize(args) {
|
|
|
30
33
|
generator,
|
|
31
34
|
userMessage,
|
|
32
35
|
controllersRef,
|
|
36
|
+
appendedRef,
|
|
33
37
|
storeRef,
|
|
34
38
|
resolveOutcome,
|
|
35
39
|
setRuns,
|
|
36
40
|
onFailureStatus
|
|
37
41
|
} = args;
|
|
38
|
-
|
|
42
|
+
let parts = [];
|
|
39
43
|
try {
|
|
40
44
|
for await (const part of generator) {
|
|
41
45
|
if (controllersRef.current.get(threadId) !== controller) return;
|
|
@@ -44,10 +48,10 @@ async function consumeAndFinalize(args) {
|
|
|
44
48
|
storeRef.current.setResumeToken(threadId, part.resumeToken);
|
|
45
49
|
continue;
|
|
46
50
|
}
|
|
47
|
-
parts
|
|
51
|
+
parts = mergePart(parts, part);
|
|
48
52
|
setRuns((prev) => {
|
|
49
53
|
const next = new Map(prev);
|
|
50
|
-
next.set(threadId, { status: "streaming", parts
|
|
54
|
+
next.set(threadId, { status: "streaming", parts });
|
|
51
55
|
return next;
|
|
52
56
|
});
|
|
53
57
|
}
|
|
@@ -58,16 +62,22 @@ async function consumeAndFinalize(args) {
|
|
|
58
62
|
id: crypto.randomUUID(),
|
|
59
63
|
role: "assistant",
|
|
60
64
|
parts,
|
|
61
|
-
createdAt: Date.now()
|
|
65
|
+
createdAt: Date.now(),
|
|
66
|
+
finish: "complete"
|
|
62
67
|
};
|
|
63
68
|
storeRef.current.appendMessage(threadId, assistantMessage);
|
|
69
|
+
appendedRef.current.set(threadId, controller);
|
|
64
70
|
const priorThread = storeRef.current.threads.find((thread) => thread.id === threadId);
|
|
65
71
|
const snapshot = buildDoneSnapshot(priorThread, threadId, userMessage, assistantMessage);
|
|
66
72
|
const outcome = await resolveOutcome(snapshot);
|
|
73
|
+
if (controllersRef.current.get(threadId) !== controller || controller.signal.aborted) {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
67
76
|
storeRef.current.setOutcome(threadId, outcome);
|
|
68
77
|
storeRef.current.setStatus(threadId, outcome.status);
|
|
69
78
|
storeRef.current.setResumeToken(threadId, void 0);
|
|
70
79
|
controllersRef.current.delete(threadId);
|
|
80
|
+
appendedRef.current.delete(threadId);
|
|
71
81
|
setRuns((prev) => {
|
|
72
82
|
if (!prev.has(threadId)) return prev;
|
|
73
83
|
const next = new Map(prev);
|
|
@@ -80,6 +90,7 @@ async function consumeAndFinalize(args) {
|
|
|
80
90
|
if (controller.signal.aborted) return;
|
|
81
91
|
storeRef.current.setStatus(threadId, onFailureStatus);
|
|
82
92
|
controllersRef.current.delete(threadId);
|
|
93
|
+
appendedRef.current.delete(threadId);
|
|
83
94
|
setRuns((prev) => {
|
|
84
95
|
if (!prev.has(threadId)) return prev;
|
|
85
96
|
const next = new Map(prev);
|
|
@@ -88,6 +99,31 @@ async function consumeAndFinalize(args) {
|
|
|
88
99
|
});
|
|
89
100
|
}
|
|
90
101
|
}
|
|
102
|
+
async function finalizeStop(args) {
|
|
103
|
+
const { threadId, parts, alreadyAppended, storeRef, resolveOutcome, setRuns } = args;
|
|
104
|
+
if (!alreadyAppended && parts.length > 0) {
|
|
105
|
+
const stoppedMessage = {
|
|
106
|
+
id: crypto.randomUUID(),
|
|
107
|
+
role: "assistant",
|
|
108
|
+
parts,
|
|
109
|
+
createdAt: Date.now(),
|
|
110
|
+
finish: "stopped"
|
|
111
|
+
};
|
|
112
|
+
storeRef.current.appendMessage(threadId, stoppedMessage);
|
|
113
|
+
}
|
|
114
|
+
storeRef.current.setStatus(threadId, "done");
|
|
115
|
+
storeRef.current.setResumeToken(threadId, void 0);
|
|
116
|
+
setRuns((prev) => {
|
|
117
|
+
if (!prev.has(threadId)) return prev;
|
|
118
|
+
const next = new Map(prev);
|
|
119
|
+
next.delete(threadId);
|
|
120
|
+
return next;
|
|
121
|
+
});
|
|
122
|
+
const snapshot = storeRef.current.threads.find((thread) => thread.id === threadId);
|
|
123
|
+
if (snapshot === void 0) return;
|
|
124
|
+
const outcome = await resolveOutcome(snapshot);
|
|
125
|
+
storeRef.current.setOutcome(threadId, outcome);
|
|
126
|
+
}
|
|
91
127
|
function useAgentThreadRuns({
|
|
92
128
|
transport,
|
|
93
129
|
store,
|
|
@@ -95,7 +131,10 @@ function useAgentThreadRuns({
|
|
|
95
131
|
toUserParts
|
|
96
132
|
}) {
|
|
97
133
|
const [runs, setRuns] = useState(/* @__PURE__ */ new Map());
|
|
134
|
+
const runsRef = useRef(runs);
|
|
135
|
+
runsRef.current = runs;
|
|
98
136
|
const controllersRef = useRef(/* @__PURE__ */ new Map());
|
|
137
|
+
const appendedRef = useRef(/* @__PURE__ */ new Map());
|
|
99
138
|
const lastInputRef = useRef(/* @__PURE__ */ new Map());
|
|
100
139
|
const storeRef = useRef(store);
|
|
101
140
|
storeRef.current = store;
|
|
@@ -118,6 +157,7 @@ function useAgentThreadRuns({
|
|
|
118
157
|
() => () => {
|
|
119
158
|
controllersRef.current.forEach((controller) => controller.abort());
|
|
120
159
|
controllersRef.current.clear();
|
|
160
|
+
appendedRef.current.clear();
|
|
121
161
|
},
|
|
122
162
|
[]
|
|
123
163
|
);
|
|
@@ -128,7 +168,7 @@ function useAgentThreadRuns({
|
|
|
128
168
|
const resumeToken = thread.resumeToken;
|
|
129
169
|
const lastUserMessage = thread.messages.filter((message) => message.role === "user").at(-1);
|
|
130
170
|
const resolvedTransport = resolveTransport(thread.id);
|
|
131
|
-
if (resolvedTransport
|
|
171
|
+
if (!isResumable(resolvedTransport) || resumeToken === void 0 || lastUserMessage === void 0) {
|
|
132
172
|
storeRef.current.setStatus(thread.id, "interrupted");
|
|
133
173
|
continue;
|
|
134
174
|
}
|
|
@@ -143,9 +183,17 @@ function useAgentThreadRuns({
|
|
|
143
183
|
void consumeAndFinalize({
|
|
144
184
|
threadId: thread.id,
|
|
145
185
|
controller,
|
|
146
|
-
|
|
186
|
+
// Namespaced by thread.id (stable across a thread's whole lifetime, including this
|
|
187
|
+
// resume) rather than per-call — see withPartIds' own doc for why this is NOT a replay-
|
|
188
|
+
// convergence guarantee on its own: it only protects against two id-less drafts within
|
|
189
|
+
// ONE generator colliding (the F1 bug). A transport whose resume() needs genuine replay
|
|
190
|
+
// safety must assert `idempotentReplay: true` AND mint its own content-stable ids (as
|
|
191
|
+
// aiSdkTransport does) — withPartIds is then a no-op passthrough for it, not the mechanism
|
|
192
|
+
// providing that safety.
|
|
193
|
+
generator: withPartIds(thread.id, resume(resumeToken, controller.signal)),
|
|
147
194
|
userMessage: lastUserMessage,
|
|
148
195
|
controllersRef,
|
|
196
|
+
appendedRef,
|
|
149
197
|
storeRef,
|
|
150
198
|
resolveOutcome,
|
|
151
199
|
setRuns,
|
|
@@ -176,9 +224,11 @@ function useAgentThreadRuns({
|
|
|
176
224
|
void consumeAndFinalize({
|
|
177
225
|
threadId,
|
|
178
226
|
controller,
|
|
179
|
-
|
|
227
|
+
// Namespaced by threadId — same choice, same caveat, as the mount-time resume call above.
|
|
228
|
+
generator: withPartIds(threadId, resolvedTransport.stream(input, controller.signal)),
|
|
180
229
|
userMessage,
|
|
181
230
|
controllersRef,
|
|
231
|
+
appendedRef,
|
|
182
232
|
storeRef,
|
|
183
233
|
resolveOutcome,
|
|
184
234
|
setRuns,
|
|
@@ -195,22 +245,24 @@ function useAgentThreadRuns({
|
|
|
195
245
|
},
|
|
196
246
|
[start]
|
|
197
247
|
);
|
|
198
|
-
const stop = useCallback(
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
248
|
+
const stop = useCallback(
|
|
249
|
+
(threadId) => {
|
|
250
|
+
const controller = controllersRef.current.get(threadId);
|
|
251
|
+
if (controller === void 0) return;
|
|
252
|
+
controllersRef.current.delete(threadId);
|
|
253
|
+
const parts = runsRef.current.get(threadId)?.parts ?? [];
|
|
254
|
+
controller.abort();
|
|
255
|
+
const alreadyAppended = appendedRef.current.get(threadId) === controller;
|
|
256
|
+
appendedRef.current.delete(threadId);
|
|
257
|
+
void finalizeStop({ threadId, parts, alreadyAppended, storeRef, resolveOutcome, setRuns });
|
|
258
|
+
},
|
|
259
|
+
[resolveOutcome]
|
|
260
|
+
);
|
|
209
261
|
const stopAll = useCallback(() => {
|
|
210
|
-
controllersRef.current.
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
}, []);
|
|
262
|
+
for (const threadId of Array.from(controllersRef.current.keys())) {
|
|
263
|
+
stop(threadId);
|
|
264
|
+
}
|
|
265
|
+
}, [stop]);
|
|
214
266
|
return { runs, start, retry, stop, stopAll };
|
|
215
267
|
}
|
|
216
268
|
export {
|
|
@@ -22,4 +22,6 @@ export { Composer } from './composer.js';
|
|
|
22
22
|
export type { ComposerProps } from './composer.js';
|
|
23
23
|
export { threadPartRenderers, ThreadTranscript } from './thread-message.js';
|
|
24
24
|
export type { ThreadTranscriptProps } from './thread-message.js';
|
|
25
|
+
export { ToolChip } from './tool-chip.js';
|
|
26
|
+
export type { ToolChipProps } from './tool-chip.js';
|
|
25
27
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/agent-chat/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AACpD,YAAY,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAA;AAG9D,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAC1C,YAAY,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAGpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAA;AACzD,YAAY,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAA;AAGnE,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAA;AACzD,YAAY,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAA;AAGnE,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AACrC,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAG/C,OAAO,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AACxE,YAAY,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/agent-chat/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AACpD,YAAY,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAA;AAG9D,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAC1C,YAAY,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAGpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAA;AACzD,YAAY,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAA;AAGnE,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAA;AACzD,YAAY,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAA;AAGnE,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AACrC,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAG/C,OAAO,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AACxE,YAAY,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAA;AAG7D,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AACtC,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA"}
|
package/dist/agent-chat/index.js
CHANGED
|
@@ -4,6 +4,7 @@ import { ThreadOutcomeCard } from "./thread-outcome-card.js";
|
|
|
4
4
|
import { ThreadDetailPanel } from "./thread-detail-panel.js";
|
|
5
5
|
import { Composer } from "./composer.js";
|
|
6
6
|
import { threadPartRenderers, ThreadTranscript } from "./thread-message.js";
|
|
7
|
+
import { ToolChip } from "./tool-chip.js";
|
|
7
8
|
export {
|
|
8
9
|
Composer,
|
|
9
10
|
ThreadDetailPanel,
|
|
@@ -11,5 +12,6 @@ export {
|
|
|
11
12
|
ThreadOutcomeCard,
|
|
12
13
|
ThreadTranscript,
|
|
13
14
|
ThreadWorkspace,
|
|
15
|
+
ToolChip,
|
|
14
16
|
threadPartRenderers
|
|
15
17
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { JSX } from 'react';
|
|
2
|
-
import type {
|
|
2
|
+
import type { AgentPartRenderers, ChatMessage, ForeignPart, PartRenderer, PartRenderers, StreamStatus, TranscriptPart } from '../agent/index.js';
|
|
3
3
|
/**
|
|
4
4
|
* Mantine overrides for `PartList`'s default headless renderers — the house style for rendering
|
|
5
5
|
* an `AgentPart` inside a chat surface.
|
|
@@ -10,22 +10,39 @@ import type { AgentPart, AgentPartRenderers, ChatMessage, StreamStatus } from '.
|
|
|
10
10
|
* <PartList parts={parts} components={threadPartRenderers} />
|
|
11
11
|
*/
|
|
12
12
|
export declare const threadPartRenderers: Partial<AgentPartRenderers>;
|
|
13
|
-
|
|
13
|
+
/**
|
|
14
|
+
* Render-execution counter for `MessageBlockImpl` — increments only when React actually calls the
|
|
15
|
+
* function body (a `memo` bail-out never reaches it). NOT part of the public surface —
|
|
16
|
+
* `agent-chat/index.ts` does not re-export it. The memoization test imports this module directly
|
|
17
|
+
* (bypassing the barrel) to prove the memo boundary in a controlled render-count harness.
|
|
18
|
+
*/
|
|
19
|
+
export declare const messageBlockRenderCounter: {
|
|
20
|
+
count: number;
|
|
21
|
+
};
|
|
22
|
+
type ThreadTranscriptBase = {
|
|
14
23
|
/** Settled messages for the thread, oldest first. */
|
|
15
|
-
readonly messages: ChatMessage[];
|
|
24
|
+
readonly messages: readonly ChatMessage<TranscriptPart>[];
|
|
16
25
|
/** The live (in-flight) assistant turn's parts, when a run is streaming for this thread. */
|
|
17
|
-
readonly liveParts?:
|
|
26
|
+
readonly liveParts?: readonly TranscriptPart[];
|
|
18
27
|
/** The live run's status — drives the in-progress indicator on the live block. */
|
|
19
28
|
readonly liveStatus?: StreamStatus;
|
|
29
|
+
/** Consumer renderers keyed by part.type. Consulted BEFORE the built-in union. */
|
|
30
|
+
readonly renderers?: PartRenderers;
|
|
31
|
+
/** Called for a part whose type is neither an AgentPart variant nor a registered key. Defaults
|
|
32
|
+
* to a visible `UnknownPartChip` outside production, `null` in production — never throws. */
|
|
33
|
+
readonly fallbackRenderer?: PartRenderer<ForeignPart>;
|
|
20
34
|
};
|
|
35
|
+
export type ThreadTranscriptProps = ThreadTranscriptBase;
|
|
21
36
|
/**
|
|
22
|
-
* Renders a thread's settled messages, each role-labelled ("You" / "Assistant")
|
|
23
|
-
*
|
|
37
|
+
* Renders a thread's settled messages, each role-labelled ("You" / "Assistant"). Each part
|
|
38
|
+
* resolves in order: a registered `renderers[part.type]` first, then basalt's own `PartList` for
|
|
39
|
+
* the built-in six, then `fallbackRenderer`. When `liveParts` is non-empty, an extra in-progress
|
|
24
40
|
* assistant block is appended at the tail.
|
|
25
41
|
*
|
|
26
42
|
* @example
|
|
27
43
|
* import { ThreadTranscript } from 'basalt-ui'
|
|
28
44
|
* <ThreadTranscript messages={thread.messages} liveParts={liveParts} liveStatus={runStatus} />
|
|
29
45
|
*/
|
|
30
|
-
export declare function ThreadTranscript({ messages, liveParts, liveStatus, }: ThreadTranscriptProps): JSX.Element;
|
|
46
|
+
export declare function ThreadTranscript({ messages, liveParts, liveStatus, renderers: renderersProp, fallbackRenderer, }: ThreadTranscriptProps): JSX.Element;
|
|
47
|
+
export {};
|
|
31
48
|
//# sourceMappingURL=thread-message.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"thread-message.d.ts","sourceRoot":"","sources":["../../src/agent-chat/thread-message.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"thread-message.d.ts","sourceRoot":"","sources":["../../src/agent-chat/thread-message.tsx"],"names":[],"mappings":"AAiCA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,OAAO,CAAA;AAChC,OAAO,KAAK,EAEV,kBAAkB,EAClB,WAAW,EAEX,WAAW,EACX,YAAY,EACZ,aAAa,EAGb,YAAY,EAGZ,cAAc,EACf,MAAM,UAAU,CAAA;AAkFjB;;;;;;;;GAQG;AACH,eAAO,MAAM,mBAAmB,EAAE,OAAO,CAAC,kBAAkB,CAM3D,CAAA;AAqID;;;;;GAKG;AACH,eAAO,MAAM,yBAAyB;;CAAe,CAAA;AA8ErD,KAAK,oBAAoB,GAAG;IAC1B,qDAAqD;IACrD,QAAQ,CAAC,QAAQ,EAAE,SAAS,WAAW,CAAC,cAAc,CAAC,EAAE,CAAA;IACzD,4FAA4F;IAC5F,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,cAAc,EAAE,CAAA;IAC9C,kFAAkF;IAClF,QAAQ,CAAC,UAAU,CAAC,EAAE,YAAY,CAAA;IAClC,kFAAkF;IAClF,QAAQ,CAAC,SAAS,CAAC,EAAE,aAAa,CAAA;IAClC;iGAC6F;IAC7F,QAAQ,CAAC,gBAAgB,CAAC,EAAE,YAAY,CAAC,WAAW,CAAC,CAAA;CACtD,CAAA;AAED,MAAM,MAAM,qBAAqB,GAAG,oBAAoB,CAAA;AAExD;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,EAC/B,QAAQ,EACR,SAAS,EACT,UAAU,EACV,SAAS,EAAE,aAAa,EACxB,gBAA4C,GAC7C,EAAE,qBAAqB,GAAG,GAAG,CAAC,OAAO,CAgCrC"}
|
|
@@ -11,9 +11,11 @@ import {
|
|
|
11
11
|
UnstyledButton
|
|
12
12
|
} from "@mantine/core";
|
|
13
13
|
import { useDisclosure } from "@mantine/hooks";
|
|
14
|
-
import {
|
|
14
|
+
import { Fragment, memo, useMemo } from "react";
|
|
15
|
+
import { coalesceParts, narrowAgentPart, PartList } from "../agent/index.js";
|
|
15
16
|
import { Markdown } from "../content/markdown.js";
|
|
16
|
-
import {
|
|
17
|
+
import { VX } from "../tokens/index.js";
|
|
18
|
+
import { ToolChip } from "./tool-chip.js";
|
|
17
19
|
const MICRO_LABEL_STYLE = {
|
|
18
20
|
fontFamily: "var(--basalt-font-mono)",
|
|
19
21
|
fontSize: VX.text.micro,
|
|
@@ -29,16 +31,6 @@ const RAIL_STYLE = {
|
|
|
29
31
|
borderLeft: `2px solid ${VX.divider}`,
|
|
30
32
|
paddingLeft: "var(--vx-space-agent-rail-inset-x)"
|
|
31
33
|
};
|
|
32
|
-
const CODE_BLOCK_STYLE = {
|
|
33
|
-
margin: 0,
|
|
34
|
-
marginTop: "var(--vx-space-agent-part-gap-top)",
|
|
35
|
-
fontFamily: "var(--basalt-font-mono)",
|
|
36
|
-
backgroundColor: alpha(VX.ink, 0.06),
|
|
37
|
-
borderRadius: "var(--vx-radius-card)",
|
|
38
|
-
padding: "var(--vx-space-agent-code-inset)",
|
|
39
|
-
whiteSpace: "pre-wrap",
|
|
40
|
-
overflowWrap: "anywhere"
|
|
41
|
-
};
|
|
42
34
|
function ReasoningRenderer({ part }) {
|
|
43
35
|
const [open, { toggle }] = useDisclosure(false);
|
|
44
36
|
return /* @__PURE__ */ jsx(Box, { style: RAIL_STYLE, children: /* @__PURE__ */ jsxs(Stack, { gap: 4, children: [
|
|
@@ -46,12 +38,8 @@ function ReasoningRenderer({ part }) {
|
|
|
46
38
|
/* @__PURE__ */ jsx(Collapse, { expanded: open, children: /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", style: { whiteSpace: "pre-wrap" }, children: part.text }) })
|
|
47
39
|
] }) });
|
|
48
40
|
}
|
|
49
|
-
function
|
|
50
|
-
return /* @__PURE__ */ jsx(
|
|
51
|
-
/* @__PURE__ */ jsx(Text, { style: MICRO_LABEL_STYLE, children: part.toolName }),
|
|
52
|
-
/* @__PURE__ */ jsx(Text, { component: "pre", size: "xs", style: CODE_BLOCK_STYLE, children: JSON.stringify(part.input, null, 2) }),
|
|
53
|
-
part.output !== void 0 && /* @__PURE__ */ jsx(Text, { component: "pre", size: "xs", style: CODE_BLOCK_STYLE, children: JSON.stringify(part.output, null, 2) })
|
|
54
|
-
] }) });
|
|
41
|
+
function ToolChipRenderer({ part }) {
|
|
42
|
+
return /* @__PURE__ */ jsx(ToolChip, { part });
|
|
55
43
|
}
|
|
56
44
|
function SourceRenderer({ part }) {
|
|
57
45
|
return /* @__PURE__ */ jsx(Anchor, { href: part.url, target: "_blank", rel: "noopener noreferrer", size: "sm", children: part.title ?? part.url });
|
|
@@ -62,70 +50,141 @@ function ErrorRenderer({ part }) {
|
|
|
62
50
|
const threadPartRenderers = {
|
|
63
51
|
text: TextRenderer,
|
|
64
52
|
reasoning: ReasoningRenderer,
|
|
65
|
-
tool:
|
|
53
|
+
tool: ToolChipRenderer,
|
|
66
54
|
source: SourceRenderer,
|
|
67
55
|
error: ErrorRenderer
|
|
68
56
|
};
|
|
69
|
-
function
|
|
70
|
-
|
|
57
|
+
function UnknownPartChip({ part }) {
|
|
58
|
+
return /* @__PURE__ */ jsx(Box, { style: RAIL_STYLE, children: /* @__PURE__ */ jsx(Text, { style: MICRO_LABEL_STYLE, children: `Unknown part: ${part.type}` }) });
|
|
59
|
+
}
|
|
60
|
+
const DEFAULT_FALLBACK_RENDERER = ({ part }) => process.env["NODE_ENV"] !== "production" ? /* @__PURE__ */ jsx(UnknownPartChip, { part }) : null;
|
|
61
|
+
function resolveSegments(parts, renderers, fallbackRenderer) {
|
|
62
|
+
const segments = [];
|
|
63
|
+
let buffer = [];
|
|
64
|
+
const flushBuffer = () => {
|
|
65
|
+
const first = buffer[0];
|
|
66
|
+
if (first === void 0) return;
|
|
67
|
+
segments.push({ kind: "agent", key: first.id, parts: coalesceParts(buffer) });
|
|
68
|
+
buffer = [];
|
|
69
|
+
};
|
|
71
70
|
for (const part of parts) {
|
|
72
|
-
const
|
|
73
|
-
if (
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
71
|
+
const consumerRenderer = renderers[part.type];
|
|
72
|
+
if (consumerRenderer !== void 0) {
|
|
73
|
+
flushBuffer();
|
|
74
|
+
segments.push({
|
|
75
|
+
kind: "foreign",
|
|
76
|
+
key: part.id,
|
|
77
|
+
part,
|
|
78
|
+
render: consumerRenderer
|
|
79
|
+
});
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
const agentPart = narrowAgentPart(part);
|
|
83
|
+
if (agentPart !== null) {
|
|
84
|
+
buffer.push(agentPart);
|
|
85
|
+
continue;
|
|
79
86
|
}
|
|
87
|
+
flushBuffer();
|
|
88
|
+
segments.push({
|
|
89
|
+
kind: "foreign",
|
|
90
|
+
key: part.id,
|
|
91
|
+
part,
|
|
92
|
+
render: fallbackRenderer
|
|
93
|
+
});
|
|
80
94
|
}
|
|
81
|
-
|
|
95
|
+
flushBuffer();
|
|
96
|
+
return segments;
|
|
82
97
|
}
|
|
83
98
|
const ROLE_LABEL = {
|
|
84
99
|
user: "You",
|
|
85
100
|
assistant: "Assistant"
|
|
86
101
|
};
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
102
|
+
const FINISH_INDICATOR = {
|
|
103
|
+
stopped: { label: "Stopped", statusToken: VX.status.warn },
|
|
104
|
+
error: { label: "Error", statusToken: VX.status.bad }
|
|
105
|
+
};
|
|
106
|
+
const messageBlockRenderCounter = { count: 0 };
|
|
107
|
+
function MessageBlockImpl({
|
|
108
|
+
message,
|
|
109
|
+
streaming = false,
|
|
110
|
+
renderers,
|
|
111
|
+
fallbackRenderer
|
|
91
112
|
}) {
|
|
113
|
+
messageBlockRenderCounter.count += 1;
|
|
114
|
+
const settled = !streaming;
|
|
115
|
+
const segments = useMemo(
|
|
116
|
+
() => resolveSegments(message.parts, renderers, fallbackRenderer),
|
|
117
|
+
[message.parts, renderers, fallbackRenderer]
|
|
118
|
+
);
|
|
119
|
+
const finishIndicator = message.finish === void 0 ? void 0 : FINISH_INDICATOR[message.finish];
|
|
92
120
|
return /* @__PURE__ */ jsx(
|
|
93
121
|
Box,
|
|
94
122
|
{
|
|
95
123
|
style: {
|
|
96
124
|
padding: "var(--vx-space-agent-message-inset-y) var(--vx-space-agent-message-inset-x)",
|
|
97
|
-
backgroundColor:
|
|
125
|
+
backgroundColor: message.role === "user" ? VX.surface.subtle : VX.surface.panel,
|
|
98
126
|
borderRadius: VX.radiusCard,
|
|
99
127
|
boxShadow: VX.shadowCard
|
|
100
128
|
},
|
|
101
129
|
children: /* @__PURE__ */ jsxs(Stack, { gap: 6, children: [
|
|
102
130
|
/* @__PURE__ */ jsxs(Group, { gap: 6, align: "center", children: [
|
|
103
|
-
/* @__PURE__ */ jsx(Text, { style: MICRO_LABEL_STYLE, children: ROLE_LABEL[
|
|
104
|
-
streaming && /* @__PURE__ */ jsx(Loader, { size: "xs" })
|
|
131
|
+
/* @__PURE__ */ jsx(Text, { style: MICRO_LABEL_STYLE, children: ROLE_LABEL[message.role] }),
|
|
132
|
+
streaming && /* @__PURE__ */ jsx(Loader, { size: "xs" }),
|
|
133
|
+
finishIndicator !== void 0 && /* @__PURE__ */ jsx(Text, { style: { ...MICRO_LABEL_STYLE, color: finishIndicator.statusToken }, children: finishIndicator.label })
|
|
105
134
|
] }),
|
|
106
|
-
|
|
135
|
+
segments.map(
|
|
136
|
+
(segment) => segment.kind === "agent" ? /* @__PURE__ */ jsx(PartList, { parts: segment.parts, components: threadPartRenderers }, segment.key) : /* @__PURE__ */ jsx(Fragment, { children: segment.render({
|
|
137
|
+
part: segment.part,
|
|
138
|
+
messageId: message.id,
|
|
139
|
+
partId: segment.part.id,
|
|
140
|
+
settled,
|
|
141
|
+
role: message.role
|
|
142
|
+
}) }, segment.key)
|
|
143
|
+
)
|
|
107
144
|
] })
|
|
108
145
|
}
|
|
109
146
|
);
|
|
110
147
|
}
|
|
148
|
+
function areMessageBlockPropsEqual(prev, next) {
|
|
149
|
+
return prev.message === next.message && prev.streaming === next.streaming && prev.renderers === next.renderers && prev.fallbackRenderer === next.fallbackRenderer;
|
|
150
|
+
}
|
|
151
|
+
const MessageBlock = memo(MessageBlockImpl, areMessageBlockPropsEqual);
|
|
152
|
+
const EMPTY_RENDERERS = {};
|
|
111
153
|
function ThreadTranscript({
|
|
112
154
|
messages,
|
|
113
155
|
liveParts,
|
|
114
|
-
liveStatus
|
|
156
|
+
liveStatus,
|
|
157
|
+
renderers: renderersProp,
|
|
158
|
+
fallbackRenderer = DEFAULT_FALLBACK_RENDERER
|
|
115
159
|
}) {
|
|
160
|
+
const renderers = useMemo(() => renderersProp ?? EMPTY_RENDERERS, [renderersProp]);
|
|
161
|
+
const liveMessage = useMemo(() => {
|
|
162
|
+
if (liveParts === void 0 || liveParts.length === 0) return null;
|
|
163
|
+
return { id: "__live__", role: "assistant", parts: liveParts, createdAt: 0 };
|
|
164
|
+
}, [liveParts]);
|
|
116
165
|
return /* @__PURE__ */ jsxs(Stack, { gap: "sm", children: [
|
|
117
|
-
messages.map((message) => /* @__PURE__ */ jsx(
|
|
118
|
-
|
|
166
|
+
messages.map((message) => /* @__PURE__ */ jsx(
|
|
167
|
+
MessageBlock,
|
|
168
|
+
{
|
|
169
|
+
message,
|
|
170
|
+
renderers,
|
|
171
|
+
fallbackRenderer
|
|
172
|
+
},
|
|
173
|
+
message.id
|
|
174
|
+
)),
|
|
175
|
+
liveMessage !== null && /* @__PURE__ */ jsx("div", { "aria-live": "polite", "aria-atomic": "false", "aria-relevant": "additions", children: /* @__PURE__ */ jsx(
|
|
119
176
|
MessageBlock,
|
|
120
177
|
{
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
178
|
+
message: liveMessage,
|
|
179
|
+
streaming: liveStatus === "streaming",
|
|
180
|
+
renderers,
|
|
181
|
+
fallbackRenderer
|
|
124
182
|
}
|
|
125
183
|
) })
|
|
126
184
|
] });
|
|
127
185
|
}
|
|
128
186
|
export {
|
|
129
187
|
ThreadTranscript,
|
|
188
|
+
messageBlockRenderCounter,
|
|
130
189
|
threadPartRenderers
|
|
131
190
|
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { JSX } from 'react';
|
|
2
|
+
import type { ToolCallPart } from '../agent/index.js';
|
|
3
|
+
export type ToolChipProps = {
|
|
4
|
+
readonly part: ToolCallPart;
|
|
5
|
+
readonly defaultExpanded?: boolean;
|
|
6
|
+
/** Rendered only in 'approval-requested'. Omit both to render a read-only chip. */
|
|
7
|
+
readonly onApprove?: (approvalId: string) => void;
|
|
8
|
+
readonly onDeny?: (approvalId: string, reason?: string) => void;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* A collapsed-by-default row for a single tool-call part. All seven wire states render something
|
|
12
|
+
* sane; the switch above still gates an eighth (compile-time-unhandled) state as a tsc error via a
|
|
13
|
+
* `const _: never = part` assignment, but unlike a truly-closed switch, its `default` branch never
|
|
14
|
+
* throws at RUNTIME — a value from persisted/wire data that reaches here with a `state` this build
|
|
15
|
+
* doesn't recognize renders an inert 'unknown' chip instead of blanking the transcript.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* <ToolChip part={part} />
|
|
19
|
+
*/
|
|
20
|
+
export declare function ToolChip({ part, defaultExpanded, onApprove, onDeny, }: ToolChipProps): JSX.Element;
|
|
21
|
+
//# sourceMappingURL=tool-chip.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-chip.d.ts","sourceRoot":"","sources":["../../src/agent-chat/tool-chip.tsx"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,OAAO,CAAA;AAEhC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AA4E5C,MAAM,MAAM,aAAa,GAAG;IAC1B,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAA;IAC3B,QAAQ,CAAC,eAAe,CAAC,EAAE,OAAO,CAAA;IAClC,mFAAmF;IACnF,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAA;IACjD,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,KAAK,IAAI,CAAA;CAChE,CAAA;AAED;;;;;;;;;GASG;AACH,wBAAgB,QAAQ,CAAC,EACvB,IAAI,EACJ,eAAuB,EACvB,SAAS,EACT,MAAM,GACP,EAAE,aAAa,GAAG,GAAG,CAAC,OAAO,CAiG7B"}
|