@agents24/chat-react 0.1.2 → 0.1.4
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/README.md +12 -3
- package/dist/index.cjs +388 -146
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +124 -22
- package/dist/index.d.ts +124 -22
- package/dist/index.js +370 -137
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -21,32 +21,41 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
23
|
DEFAULT_THREAD_PAGE_SIZE: () => DEFAULT_THREAD_PAGE_SIZE,
|
|
24
|
+
DefaultChatPart: () => DefaultChatPart,
|
|
25
|
+
DefaultToolPart: () => DefaultToolPart,
|
|
24
26
|
LatestThreadViewport: () => LatestThreadViewport,
|
|
25
27
|
activeRunIdFromThread: () => activeRunIdFromThread,
|
|
26
28
|
activeRunIdFromThreadDetail: () => activeRunIdFromThreadDetail,
|
|
27
|
-
|
|
29
|
+
assistantTextFromParts: () => assistantTextFromParts,
|
|
30
|
+
assistantTextFromResponseBlocks: () => assistantTextFromResponseBlocks,
|
|
28
31
|
consumeSseResponse: () => consumeSseResponse,
|
|
29
32
|
createChatId: () => createChatId,
|
|
30
33
|
createFetchChatTransport: () => createFetchChatTransport,
|
|
34
|
+
getActiveStreamingTextPartId: () => getActiveStreamingTextPartId,
|
|
31
35
|
getLatestScrollTop: () => getLatestScrollTop,
|
|
32
36
|
hasStaleUnfinishedAssistantCache: () => hasStaleUnfinishedAssistantCache,
|
|
33
37
|
hasUnfinishedAssistantMessage: () => hasUnfinishedAssistantMessage,
|
|
38
|
+
isActiveStreamingTextPart: () => isActiveStreamingTextPart,
|
|
34
39
|
isAtTimelineLatestEdge: () => isAtTimelineLatestEdge,
|
|
35
40
|
isRunningThreadStatus: () => isRunningThreadStatus,
|
|
36
41
|
isScrollable: () => isScrollable,
|
|
37
42
|
latestContextWindowFromThread: () => latestContextWindowFromThread,
|
|
38
43
|
mergeReasoningSteps: () => mergeReasoningSteps,
|
|
39
44
|
parseSseBlock: () => parseSseBlock,
|
|
40
|
-
|
|
41
|
-
|
|
45
|
+
partsFromResponseBlocks: () => partsFromResponseBlocks,
|
|
46
|
+
reasoningStepsFromParts: () => reasoningStepsFromParts,
|
|
47
|
+
renderChatPart: () => renderChatPart,
|
|
42
48
|
shouldPrefetchOlder: () => shouldPrefetchOlder,
|
|
49
|
+
shouldUseTopOriginTimeline: () => shouldUseTopOriginTimeline,
|
|
43
50
|
textFromFinalOutput: () => textFromFinalOutput,
|
|
44
51
|
threadActivityDate: () => threadActivityDate,
|
|
45
52
|
threadDetailToMessages: () => threadDetailToMessages,
|
|
46
53
|
threadPaging: () => threadPaging,
|
|
47
54
|
titleFromMessage: () => titleFromMessage,
|
|
55
|
+
toolStateFromStatus: () => toolStateFromStatus,
|
|
48
56
|
useAgents24ChatController: () => useAgents24ChatController,
|
|
49
|
-
useLatestThreadViewport: () => useLatestThreadViewport
|
|
57
|
+
useLatestThreadViewport: () => useLatestThreadViewport,
|
|
58
|
+
useStreamingText: () => useStreamingText
|
|
50
59
|
});
|
|
51
60
|
module.exports = __toCommonJS(index_exports);
|
|
52
61
|
|
|
@@ -65,7 +74,8 @@ var titleFromMessage = (text, files = []) => {
|
|
|
65
74
|
return base.replace(/\s+/g, " ").slice(0, 48);
|
|
66
75
|
};
|
|
67
76
|
var threadActivityDate = (thread) => String(thread.updated_at || thread.last_activity_at || thread.created_at || (/* @__PURE__ */ new Date()).toISOString());
|
|
68
|
-
var
|
|
77
|
+
var assistantTextFromResponseBlocks = (blocks) => (blocks || []).filter((block) => block.kind === "assistant_text" && typeof block.text === "string").map((block) => String(block.text)).join("\n\n").trim();
|
|
78
|
+
var assistantTextFromParts = (parts) => (parts || []).filter((part) => part.kind === "text").map((part) => part.text).join("\n\n").trim();
|
|
69
79
|
var textFromFinalOutput = (value) => {
|
|
70
80
|
if (typeof value === "string") return value;
|
|
71
81
|
if (!value || typeof value !== "object") return "";
|
|
@@ -110,95 +120,126 @@ var assistantTextFromEvents = (events) => {
|
|
|
110
120
|
if (typeof assistantText === "string" && assistantText.trim()) return assistantText;
|
|
111
121
|
return textFromFinalOutput(latestEventPayloadValue(events, "final_output"));
|
|
112
122
|
};
|
|
113
|
-
var
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
123
|
+
var asRecord = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
124
|
+
var optionalString = (value) => typeof value === "string" && value.trim() ? value.trim() : void 0;
|
|
125
|
+
var toolStateFromStatus = (status) => {
|
|
126
|
+
const normalized = String(status || "").trim().toLowerCase();
|
|
127
|
+
if (["failed", "error"].includes(normalized)) return "output-error";
|
|
128
|
+
if (["cancelled", "canceled"].includes(normalized)) return "cancelled";
|
|
129
|
+
if (["complete", "completed", "done", "success"].includes(normalized)) return "output-available";
|
|
130
|
+
if (["running", "active", "pending", "streaming"].includes(normalized)) return "input-available";
|
|
131
|
+
return "input-available";
|
|
117
132
|
};
|
|
118
|
-
var
|
|
119
|
-
var
|
|
120
|
-
var
|
|
121
|
-
const
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
if (
|
|
142
|
-
|
|
143
|
-
return name ? humanize(name) : actionLabels[toolActionKey(tool)];
|
|
144
|
-
};
|
|
145
|
-
var toolDetail = (tool) => {
|
|
146
|
-
const summary = String(tool.summary || "").trim();
|
|
147
|
-
const detail = String(tool.detail || "").trim();
|
|
148
|
-
return summary || detail || void 0;
|
|
149
|
-
};
|
|
150
|
-
var summarizeToolGroup = (tools) => {
|
|
151
|
-
if (tools.length === 1) return tools[0].title;
|
|
152
|
-
const counts = /* @__PURE__ */ new Map();
|
|
153
|
-
tools.forEach((tool) => counts.set(tool.actionKey, (counts.get(tool.actionKey) || 0) + 1));
|
|
154
|
-
return Array.from(counts.entries()).map(([key, count]) => `${actionLabels[key]} ${count}`).join(", ");
|
|
155
|
-
};
|
|
156
|
-
var toolGroupStatus = (tools) => {
|
|
157
|
-
if (tools.some((tool) => tool.status === "error")) return "error";
|
|
158
|
-
if (tools.some((tool) => tool.status === "running")) return "running";
|
|
159
|
-
return "done";
|
|
133
|
+
var toolNameFromRecord = (tool) => String(tool.toolName || tool.tool_name || tool.name || tool.slug || tool.action || "tool").trim() || "tool";
|
|
134
|
+
var toolCallIdFromRecords = (block, tool) => optionalString(tool.toolCallId) || optionalString(tool.tool_call_id) || optionalString(block.toolCallId) || optionalString(block.tool_call_id) || optionalString(block.id) || null;
|
|
135
|
+
var presentationFromTool = (tool) => {
|
|
136
|
+
const presentation = asRecord(tool.presentation);
|
|
137
|
+
const outputView = asRecord(tool.outputView) || asRecord(tool.output_view);
|
|
138
|
+
const next = presentation ? { ...presentation } : {};
|
|
139
|
+
[
|
|
140
|
+
"title",
|
|
141
|
+
"activity",
|
|
142
|
+
"detail",
|
|
143
|
+
"category",
|
|
144
|
+
"groupKey",
|
|
145
|
+
"groupLabel",
|
|
146
|
+
"showOutput",
|
|
147
|
+
"outputView"
|
|
148
|
+
].forEach((key) => {
|
|
149
|
+
if (tool[key] !== void 0) {
|
|
150
|
+
next[key] = tool[key];
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
if (tool.group_key !== void 0) next.group_key = tool.group_key;
|
|
154
|
+
if (tool.group_label !== void 0) next.group_label = tool.group_label;
|
|
155
|
+
if (tool.show_output !== void 0) next.show_output = tool.show_output;
|
|
156
|
+
if (outputView && next.outputView === void 0) next.outputView = outputView;
|
|
157
|
+
return Object.keys(next).length > 0 ? next : null;
|
|
160
158
|
};
|
|
161
|
-
var
|
|
162
|
-
const tool = block.tool || {};
|
|
163
|
-
const
|
|
159
|
+
var createToolPart = (block, index) => {
|
|
160
|
+
const tool = asRecord(block.tool) || {};
|
|
161
|
+
const toolName = toolNameFromRecord(tool);
|
|
162
|
+
const errorText = optionalString(tool.errorText) || optionalString(tool.error) || optionalString(block.error) || null;
|
|
164
163
|
return {
|
|
165
164
|
id: String(block.id || `${block.kind || "tool"}-${index}`),
|
|
165
|
+
type: `tool-${toolName}`,
|
|
166
166
|
kind: "tool",
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
167
|
+
toolName,
|
|
168
|
+
toolCallId: toolCallIdFromRecords(block, tool),
|
|
169
|
+
state: toolStateFromStatus(block.status),
|
|
170
|
+
input: tool.input ?? block.input,
|
|
171
|
+
output: tool.output ?? block.output,
|
|
172
|
+
errorText,
|
|
173
|
+
presentation: presentationFromTool(tool),
|
|
174
|
+
raw: block
|
|
172
175
|
};
|
|
173
176
|
};
|
|
174
|
-
var
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
tools: pendingTools
|
|
185
|
-
});
|
|
186
|
-
pendingTools = [];
|
|
187
|
-
};
|
|
177
|
+
var createDataPart = (block, index, name = String(block.kind || "data")) => ({
|
|
178
|
+
id: String(block.id || `${name}-${index}`),
|
|
179
|
+
type: "data",
|
|
180
|
+
kind: "data",
|
|
181
|
+
name,
|
|
182
|
+
data: block,
|
|
183
|
+
raw: block
|
|
184
|
+
});
|
|
185
|
+
var partsFromResponseBlocks = (blocks, fallbackText) => {
|
|
186
|
+
const parts = [];
|
|
188
187
|
(blocks || []).forEach((block, index) => {
|
|
189
188
|
const id = String(block.id || `${block.kind || "block"}-${index}`);
|
|
190
189
|
if (block.kind === "assistant_text" && typeof block.text === "string") {
|
|
191
|
-
|
|
192
|
-
|
|
190
|
+
parts.push({ id, type: "text", kind: "text", text: String(block.text), raw: block });
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
if (block.kind === "tool_call") {
|
|
194
|
+
parts.push(createToolPart(block, index));
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
if (block.kind === "ui_blocks") {
|
|
198
|
+
parts.push({
|
|
199
|
+
id,
|
|
200
|
+
type: "ui-blocks",
|
|
201
|
+
kind: "ui-blocks",
|
|
202
|
+
state: toolStateFromStatus(block.status),
|
|
203
|
+
toolCallId: optionalString(block.toolCallId) || optionalString(block.tool_call_id) || null,
|
|
204
|
+
contractVersion: optionalString(block.contractVersion) || optionalString(block.contract_version) || null,
|
|
205
|
+
bundle: asRecord(block.bundle),
|
|
206
|
+
errorText: optionalString(block.error) || null,
|
|
207
|
+
raw: block
|
|
208
|
+
});
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
if (block.kind === "reasoning_note") {
|
|
212
|
+
parts.push({
|
|
213
|
+
id,
|
|
214
|
+
type: "reasoning",
|
|
215
|
+
kind: "reasoning",
|
|
216
|
+
label: optionalString(block.label) || null,
|
|
217
|
+
text: optionalString(block.text) || optionalString(block.summary) || null,
|
|
218
|
+
status: optionalString(block.status) || null,
|
|
219
|
+
raw: block
|
|
220
|
+
});
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
if (block.kind === "approval_request") {
|
|
224
|
+
parts.push({ id, type: "approval", kind: "approval", raw: block });
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
if (block.kind === "error") {
|
|
228
|
+
parts.push({
|
|
229
|
+
id,
|
|
230
|
+
type: "error",
|
|
231
|
+
kind: "error",
|
|
232
|
+
errorText: optionalString(block.error) || optionalString(block.message) || "Error",
|
|
233
|
+
raw: block
|
|
234
|
+
});
|
|
193
235
|
return;
|
|
194
236
|
}
|
|
195
|
-
|
|
237
|
+
parts.push(createDataPart(block, index));
|
|
196
238
|
});
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
mapped.push({ id: "assistant-fallback-text", kind: "text", content: fallbackText });
|
|
239
|
+
if (!parts.some((part) => part.kind === "text") && fallbackText?.trim()) {
|
|
240
|
+
parts.push({ id: "assistant-fallback-text", type: "text", kind: "text", text: fallbackText });
|
|
200
241
|
}
|
|
201
|
-
return
|
|
242
|
+
return parts;
|
|
202
243
|
};
|
|
203
244
|
var mergeReasoningSteps = (steps, options) => {
|
|
204
245
|
if (!steps?.length) return [];
|
|
@@ -216,21 +257,20 @@ var mergeReasoningSteps = (steps, options) => {
|
|
|
216
257
|
});
|
|
217
258
|
return merged;
|
|
218
259
|
};
|
|
219
|
-
var
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
const tool = block.tool || {};
|
|
260
|
+
var reasoningStepsFromParts = (parts) => (parts || []).map((block) => {
|
|
261
|
+
if (block.kind === "tool") {
|
|
262
|
+
const label = optionalString(block.presentation?.activity) || optionalString(block.presentation?.title) || block.toolName;
|
|
223
263
|
return {
|
|
224
|
-
label
|
|
225
|
-
status: block.
|
|
226
|
-
description:
|
|
264
|
+
label,
|
|
265
|
+
status: block.state === "input-available" || block.state === "input-streaming" ? "active" : "complete",
|
|
266
|
+
description: optionalString(block.presentation?.detail) || ""
|
|
227
267
|
};
|
|
228
268
|
}
|
|
229
|
-
if (kind === "
|
|
269
|
+
if (block.kind === "reasoning") {
|
|
230
270
|
return {
|
|
231
|
-
label:
|
|
271
|
+
label: block.label || "Reasoning",
|
|
232
272
|
status: block.status === "running" ? "active" : "complete",
|
|
233
|
-
description:
|
|
273
|
+
description: block.text || ""
|
|
234
274
|
};
|
|
235
275
|
}
|
|
236
276
|
return null;
|
|
@@ -249,19 +289,21 @@ var turnToMessages = (turn, activeRunId) => {
|
|
|
249
289
|
role: "user",
|
|
250
290
|
content: userContent,
|
|
251
291
|
createdAt,
|
|
292
|
+
parts: userContent ? [{ id: `${baseId}-user-text`, type: "text", kind: "text", text: userContent }] : [],
|
|
252
293
|
attachments
|
|
253
294
|
});
|
|
254
295
|
}
|
|
255
|
-
const assistantText = turn.assistant_output_text ||
|
|
296
|
+
const assistantText = turn.assistant_output_text || assistantTextFromResponseBlocks(responseBlocks) || assistantTextFromEvents(turn.run_events) || textFromFinalOutput(turn.final_output);
|
|
256
297
|
if (assistantText || responseBlocks.length > 0 || isRunning) {
|
|
298
|
+
const parts = partsFromResponseBlocks(responseBlocks, assistantText);
|
|
257
299
|
messages.push({
|
|
258
300
|
id: `${baseId}-assistant`,
|
|
259
301
|
role: "assistant",
|
|
260
302
|
runId: turn.run_id || null,
|
|
261
|
-
content: assistantText,
|
|
303
|
+
content: assistantText || assistantTextFromParts(parts),
|
|
262
304
|
createdAt: turn.completed_at ? new Date(turn.completed_at) : createdAt,
|
|
263
|
-
|
|
264
|
-
reasoningSteps: mergeReasoningSteps(
|
|
305
|
+
parts,
|
|
306
|
+
reasoningSteps: mergeReasoningSteps(reasoningStepsFromParts(parts), { finalize: !isRunning }),
|
|
265
307
|
isFinal: !isRunning
|
|
266
308
|
});
|
|
267
309
|
}
|
|
@@ -475,7 +517,7 @@ function useAgents24ChatController({
|
|
|
475
517
|
createdAt: /* @__PURE__ */ new Date(),
|
|
476
518
|
reasoningSteps: input.reasoning,
|
|
477
519
|
isFinal: false,
|
|
478
|
-
|
|
520
|
+
parts: input.parts || []
|
|
479
521
|
});
|
|
480
522
|
messagesRef.current = next2;
|
|
481
523
|
return next2;
|
|
@@ -487,7 +529,7 @@ function useAgents24ChatController({
|
|
|
487
529
|
content: input.content,
|
|
488
530
|
reasoningSteps: input.reasoning,
|
|
489
531
|
isFinal: false,
|
|
490
|
-
|
|
532
|
+
parts: input.parts ?? next[index].parts
|
|
491
533
|
};
|
|
492
534
|
messagesRef.current = next;
|
|
493
535
|
return next;
|
|
@@ -503,7 +545,7 @@ function useAgents24ChatController({
|
|
|
503
545
|
(message) => input.messageId && message.id === input.messageId || input.runId && message.role === "assistant" && message.runId === input.runId
|
|
504
546
|
);
|
|
505
547
|
const existing = existingIndex >= 0 ? input.baseMessages[existingIndex] : void 0;
|
|
506
|
-
const
|
|
548
|
+
const parts = input.parts || existing?.parts || partsFromResponseBlocks(void 0, content);
|
|
507
549
|
const assistant = {
|
|
508
550
|
id: existing?.id || input.messageId || createId(),
|
|
509
551
|
role: "assistant",
|
|
@@ -511,13 +553,7 @@ function useAgents24ChatController({
|
|
|
511
553
|
content,
|
|
512
554
|
createdAt: /* @__PURE__ */ new Date(),
|
|
513
555
|
isFinal: true,
|
|
514
|
-
|
|
515
|
-
if (block.kind === "tool") return { ...block, status: input.error ? "error" : "done" };
|
|
516
|
-
if (block.kind === "tool_group") {
|
|
517
|
-
return { ...block, status: input.error ? "error" : "done", tools: block.tools.map((tool) => ({ ...tool, status: input.error ? "error" : "done" })) };
|
|
518
|
-
}
|
|
519
|
-
return block;
|
|
520
|
-
}),
|
|
556
|
+
parts,
|
|
521
557
|
reasoningSteps: mergeReasoningSteps(input.reasoning, { finalize: true }),
|
|
522
558
|
thinkingDurationMs: input.thinkingDurationMs
|
|
523
559
|
};
|
|
@@ -552,7 +588,11 @@ function useAgents24ChatController({
|
|
|
552
588
|
setIsLoadingOlder(false);
|
|
553
589
|
isLoadingOlderRef.current = false;
|
|
554
590
|
try {
|
|
555
|
-
const detail = await transport.getThread({
|
|
591
|
+
const detail = await transport.getThread({
|
|
592
|
+
threadId,
|
|
593
|
+
limit: pageSize,
|
|
594
|
+
includeRunEvents: false
|
|
595
|
+
});
|
|
556
596
|
if (activeThreadIdRef.current !== threadId || seq !== requestSeqRef.current) return;
|
|
557
597
|
const nextMessages = threadDetailToMessages(detail);
|
|
558
598
|
const paging = threadPaging(detail);
|
|
@@ -584,7 +624,12 @@ function useAgents24ChatController({
|
|
|
584
624
|
isLoadingOlderRef.current = true;
|
|
585
625
|
setIsLoadingOlder(true);
|
|
586
626
|
try {
|
|
587
|
-
const detail = await transport.getThread({
|
|
627
|
+
const detail = await transport.getThread({
|
|
628
|
+
threadId,
|
|
629
|
+
limit: pageSize,
|
|
630
|
+
beforeTurnIndex,
|
|
631
|
+
includeRunEvents: false
|
|
632
|
+
});
|
|
588
633
|
if (activeThreadIdRef.current !== threadId) return;
|
|
589
634
|
const older = threadDetailToMessages(detail);
|
|
590
635
|
const paging = threadPaging(detail);
|
|
@@ -608,16 +653,17 @@ function useAgents24ChatController({
|
|
|
608
653
|
if (event.run_id) activeRunIdRef.current = event.run_id;
|
|
609
654
|
setContextStatus((current) => mergeContextWindow(current, payload.context_window));
|
|
610
655
|
if (responseBlocks) {
|
|
611
|
-
const blockText = String(payload.assistant_output_text || "") ||
|
|
656
|
+
const blockText = String(payload.assistant_output_text || "") || assistantTextFromResponseBlocks(responseBlocks) || streamingContentRef.current;
|
|
612
657
|
if (blockText) setStreamingText(blockText);
|
|
613
|
-
const
|
|
658
|
+
const parts = partsFromResponseBlocks(responseBlocks, blockText);
|
|
659
|
+
const reasoning = mergeReasoningSteps([...reasoningRef.current, ...reasoningStepsFromParts(parts)]);
|
|
614
660
|
setReasoningSteps(reasoning);
|
|
615
661
|
setLiveAssistantMessage({
|
|
616
662
|
messageId: assistantMessageId,
|
|
617
663
|
runId: event.run_id || activeRunIdRef.current,
|
|
618
664
|
content: blockText,
|
|
619
665
|
reasoning,
|
|
620
|
-
|
|
666
|
+
parts,
|
|
621
667
|
baseMessages
|
|
622
668
|
});
|
|
623
669
|
}
|
|
@@ -647,7 +693,7 @@ function useAgents24ChatController({
|
|
|
647
693
|
thinkingDurationMs: Date.now() - startedAt,
|
|
648
694
|
messageId: assistantMessageId,
|
|
649
695
|
runId: event.run_id || activeRunIdRef.current,
|
|
650
|
-
|
|
696
|
+
parts: responseBlocks ? partsFromResponseBlocks(responseBlocks, finalText) : void 0,
|
|
651
697
|
error: isFailed ? String(payload.message || payload.error || event.diagnostics?.[0]?.message || onStreamErrorMessage?.(event) || "The chat run failed.") : void 0
|
|
652
698
|
});
|
|
653
699
|
},
|
|
@@ -674,6 +720,7 @@ function useAgents24ChatController({
|
|
|
674
720
|
role: "user",
|
|
675
721
|
content: input.message.text,
|
|
676
722
|
createdAt: /* @__PURE__ */ new Date(),
|
|
723
|
+
parts: input.message.text ? [{ id: createId(), type: "text", kind: "text", text: input.message.text }] : [],
|
|
677
724
|
attachments: input.message.files
|
|
678
725
|
};
|
|
679
726
|
baseMessages = [...messagesRef.current, userMessage];
|
|
@@ -685,6 +732,7 @@ function useAgents24ChatController({
|
|
|
685
732
|
content: "",
|
|
686
733
|
createdAt: /* @__PURE__ */ new Date(),
|
|
687
734
|
isFinal: false,
|
|
735
|
+
parts: [],
|
|
688
736
|
reasoningSteps: []
|
|
689
737
|
};
|
|
690
738
|
const liveMessages = [...baseMessages, assistantMessage];
|
|
@@ -895,6 +943,7 @@ function useAgents24ChatController({
|
|
|
895
943
|
createdAt: /* @__PURE__ */ new Date(),
|
|
896
944
|
isFinal: Boolean(input.isFinal),
|
|
897
945
|
isVoice: input.role === "user",
|
|
946
|
+
parts: content ? [{ id: createId(), type: "text", kind: "text", text: content }] : [],
|
|
898
947
|
citations: input.citations,
|
|
899
948
|
reasoningSteps: input.reasoningSteps
|
|
900
949
|
};
|
|
@@ -958,6 +1007,53 @@ function useAgents24ChatController({
|
|
|
958
1007
|
]);
|
|
959
1008
|
}
|
|
960
1009
|
|
|
1010
|
+
// src/renderers.tsx
|
|
1011
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
1012
|
+
var DefaultToolPart = ({ part }) => {
|
|
1013
|
+
const label = typeof part.presentation?.activity === "string" ? part.presentation.activity : typeof part.presentation?.title === "string" ? part.presentation.title : part.toolName;
|
|
1014
|
+
const detail = typeof part.presentation?.detail === "string" ? part.presentation.detail : part.errorText || part.state;
|
|
1015
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { "data-agents24-tool-part": part.type, "data-state": part.state, children: [
|
|
1016
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { children: label }),
|
|
1017
|
+
detail ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { children: detail }) : null
|
|
1018
|
+
] });
|
|
1019
|
+
};
|
|
1020
|
+
var DefaultChatPart = ({
|
|
1021
|
+
part,
|
|
1022
|
+
message,
|
|
1023
|
+
renderOptions
|
|
1024
|
+
}) => {
|
|
1025
|
+
if (renderOptions?.renderPart) {
|
|
1026
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: renderOptions.renderPart(part, message) });
|
|
1027
|
+
}
|
|
1028
|
+
if (part.kind === "text") return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: part.text });
|
|
1029
|
+
if (part.kind === "tool") {
|
|
1030
|
+
const ToolRenderer = renderOptions?.toolRenderers?.[part.type] || renderOptions?.fallbackToolRenderer || DefaultToolPart;
|
|
1031
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: ToolRenderer({ part, message }) });
|
|
1032
|
+
}
|
|
1033
|
+
if (part.kind === "reasoning") {
|
|
1034
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { "data-agents24-reasoning-part": true, children: part.text || part.label });
|
|
1035
|
+
}
|
|
1036
|
+
if (part.kind === "ui-blocks") {
|
|
1037
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { "data-agents24-ui-blocks-part": true, "data-state": part.state });
|
|
1038
|
+
}
|
|
1039
|
+
if (part.kind === "approval") {
|
|
1040
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { "data-agents24-approval-part": true });
|
|
1041
|
+
}
|
|
1042
|
+
if (part.kind === "error") {
|
|
1043
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { "data-agents24-error-part": true, children: part.errorText });
|
|
1044
|
+
}
|
|
1045
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { "data-agents24-data-part": part.name });
|
|
1046
|
+
};
|
|
1047
|
+
var renderChatPart = (part, message, renderOptions) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1048
|
+
DefaultChatPart,
|
|
1049
|
+
{
|
|
1050
|
+
part,
|
|
1051
|
+
message,
|
|
1052
|
+
renderOptions
|
|
1053
|
+
},
|
|
1054
|
+
part.id
|
|
1055
|
+
);
|
|
1056
|
+
|
|
961
1057
|
// src/sse.ts
|
|
962
1058
|
var parseSseBlock = (block) => {
|
|
963
1059
|
const data = block.split("\n").filter((line) => line.startsWith("data:")).map((line) => line.replace(/^data:\s?/, "")).join("\n").trim();
|
|
@@ -1000,6 +1096,140 @@ var consumeSseResponse = async (response, onEvent) => {
|
|
|
1000
1096
|
return { threadId, runId };
|
|
1001
1097
|
};
|
|
1002
1098
|
|
|
1099
|
+
// src/streaming-text.ts
|
|
1100
|
+
var import_react2 = require("react");
|
|
1101
|
+
var DEFAULT_COMPLETED_TEXT_CACHE_SIZE = 200;
|
|
1102
|
+
var defaultCompletedTextCache = /* @__PURE__ */ new Map();
|
|
1103
|
+
var defaultStreamingTextCache = {
|
|
1104
|
+
get: (id) => defaultCompletedTextCache.get(id),
|
|
1105
|
+
set: (id, text) => {
|
|
1106
|
+
defaultCompletedTextCache.set(id, text);
|
|
1107
|
+
if (defaultCompletedTextCache.size > DEFAULT_COMPLETED_TEXT_CACHE_SIZE) {
|
|
1108
|
+
const firstKey = defaultCompletedTextCache.keys().next().value;
|
|
1109
|
+
if (firstKey) defaultCompletedTextCache.delete(firstKey);
|
|
1110
|
+
}
|
|
1111
|
+
}
|
|
1112
|
+
};
|
|
1113
|
+
var getActiveStreamingTextPartId = (message, streamingMessageId) => {
|
|
1114
|
+
if (message.role !== "assistant" || streamingMessageId !== message.id) return null;
|
|
1115
|
+
return message.parts.slice().reverse().find((part) => part.kind === "text")?.id || null;
|
|
1116
|
+
};
|
|
1117
|
+
var isActiveStreamingTextPart = (message, part, streamingMessageId) => part.kind === "text" && part.id === getActiveStreamingTextPartId(message, streamingMessageId);
|
|
1118
|
+
function useStreamingText({
|
|
1119
|
+
id,
|
|
1120
|
+
isStreaming,
|
|
1121
|
+
text,
|
|
1122
|
+
cache = defaultStreamingTextCache,
|
|
1123
|
+
charsPerSecond = 72,
|
|
1124
|
+
catchupThreshold = 40,
|
|
1125
|
+
maxCatchupChars = 20
|
|
1126
|
+
}) {
|
|
1127
|
+
const cacheAdapter = cache === false ? null : cache;
|
|
1128
|
+
const [displayedText, setDisplayedText] = (0, import_react2.useState)(() => {
|
|
1129
|
+
const cachedText = cacheAdapter?.get(id);
|
|
1130
|
+
return isStreaming && cachedText !== text ? "" : text;
|
|
1131
|
+
});
|
|
1132
|
+
const targetRef = (0, import_react2.useRef)(text);
|
|
1133
|
+
const displayedRef = (0, import_react2.useRef)(displayedText);
|
|
1134
|
+
const rafRef = (0, import_react2.useRef)(null);
|
|
1135
|
+
const lastFrameAtRef = (0, import_react2.useRef)(null);
|
|
1136
|
+
const idRef = (0, import_react2.useRef)(id);
|
|
1137
|
+
const shouldAnimateRef = (0, import_react2.useRef)(isStreaming);
|
|
1138
|
+
(0, import_react2.useEffect)(() => {
|
|
1139
|
+
if (isStreaming || !text) return;
|
|
1140
|
+
cacheAdapter?.set(id, text);
|
|
1141
|
+
}, [cacheAdapter, id, isStreaming, text]);
|
|
1142
|
+
(0, import_react2.useEffect)(() => {
|
|
1143
|
+
targetRef.current = text;
|
|
1144
|
+
}, [text]);
|
|
1145
|
+
(0, import_react2.useEffect)(() => {
|
|
1146
|
+
if (idRef.current === id) return;
|
|
1147
|
+
idRef.current = id;
|
|
1148
|
+
const cachedText = cacheAdapter?.get(id);
|
|
1149
|
+
const initial = isStreaming && cachedText !== text ? "" : text;
|
|
1150
|
+
shouldAnimateRef.current = isStreaming && initial !== text;
|
|
1151
|
+
displayedRef.current = initial;
|
|
1152
|
+
setDisplayedText(initial);
|
|
1153
|
+
if (rafRef.current !== null) {
|
|
1154
|
+
cancelAnimationFrame(rafRef.current);
|
|
1155
|
+
rafRef.current = null;
|
|
1156
|
+
}
|
|
1157
|
+
lastFrameAtRef.current = null;
|
|
1158
|
+
}, [cacheAdapter, id, isStreaming, text]);
|
|
1159
|
+
(0, import_react2.useEffect)(() => {
|
|
1160
|
+
if (typeof window === "undefined") {
|
|
1161
|
+
displayedRef.current = text;
|
|
1162
|
+
setDisplayedText(text);
|
|
1163
|
+
return;
|
|
1164
|
+
}
|
|
1165
|
+
const reduceMotion = typeof window.matchMedia === "function" && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
1166
|
+
if (reduceMotion) {
|
|
1167
|
+
displayedRef.current = text;
|
|
1168
|
+
setDisplayedText(text);
|
|
1169
|
+
shouldAnimateRef.current = false;
|
|
1170
|
+
return;
|
|
1171
|
+
}
|
|
1172
|
+
const cachedText = cacheAdapter?.get(id);
|
|
1173
|
+
if (cachedText === text) {
|
|
1174
|
+
displayedRef.current = text;
|
|
1175
|
+
setDisplayedText(text);
|
|
1176
|
+
shouldAnimateRef.current = false;
|
|
1177
|
+
return;
|
|
1178
|
+
}
|
|
1179
|
+
if (isStreaming) {
|
|
1180
|
+
shouldAnimateRef.current = true;
|
|
1181
|
+
}
|
|
1182
|
+
if (!shouldAnimateRef.current) {
|
|
1183
|
+
displayedRef.current = text;
|
|
1184
|
+
setDisplayedText(text);
|
|
1185
|
+
return;
|
|
1186
|
+
}
|
|
1187
|
+
if (!text.startsWith(displayedRef.current)) {
|
|
1188
|
+
displayedRef.current = "";
|
|
1189
|
+
setDisplayedText("");
|
|
1190
|
+
}
|
|
1191
|
+
const tick = (timestamp) => {
|
|
1192
|
+
const previousTimestamp = lastFrameAtRef.current ?? timestamp;
|
|
1193
|
+
lastFrameAtRef.current = timestamp;
|
|
1194
|
+
const target = targetRef.current;
|
|
1195
|
+
const current = displayedRef.current;
|
|
1196
|
+
if (current.length >= target.length) {
|
|
1197
|
+
shouldAnimateRef.current = false;
|
|
1198
|
+
rafRef.current = null;
|
|
1199
|
+
return;
|
|
1200
|
+
}
|
|
1201
|
+
const elapsedMs = Math.max(8, timestamp - previousTimestamp);
|
|
1202
|
+
const charsFromTime = Math.max(1, Math.floor(elapsedMs / 1e3 * charsPerSecond));
|
|
1203
|
+
const gap = target.length - current.length;
|
|
1204
|
+
const catchupStep = gap > catchupThreshold ? Math.min(maxCatchupChars, Math.ceil(gap / 10)) : charsFromTime;
|
|
1205
|
+
const nextLength = Math.min(
|
|
1206
|
+
target.length,
|
|
1207
|
+
current.length + Math.max(charsFromTime, catchupStep)
|
|
1208
|
+
);
|
|
1209
|
+
const next = target.slice(0, nextLength);
|
|
1210
|
+
displayedRef.current = next;
|
|
1211
|
+
setDisplayedText(next);
|
|
1212
|
+
rafRef.current = window.requestAnimationFrame(tick);
|
|
1213
|
+
};
|
|
1214
|
+
if (rafRef.current === null && displayedRef.current.length < text.length) {
|
|
1215
|
+
rafRef.current = window.requestAnimationFrame(tick);
|
|
1216
|
+
}
|
|
1217
|
+
return () => {
|
|
1218
|
+
if (rafRef.current !== null) {
|
|
1219
|
+
cancelAnimationFrame(rafRef.current);
|
|
1220
|
+
rafRef.current = null;
|
|
1221
|
+
}
|
|
1222
|
+
lastFrameAtRef.current = null;
|
|
1223
|
+
};
|
|
1224
|
+
}, [cacheAdapter, catchupThreshold, charsPerSecond, id, isStreaming, maxCatchupChars, text]);
|
|
1225
|
+
return {
|
|
1226
|
+
displayedText,
|
|
1227
|
+
isAnimating: isStreaming,
|
|
1228
|
+
mode: isStreaming ? "streaming" : "static",
|
|
1229
|
+
parseIncompleteMarkdown: isStreaming
|
|
1230
|
+
};
|
|
1231
|
+
}
|
|
1232
|
+
|
|
1003
1233
|
// src/transport.ts
|
|
1004
1234
|
var jsonHeaders = (headers) => ({
|
|
1005
1235
|
...headers || {},
|
|
@@ -1081,8 +1311,8 @@ var createFetchChatTransport = ({
|
|
|
1081
1311
|
};
|
|
1082
1312
|
|
|
1083
1313
|
// src/viewport.tsx
|
|
1084
|
-
var
|
|
1085
|
-
var
|
|
1314
|
+
var import_react3 = require("react");
|
|
1315
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
1086
1316
|
var LATEST_EDGE_THRESHOLD_PX = 2;
|
|
1087
1317
|
var MIN_OLDER_PREFETCH_PX = 320;
|
|
1088
1318
|
var MAX_OLDER_PREFETCH_PX = 900;
|
|
@@ -1093,6 +1323,11 @@ var isAtTimelineLatestEdge = (element, isTopOrigin) => {
|
|
|
1093
1323
|
};
|
|
1094
1324
|
var shouldPrefetchOlder = (element) => Math.abs(element.scrollTop) + element.clientHeight >= element.scrollHeight - Math.min(MAX_OLDER_PREFETCH_PX, Math.max(MIN_OLDER_PREFETCH_PX, element.clientHeight * 0.75));
|
|
1095
1325
|
var getLatestScrollTop = (element, isTopOrigin) => isTopOrigin ? Math.max(0, element.scrollHeight - element.clientHeight) : 0;
|
|
1326
|
+
var shouldUseTopOriginTimeline = ({
|
|
1327
|
+
hasOlder,
|
|
1328
|
+
itemCount,
|
|
1329
|
+
topOriginMaxItems = 4
|
|
1330
|
+
}) => !hasOlder && itemCount > 0 && itemCount <= topOriginMaxItems;
|
|
1096
1331
|
function useLatestThreadViewport({
|
|
1097
1332
|
itemCount,
|
|
1098
1333
|
hasOlder,
|
|
@@ -1102,19 +1337,17 @@ function useLatestThreadViewport({
|
|
|
1102
1337
|
shouldAutoFollow = true,
|
|
1103
1338
|
topOriginMaxItems = 4
|
|
1104
1339
|
}) {
|
|
1105
|
-
const scrollContainerRef = (0,
|
|
1106
|
-
const olderPagePreserveRef = (0,
|
|
1107
|
-
const olderPageRequestInFlightRef = (0,
|
|
1108
|
-
const intrinsicResizePreserveRef = (0,
|
|
1109
|
-
const autoFollowLatestRef = (0,
|
|
1110
|
-
const programmaticScrollRef = (0,
|
|
1111
|
-
const programmaticScrollTimeoutRef = (0,
|
|
1112
|
-
const activeStreamKeyRef = (0,
|
|
1113
|
-
const [isAtLatest, setIsAtLatest] = (0,
|
|
1114
|
-
const
|
|
1115
|
-
const
|
|
1116
|
-
const isTopOrigin = topOriginCandidate && !topOriginCandidateOverflows;
|
|
1117
|
-
const markProgrammaticScroll = (0, import_react2.useCallback)(() => {
|
|
1340
|
+
const scrollContainerRef = (0, import_react3.useRef)(null);
|
|
1341
|
+
const olderPagePreserveRef = (0, import_react3.useRef)(null);
|
|
1342
|
+
const olderPageRequestInFlightRef = (0, import_react3.useRef)(false);
|
|
1343
|
+
const intrinsicResizePreserveRef = (0, import_react3.useRef)(null);
|
|
1344
|
+
const autoFollowLatestRef = (0, import_react3.useRef)(true);
|
|
1345
|
+
const programmaticScrollRef = (0, import_react3.useRef)(false);
|
|
1346
|
+
const programmaticScrollTimeoutRef = (0, import_react3.useRef)(null);
|
|
1347
|
+
const activeStreamKeyRef = (0, import_react3.useRef)(null);
|
|
1348
|
+
const [isAtLatest, setIsAtLatest] = (0, import_react3.useState)(true);
|
|
1349
|
+
const isTopOrigin = shouldUseTopOriginTimeline({ hasOlder, itemCount, topOriginMaxItems });
|
|
1350
|
+
const markProgrammaticScroll = (0, import_react3.useCallback)(() => {
|
|
1118
1351
|
programmaticScrollRef.current = true;
|
|
1119
1352
|
if (programmaticScrollTimeoutRef.current) clearTimeout(programmaticScrollTimeoutRef.current);
|
|
1120
1353
|
programmaticScrollTimeoutRef.current = setTimeout(() => {
|
|
@@ -1122,29 +1355,24 @@ function useLatestThreadViewport({
|
|
|
1122
1355
|
programmaticScrollTimeoutRef.current = null;
|
|
1123
1356
|
}, 80);
|
|
1124
1357
|
}, []);
|
|
1125
|
-
const scrollToLatest = (0,
|
|
1358
|
+
const scrollToLatest = (0, import_react3.useCallback)(() => {
|
|
1126
1359
|
const element = scrollContainerRef.current;
|
|
1127
1360
|
if (!element) return;
|
|
1128
1361
|
markProgrammaticScroll();
|
|
1129
1362
|
element.scrollTop = getLatestScrollTop(element, isTopOrigin);
|
|
1130
1363
|
setIsAtLatest(true);
|
|
1131
1364
|
}, [isTopOrigin, markProgrammaticScroll]);
|
|
1132
|
-
(0,
|
|
1365
|
+
(0, import_react3.useEffect)(() => {
|
|
1133
1366
|
return () => {
|
|
1134
1367
|
if (programmaticScrollTimeoutRef.current) clearTimeout(programmaticScrollTimeoutRef.current);
|
|
1135
1368
|
const preserve = intrinsicResizePreserveRef.current;
|
|
1136
1369
|
if (preserve?.frame !== null && preserve?.frame !== void 0) cancelAnimationFrame(preserve.frame);
|
|
1137
1370
|
};
|
|
1138
1371
|
}, []);
|
|
1139
|
-
(0,
|
|
1372
|
+
(0, import_react3.useLayoutEffect)(() => {
|
|
1140
1373
|
const element = scrollContainerRef.current;
|
|
1141
1374
|
const preserve = olderPagePreserveRef.current;
|
|
1142
1375
|
if (!element) return;
|
|
1143
|
-
if (topOriginCandidate) {
|
|
1144
|
-
setTopOriginCandidateOverflows(isScrollable(element));
|
|
1145
|
-
} else if (topOriginCandidateOverflows) {
|
|
1146
|
-
setTopOriginCandidateOverflows(false);
|
|
1147
|
-
}
|
|
1148
1376
|
if (!preserve) {
|
|
1149
1377
|
setIsAtLatest(isAtTimelineLatestEdge(element, isTopOrigin));
|
|
1150
1378
|
return;
|
|
@@ -1155,8 +1383,8 @@ function useLatestThreadViewport({
|
|
|
1155
1383
|
olderPagePreserveRef.current = null;
|
|
1156
1384
|
olderPageRequestInFlightRef.current = false;
|
|
1157
1385
|
setIsAtLatest(isAtTimelineLatestEdge(element, isTopOrigin));
|
|
1158
|
-
}, [isTopOrigin, itemCount, markProgrammaticScroll
|
|
1159
|
-
const handleScroll = (0,
|
|
1386
|
+
}, [isTopOrigin, itemCount, markProgrammaticScroll]);
|
|
1387
|
+
const handleScroll = (0, import_react3.useCallback)(
|
|
1160
1388
|
(event) => {
|
|
1161
1389
|
const element = event.currentTarget;
|
|
1162
1390
|
const atLatest = isAtTimelineLatestEdge(element, isTopOrigin);
|
|
@@ -1180,7 +1408,7 @@ function useLatestThreadViewport({
|
|
|
1180
1408
|
},
|
|
1181
1409
|
[hasOlder, isLoadingOlder, isTopOrigin, onLoadOlder]
|
|
1182
1410
|
);
|
|
1183
|
-
const preserveIntrinsicResize = (0,
|
|
1411
|
+
const preserveIntrinsicResize = (0, import_react3.useCallback)(() => {
|
|
1184
1412
|
const element = scrollContainerRef.current;
|
|
1185
1413
|
if (!element || isTopOrigin) return;
|
|
1186
1414
|
const active = intrinsicResizePreserveRef.current;
|
|
@@ -1209,25 +1437,30 @@ function useLatestThreadViewport({
|
|
|
1209
1437
|
};
|
|
1210
1438
|
intrinsicResizePreserveRef.current.frame = requestAnimationFrame(preserveFrame);
|
|
1211
1439
|
}, [isTopOrigin, markProgrammaticScroll]);
|
|
1212
|
-
(0,
|
|
1440
|
+
(0, import_react3.useEffect)(() => {
|
|
1213
1441
|
const key = activeStreamKey || null;
|
|
1214
1442
|
if (!key || activeStreamKeyRef.current === key) {
|
|
1215
1443
|
activeStreamKeyRef.current = key;
|
|
1216
1444
|
return;
|
|
1217
1445
|
}
|
|
1218
1446
|
autoFollowLatestRef.current = true;
|
|
1447
|
+
if (isTopOrigin) {
|
|
1448
|
+
activeStreamKeyRef.current = key;
|
|
1449
|
+
return;
|
|
1450
|
+
}
|
|
1219
1451
|
const frame = requestAnimationFrame(scrollToLatest);
|
|
1220
1452
|
activeStreamKeyRef.current = key;
|
|
1221
1453
|
return () => cancelAnimationFrame(frame);
|
|
1222
|
-
}, [activeStreamKey, scrollToLatest]);
|
|
1223
|
-
(0,
|
|
1454
|
+
}, [activeStreamKey, isTopOrigin, scrollToLatest]);
|
|
1455
|
+
(0, import_react3.useLayoutEffect)(() => {
|
|
1456
|
+
if (isTopOrigin) return;
|
|
1224
1457
|
if (!activeStreamKey || !shouldAutoFollow || !autoFollowLatestRef.current) return;
|
|
1225
1458
|
if (isLoadingOlder || olderPageRequestInFlightRef.current) return;
|
|
1226
1459
|
const frame = requestAnimationFrame(() => {
|
|
1227
1460
|
if (autoFollowLatestRef.current && !isLoadingOlder && !olderPageRequestInFlightRef.current) scrollToLatest();
|
|
1228
1461
|
});
|
|
1229
1462
|
return () => cancelAnimationFrame(frame);
|
|
1230
|
-
}, [activeStreamKey, isLoadingOlder, itemCount, scrollToLatest, shouldAutoFollow]);
|
|
1463
|
+
}, [activeStreamKey, isLoadingOlder, isTopOrigin, itemCount, scrollToLatest, shouldAutoFollow]);
|
|
1231
1464
|
return {
|
|
1232
1465
|
scrollContainerRef,
|
|
1233
1466
|
isAtLatest,
|
|
@@ -1256,8 +1489,8 @@ function LatestThreadViewport({
|
|
|
1256
1489
|
onLoadOlder,
|
|
1257
1490
|
activeStreamKey
|
|
1258
1491
|
});
|
|
1259
|
-
const timelineItems = (0,
|
|
1260
|
-
return /* @__PURE__ */ (0,
|
|
1492
|
+
const timelineItems = (0, import_react3.useMemo)(() => viewport.isTopOrigin ? items : [...items].reverse(), [items, viewport.isTopOrigin]);
|
|
1493
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
1261
1494
|
"div",
|
|
1262
1495
|
{
|
|
1263
1496
|
ref: viewport.scrollContainerRef,
|
|
@@ -1276,31 +1509,40 @@ function LatestThreadViewport({
|
|
|
1276
1509
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1277
1510
|
0 && (module.exports = {
|
|
1278
1511
|
DEFAULT_THREAD_PAGE_SIZE,
|
|
1512
|
+
DefaultChatPart,
|
|
1513
|
+
DefaultToolPart,
|
|
1279
1514
|
LatestThreadViewport,
|
|
1280
1515
|
activeRunIdFromThread,
|
|
1281
1516
|
activeRunIdFromThreadDetail,
|
|
1282
|
-
|
|
1517
|
+
assistantTextFromParts,
|
|
1518
|
+
assistantTextFromResponseBlocks,
|
|
1283
1519
|
consumeSseResponse,
|
|
1284
1520
|
createChatId,
|
|
1285
1521
|
createFetchChatTransport,
|
|
1522
|
+
getActiveStreamingTextPartId,
|
|
1286
1523
|
getLatestScrollTop,
|
|
1287
1524
|
hasStaleUnfinishedAssistantCache,
|
|
1288
1525
|
hasUnfinishedAssistantMessage,
|
|
1526
|
+
isActiveStreamingTextPart,
|
|
1289
1527
|
isAtTimelineLatestEdge,
|
|
1290
1528
|
isRunningThreadStatus,
|
|
1291
1529
|
isScrollable,
|
|
1292
1530
|
latestContextWindowFromThread,
|
|
1293
1531
|
mergeReasoningSteps,
|
|
1294
1532
|
parseSseBlock,
|
|
1295
|
-
|
|
1296
|
-
|
|
1533
|
+
partsFromResponseBlocks,
|
|
1534
|
+
reasoningStepsFromParts,
|
|
1535
|
+
renderChatPart,
|
|
1297
1536
|
shouldPrefetchOlder,
|
|
1537
|
+
shouldUseTopOriginTimeline,
|
|
1298
1538
|
textFromFinalOutput,
|
|
1299
1539
|
threadActivityDate,
|
|
1300
1540
|
threadDetailToMessages,
|
|
1301
1541
|
threadPaging,
|
|
1302
1542
|
titleFromMessage,
|
|
1543
|
+
toolStateFromStatus,
|
|
1303
1544
|
useAgents24ChatController,
|
|
1304
|
-
useLatestThreadViewport
|
|
1545
|
+
useLatestThreadViewport,
|
|
1546
|
+
useStreamingText
|
|
1305
1547
|
});
|
|
1306
1548
|
//# sourceMappingURL=index.cjs.map
|