bs-agent 0.0.28 → 0.0.29
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 +81 -55
- package/dist/react/index.cjs +149 -179
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.cts +27 -33
- package/dist/react/index.d.ts +27 -33
- package/dist/react/index.js +150 -179
- package/dist/react/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -10,8 +10,8 @@ streaming support.
|
|
|
10
10
|
- ⚛️ **React bindings** — hooks & context for chat UIs with session management
|
|
11
11
|
- 💬 **Multi-turn** — session-based conversations with persistent history
|
|
12
12
|
- 🛑 **Abort** — cancel any streaming request mid-flight
|
|
13
|
-
- 🐛 **
|
|
14
|
-
|
|
13
|
+
- 🐛 **Inline debug info** — tool calls, reasoning, handoffs & errors as
|
|
14
|
+
message parts
|
|
15
15
|
- 📦 **Zero extra deps** — native `fetch` + `ReadableStream`, only `zod` as a
|
|
16
16
|
dependency
|
|
17
17
|
|
|
@@ -318,7 +318,7 @@ function App() {
|
|
|
318
318
|
## `useAgent` Hook
|
|
319
319
|
|
|
320
320
|
The main hook for interacting with an agent. Manages messages, streaming,
|
|
321
|
-
|
|
321
|
+
and sessions.
|
|
322
322
|
|
|
323
323
|
```tsx
|
|
324
324
|
import { useAgent } from "@buildship/agent/react";
|
|
@@ -335,7 +335,6 @@ function ChatPage() {
|
|
|
335
335
|
switchSession, // (sessionId?) => void — switch to a session (or create new)
|
|
336
336
|
deleteSession, // (sessionId) => void — delete a session
|
|
337
337
|
addOptimisticMessage, // (input) => void — add a user message immediately
|
|
338
|
-
debugData, // Record<string, DebugDataType> — debug entries by execution ID
|
|
339
338
|
} = useAgent(
|
|
340
339
|
"agent-id",
|
|
341
340
|
"https://your-project.buildship.run/executeAgent/AGENT_ID",
|
|
@@ -564,8 +563,8 @@ Messages can contain rich, interleaved content via `parts`:
|
|
|
564
563
|
type Message = {
|
|
565
564
|
role: "user" | "agent";
|
|
566
565
|
content: string; // Full text content
|
|
567
|
-
parts?: MessagePart[]; // Rich content (text
|
|
568
|
-
executionId?: string; //
|
|
566
|
+
parts?: MessagePart[]; // Rich content (text, widgets, tool calls, reasoning, etc.)
|
|
567
|
+
executionId?: string; // Execution ID for this turn
|
|
569
568
|
attachments?: Array<ImagePart | FilePart>; // Multimodal user message attachments
|
|
570
569
|
};
|
|
571
570
|
|
|
@@ -579,11 +578,26 @@ type MessagePart =
|
|
|
579
578
|
paused?: boolean;
|
|
580
579
|
status?: "pending" | "submitted";
|
|
581
580
|
result?: any;
|
|
582
|
-
}
|
|
581
|
+
}
|
|
582
|
+
| {
|
|
583
|
+
type: "tool_call";
|
|
584
|
+
toolName: string;
|
|
585
|
+
callId: string;
|
|
586
|
+
toolType: ToolType;
|
|
587
|
+
status: "progress" | "complete" | "error";
|
|
588
|
+
inputs?: unknown;
|
|
589
|
+
output?: unknown;
|
|
590
|
+
error?: string;
|
|
591
|
+
serverName?: string; // MCP server name
|
|
592
|
+
}
|
|
593
|
+
| { type: "reasoning"; reasoning: string; index?: number }
|
|
594
|
+
| { type: "handoff"; agentName: string }
|
|
595
|
+
| { type: "run_error"; message: string; code?: string };
|
|
583
596
|
```
|
|
584
597
|
|
|
585
598
|
> **Tip:** When rendering messages, iterate over `msg.parts` instead of
|
|
586
|
-
> `msg.content` to get
|
|
599
|
+
> `msg.content` to get text, widgets, tool calls, reasoning, handoffs, and
|
|
600
|
+
> errors interleaved in chronological order.
|
|
587
601
|
|
|
588
602
|
## Sessions
|
|
589
603
|
|
|
@@ -618,48 +632,27 @@ type Session = {
|
|
|
618
632
|
};
|
|
619
633
|
```
|
|
620
634
|
|
|
621
|
-
## Debug
|
|
635
|
+
## Inline Debug Info
|
|
622
636
|
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
637
|
+
Tool calls, reasoning, agent handoffs, and errors are all embedded directly in
|
|
638
|
+
the agent message's `parts` array — no separate debug state. Filter by `type`
|
|
639
|
+
to render them:
|
|
626
640
|
|
|
627
641
|
```tsx
|
|
628
|
-
const {
|
|
629
|
-
|
|
630
|
-
// Get debug
|
|
631
|
-
const
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
type
|
|
642
|
+
const { messages } = useAgent(...);
|
|
643
|
+
|
|
644
|
+
// Get debug parts from an agent message
|
|
645
|
+
const debugParts = message.parts?.filter(
|
|
646
|
+
(p) =>
|
|
647
|
+
p.type === "tool_call" ||
|
|
648
|
+
p.type === "reasoning" ||
|
|
649
|
+
p.type === "handoff" ||
|
|
650
|
+
p.type === "run_error",
|
|
651
|
+
);
|
|
635
652
|
```
|
|
636
653
|
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
```ts
|
|
640
|
-
type ToolExecutionItem = {
|
|
641
|
-
itemType: "tool_call";
|
|
642
|
-
toolName: string;
|
|
643
|
-
callId: string;
|
|
644
|
-
toolType: ToolType; // "flow" | "node" | "mcp" | "client" | "builtin" | "agent"
|
|
645
|
-
status: "progress" | "complete" | "error";
|
|
646
|
-
inputs?: unknown;
|
|
647
|
-
output?: unknown;
|
|
648
|
-
error?: string;
|
|
649
|
-
serverName?: string; // For MCP tools
|
|
650
|
-
};
|
|
651
|
-
|
|
652
|
-
type ReasoningItem = {
|
|
653
|
-
itemType: "reasoning";
|
|
654
|
-
reasoning: string;
|
|
655
|
-
index?: number;
|
|
656
|
-
};
|
|
657
|
-
|
|
658
|
-
type HandoffItem = {
|
|
659
|
-
itemType: "handoff";
|
|
660
|
-
agentName: string;
|
|
661
|
-
};
|
|
662
|
-
```
|
|
654
|
+
See the [Message Parts](#message-parts) section above for the full type
|
|
655
|
+
definitions of each part.
|
|
663
656
|
|
|
664
657
|
## React API Reference
|
|
665
658
|
|
|
@@ -667,7 +660,7 @@ type HandoffItem = {
|
|
|
667
660
|
|
|
668
661
|
| Hook | Description |
|
|
669
662
|
| ------------------------------------------ | ------------------------------------------------ |
|
|
670
|
-
| `useAgent(agentId, agentUrl, accessKey?)` | Main hook — messages, streaming, sessions
|
|
663
|
+
| `useAgent(agentId, agentUrl, accessKey?)` | Main hook — messages, streaming, sessions |
|
|
671
664
|
| `useAgentContext(agentId, agentUrl, key?)` | Context-based alternative for multi-agent setups |
|
|
672
665
|
| `useClientTool(agentId, config)` | Register a client tool (headless or widget) |
|
|
673
666
|
|
|
@@ -675,7 +668,7 @@ type HandoffItem = {
|
|
|
675
668
|
|
|
676
669
|
| Component | Description |
|
|
677
670
|
| ------------------------------------------- | -------------------------------------------------- |
|
|
678
|
-
| `<AgentContextProvider>` | Provides shared agent state (sessions
|
|
671
|
+
| `<AgentContextProvider>` | Provides shared agent state (sessions) |
|
|
679
672
|
| `<ToolRenderer agentId={id} part={part} />` | Renders a widget tool from a message part |
|
|
680
673
|
|
|
681
674
|
### Utilities
|
|
@@ -708,7 +701,7 @@ function App() {
|
|
|
708
701
|
}
|
|
709
702
|
|
|
710
703
|
function Chat() {
|
|
711
|
-
const { messages, handleSend, inProgress, resumeTool, abort
|
|
704
|
+
const { messages, handleSend, inProgress, resumeTool, abort } =
|
|
712
705
|
useAgent(AGENT_ID, AGENT_URL);
|
|
713
706
|
const [input, setInput] = useState("");
|
|
714
707
|
|
|
@@ -748,13 +741,46 @@ function Chat() {
|
|
|
748
741
|
{messages.map((msg, i) => (
|
|
749
742
|
<div key={i}>
|
|
750
743
|
<strong>{msg.role}:</strong>
|
|
751
|
-
{msg.parts?.map((part) =>
|
|
752
|
-
part.type === "text"
|
|
753
|
-
<span key={
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
744
|
+
{msg.parts?.map((part, j) => {
|
|
745
|
+
if (part.type === "text") {
|
|
746
|
+
return <span key={j}>{part.text}</span>;
|
|
747
|
+
}
|
|
748
|
+
if (part.type === "widget") {
|
|
749
|
+
return <ToolRenderer key={j} agentId={AGENT_ID} part={part} />;
|
|
750
|
+
}
|
|
751
|
+
if (part.type === "tool_call") {
|
|
752
|
+
return (
|
|
753
|
+
<div key={j} style={{ opacity: 0.7, fontSize: "0.85em" }}>
|
|
754
|
+
🔧 {part.toolName}{" "}
|
|
755
|
+
{part.status === "progress"
|
|
756
|
+
? "running..."
|
|
757
|
+
: part.status === "error"
|
|
758
|
+
? `failed: ${part.error}`
|
|
759
|
+
: "✓"}
|
|
760
|
+
</div>
|
|
761
|
+
);
|
|
762
|
+
}
|
|
763
|
+
if (part.type === "reasoning") {
|
|
764
|
+
return (
|
|
765
|
+
<div key={j} style={{ fontStyle: "italic", opacity: 0.6 }}>
|
|
766
|
+
💭 {part.reasoning}
|
|
767
|
+
</div>
|
|
768
|
+
);
|
|
769
|
+
}
|
|
770
|
+
if (part.type === "handoff") {
|
|
771
|
+
return (
|
|
772
|
+
<div key={j}>→ Handed off to {part.agentName}</div>
|
|
773
|
+
);
|
|
774
|
+
}
|
|
775
|
+
if (part.type === "run_error") {
|
|
776
|
+
return (
|
|
777
|
+
<div key={j} style={{ color: "red" }}>
|
|
778
|
+
⚠️ {part.message}
|
|
779
|
+
</div>
|
|
780
|
+
);
|
|
781
|
+
}
|
|
782
|
+
return null;
|
|
783
|
+
}) ?? msg.content}
|
|
758
784
|
</div>
|
|
759
785
|
))}
|
|
760
786
|
|
package/dist/react/index.cjs
CHANGED
|
@@ -20,7 +20,6 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/react/index.ts
|
|
21
21
|
var react_exports = {};
|
|
22
22
|
__export(react_exports, {
|
|
23
|
-
AGENT_DEBUG_DATA_KEY: () => AGENT_DEBUG_DATA_KEY,
|
|
24
23
|
AGENT_SESSIONS_KEY: () => AGENT_SESSIONS_KEY,
|
|
25
24
|
AgentContextProvider: () => AgentContextProvider,
|
|
26
25
|
AgentToolContext: () => AgentToolContext,
|
|
@@ -45,7 +44,6 @@ var import_react3 = require("react");
|
|
|
45
44
|
|
|
46
45
|
// src/react/constants.ts
|
|
47
46
|
var AGENT_SESSIONS_KEY = "buildship:agent:conversations";
|
|
48
|
-
var AGENT_DEBUG_DATA_KEY = "buildship:agent:debug";
|
|
49
47
|
var DEFAULT_SESSION_NAME = "New Chat";
|
|
50
48
|
var TEMPORARY_SESSION_ID = "sess_temp";
|
|
51
49
|
|
|
@@ -151,122 +149,6 @@ var useSessionUtils = (agentId, allSessions, setAllSessions, currentSessionId, s
|
|
|
151
149
|
};
|
|
152
150
|
};
|
|
153
151
|
|
|
154
|
-
// src/react/debug-handlers.ts
|
|
155
|
-
var createDebugHandlers = (setDebugData) => {
|
|
156
|
-
const handleStreamEvent = (event) => {
|
|
157
|
-
const executionId = event.meta.executionId;
|
|
158
|
-
switch (event.type) {
|
|
159
|
-
case "tool_call_start": {
|
|
160
|
-
const { callId, toolName, toolType, inputs, serverName } = event.data;
|
|
161
|
-
setDebugData((prev) => ({
|
|
162
|
-
...prev,
|
|
163
|
-
[executionId]: [
|
|
164
|
-
...prev[executionId] || [],
|
|
165
|
-
{
|
|
166
|
-
itemType: "tool_call",
|
|
167
|
-
toolName,
|
|
168
|
-
callId,
|
|
169
|
-
toolType,
|
|
170
|
-
status: "progress",
|
|
171
|
-
inputs,
|
|
172
|
-
serverName
|
|
173
|
-
}
|
|
174
|
-
]
|
|
175
|
-
}));
|
|
176
|
-
break;
|
|
177
|
-
}
|
|
178
|
-
case "tool_call_end": {
|
|
179
|
-
const { callId, result, error } = event.data;
|
|
180
|
-
setDebugData((prev) => {
|
|
181
|
-
const currentData = [...prev[executionId] || []];
|
|
182
|
-
for (let i = currentData.length - 1; i >= 0; i--) {
|
|
183
|
-
if (currentData[i].itemType === "tool_call") {
|
|
184
|
-
const toolItem = currentData[i];
|
|
185
|
-
if (toolItem.callId === callId) {
|
|
186
|
-
currentData[i] = {
|
|
187
|
-
...toolItem,
|
|
188
|
-
status: error ? "error" : "complete",
|
|
189
|
-
output: result,
|
|
190
|
-
error
|
|
191
|
-
};
|
|
192
|
-
break;
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
return {
|
|
197
|
-
...prev,
|
|
198
|
-
[executionId]: currentData
|
|
199
|
-
};
|
|
200
|
-
});
|
|
201
|
-
break;
|
|
202
|
-
}
|
|
203
|
-
case "reasoning_delta": {
|
|
204
|
-
const { delta, index } = event.data;
|
|
205
|
-
setDebugData((prev) => {
|
|
206
|
-
const currentData = [...prev[executionId] || []];
|
|
207
|
-
let existingItemIndex = -1;
|
|
208
|
-
for (let i = currentData.length - 1; i >= 0; i--) {
|
|
209
|
-
const item = currentData[i];
|
|
210
|
-
if (item.itemType === "reasoning" && item.index === index) {
|
|
211
|
-
existingItemIndex = i;
|
|
212
|
-
break;
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
if (existingItemIndex === -1) {
|
|
216
|
-
currentData.push({ itemType: "reasoning", reasoning: delta, index });
|
|
217
|
-
} else {
|
|
218
|
-
const hasInterleavedItems = currentData.slice(existingItemIndex + 1).some((item) => item.itemType !== "reasoning");
|
|
219
|
-
if (hasInterleavedItems) {
|
|
220
|
-
currentData.push({ itemType: "reasoning", reasoning: delta, index });
|
|
221
|
-
} else {
|
|
222
|
-
currentData[existingItemIndex] = {
|
|
223
|
-
itemType: "reasoning",
|
|
224
|
-
reasoning: currentData[existingItemIndex].reasoning + delta,
|
|
225
|
-
index
|
|
226
|
-
};
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
return {
|
|
230
|
-
...prev,
|
|
231
|
-
[executionId]: currentData
|
|
232
|
-
};
|
|
233
|
-
});
|
|
234
|
-
break;
|
|
235
|
-
}
|
|
236
|
-
case "agent_handoff": {
|
|
237
|
-
setDebugData((prev) => ({
|
|
238
|
-
...prev,
|
|
239
|
-
[executionId]: [
|
|
240
|
-
...prev[executionId] || [],
|
|
241
|
-
{
|
|
242
|
-
itemType: "handoff",
|
|
243
|
-
agentName: event.data.agentName
|
|
244
|
-
}
|
|
245
|
-
]
|
|
246
|
-
}));
|
|
247
|
-
break;
|
|
248
|
-
}
|
|
249
|
-
case "run_error": {
|
|
250
|
-
setDebugData((prev) => ({
|
|
251
|
-
...prev,
|
|
252
|
-
[executionId]: [
|
|
253
|
-
...prev[executionId] || [],
|
|
254
|
-
{
|
|
255
|
-
itemType: "run_error",
|
|
256
|
-
message: event.data.message,
|
|
257
|
-
code: event.data.code
|
|
258
|
-
}
|
|
259
|
-
]
|
|
260
|
-
}));
|
|
261
|
-
break;
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
};
|
|
265
|
-
return {
|
|
266
|
-
handleStreamEvent
|
|
267
|
-
};
|
|
268
|
-
};
|
|
269
|
-
|
|
270
152
|
// src/react/client-tools.ts
|
|
271
153
|
var import_react2 = require("react");
|
|
272
154
|
var import_zod = require("zod");
|
|
@@ -371,7 +253,7 @@ function updateAgentMessageParts(parts, newPart) {
|
|
|
371
253
|
}
|
|
372
254
|
|
|
373
255
|
// src/react/stream-callbacks.ts
|
|
374
|
-
function buildStreamCallbacks(deps
|
|
256
|
+
function buildStreamCallbacks(deps) {
|
|
375
257
|
const {
|
|
376
258
|
setMessages,
|
|
377
259
|
setInProgress,
|
|
@@ -386,16 +268,10 @@ function buildStreamCallbacks(deps, debugKey) {
|
|
|
386
268
|
onComplete: () => {
|
|
387
269
|
console.log("Agent closed");
|
|
388
270
|
setInProgress(false);
|
|
389
|
-
if (syncSessionRef.current) {
|
|
390
|
-
syncSessionRef.current(messagesRef.current);
|
|
391
|
-
}
|
|
392
271
|
},
|
|
393
272
|
onError: (error) => {
|
|
394
273
|
console.log("Agent error", error);
|
|
395
274
|
setInProgress(false);
|
|
396
|
-
if (syncSessionRef.current) {
|
|
397
|
-
syncSessionRef.current(messagesRef.current);
|
|
398
|
-
}
|
|
399
275
|
},
|
|
400
276
|
onEvent: (event) => {
|
|
401
277
|
if (event.type === "text_delta") {
|
|
@@ -409,33 +285,36 @@ function buildStreamCallbacks(deps, debugKey) {
|
|
|
409
285
|
);
|
|
410
286
|
} else if (event.type === "tool_call_start" && event.data.toolType === "client") {
|
|
411
287
|
handleClientToolCall(event, setMessages, syncSessionRef, toolContext, agentId);
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
callId: event.data.callId,
|
|
423
|
-
toolName: event.data.toolName,
|
|
424
|
-
toolType: event.data.toolType
|
|
425
|
-
},
|
|
426
|
-
meta: debugMeta
|
|
427
|
-
});
|
|
428
|
-
}
|
|
429
|
-
}
|
|
430
|
-
} else if (debugKey) {
|
|
431
|
-
deps.debugHandlers.handleStreamEvent({
|
|
432
|
-
...event,
|
|
433
|
-
meta: { ...event.meta, executionId: debugKey }
|
|
434
|
-
});
|
|
288
|
+
} else if (event.type === "tool_call_start") {
|
|
289
|
+
handleToolCallStart(event, setMessages, syncSessionRef);
|
|
290
|
+
} else if (event.type === "tool_call_end") {
|
|
291
|
+
handleToolCallEnd(event, setMessages, syncSessionRef);
|
|
292
|
+
} else if (event.type === "reasoning_delta") {
|
|
293
|
+
handleReasoningDelta(event, setMessages, syncSessionRef);
|
|
294
|
+
} else if (event.type === "agent_handoff") {
|
|
295
|
+
handleAgentHandoff(event, setMessages, syncSessionRef);
|
|
296
|
+
} else if (event.type === "run_error") {
|
|
297
|
+
handleRunError(event, setMessages, syncSessionRef);
|
|
435
298
|
}
|
|
436
299
|
}
|
|
437
300
|
};
|
|
438
301
|
}
|
|
302
|
+
function ensureAgentMessage(prev, executionId) {
|
|
303
|
+
const last = prev[prev.length - 1];
|
|
304
|
+
if (last?.role === "agent") {
|
|
305
|
+
return [prev, last];
|
|
306
|
+
}
|
|
307
|
+
const newMsg = {
|
|
308
|
+
role: "agent",
|
|
309
|
+
content: "",
|
|
310
|
+
parts: [],
|
|
311
|
+
executionId
|
|
312
|
+
};
|
|
313
|
+
return [[...prev, newMsg], newMsg];
|
|
314
|
+
}
|
|
315
|
+
function replaceLastAgent(prev, updated) {
|
|
316
|
+
return [...prev.slice(0, -1), updated];
|
|
317
|
+
}
|
|
439
318
|
function handleTextDelta(event, setMessages, syncSessionRef, modifier, fullTextModifier, agentId) {
|
|
440
319
|
const sequence = event.meta.sequence;
|
|
441
320
|
const originalText = event.data;
|
|
@@ -556,11 +435,126 @@ function handleClientToolCall(event, setMessages, syncSessionRef, toolContext, a
|
|
|
556
435
|
return updatedMessages;
|
|
557
436
|
});
|
|
558
437
|
}
|
|
438
|
+
function handleToolCallStart(event, setMessages, syncSessionRef) {
|
|
439
|
+
const { callId, toolName, toolType, inputs, serverName } = event.data;
|
|
440
|
+
setMessages((prev) => {
|
|
441
|
+
const [msgs, agentMsg] = ensureAgentMessage(prev, event.meta.executionId);
|
|
442
|
+
const newPart = {
|
|
443
|
+
type: "tool_call",
|
|
444
|
+
toolName,
|
|
445
|
+
callId,
|
|
446
|
+
toolType,
|
|
447
|
+
status: "progress",
|
|
448
|
+
inputs,
|
|
449
|
+
serverName,
|
|
450
|
+
sequence: event.meta.sequence
|
|
451
|
+
};
|
|
452
|
+
const updated = {
|
|
453
|
+
...agentMsg,
|
|
454
|
+
parts: [...agentMsg.parts || [], newPart]
|
|
455
|
+
};
|
|
456
|
+
const updatedMessages = replaceLastAgent(msgs, updated);
|
|
457
|
+
if (syncSessionRef.current) syncSessionRef.current(updatedMessages);
|
|
458
|
+
return updatedMessages;
|
|
459
|
+
});
|
|
460
|
+
}
|
|
461
|
+
function handleToolCallEnd(event, setMessages, syncSessionRef) {
|
|
462
|
+
const { callId, result, error } = event.data;
|
|
463
|
+
setMessages((prev) => {
|
|
464
|
+
const last = prev[prev.length - 1];
|
|
465
|
+
if (last?.role !== "agent" || !last.parts) return prev;
|
|
466
|
+
const updatedParts = [...last.parts];
|
|
467
|
+
for (let i = updatedParts.length - 1; i >= 0; i--) {
|
|
468
|
+
const part = updatedParts[i];
|
|
469
|
+
if (part.type === "tool_call" && part.callId === callId) {
|
|
470
|
+
updatedParts[i] = {
|
|
471
|
+
...part,
|
|
472
|
+
status: error ? "error" : "complete",
|
|
473
|
+
output: result,
|
|
474
|
+
error
|
|
475
|
+
};
|
|
476
|
+
break;
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
const updated = { ...last, parts: updatedParts };
|
|
480
|
+
const updatedMessages = replaceLastAgent(prev, updated);
|
|
481
|
+
if (syncSessionRef.current) syncSessionRef.current(updatedMessages);
|
|
482
|
+
return updatedMessages;
|
|
483
|
+
});
|
|
484
|
+
}
|
|
485
|
+
function handleReasoningDelta(event, setMessages, syncSessionRef) {
|
|
486
|
+
const { delta, index } = event.data;
|
|
487
|
+
setMessages((prev) => {
|
|
488
|
+
const [msgs, agentMsg] = ensureAgentMessage(prev, event.meta.executionId);
|
|
489
|
+
const parts = [...agentMsg.parts || []];
|
|
490
|
+
let existingIdx = -1;
|
|
491
|
+
for (let i = parts.length - 1; i >= 0; i--) {
|
|
492
|
+
const p = parts[i];
|
|
493
|
+
if (p.type === "reasoning" && p.index === index) {
|
|
494
|
+
existingIdx = i;
|
|
495
|
+
break;
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
if (existingIdx === -1) {
|
|
499
|
+
parts.push({ type: "reasoning", reasoning: delta, index, sequence: event.meta.sequence });
|
|
500
|
+
} else {
|
|
501
|
+
const hasInterleavedItems = parts.slice(existingIdx + 1).some((p) => p.type !== "reasoning");
|
|
502
|
+
if (hasInterleavedItems) {
|
|
503
|
+
parts.push({ type: "reasoning", reasoning: delta, index, sequence: event.meta.sequence });
|
|
504
|
+
} else {
|
|
505
|
+
const existing = parts[existingIdx];
|
|
506
|
+
parts[existingIdx] = {
|
|
507
|
+
...existing,
|
|
508
|
+
reasoning: existing.reasoning + delta
|
|
509
|
+
};
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
const updated = { ...agentMsg, parts };
|
|
513
|
+
const updatedMessages = replaceLastAgent(msgs, updated);
|
|
514
|
+
if (syncSessionRef.current) syncSessionRef.current(updatedMessages);
|
|
515
|
+
return updatedMessages;
|
|
516
|
+
});
|
|
517
|
+
}
|
|
518
|
+
function handleAgentHandoff(event, setMessages, syncSessionRef) {
|
|
519
|
+
setMessages((prev) => {
|
|
520
|
+
const [msgs, agentMsg] = ensureAgentMessage(prev, event.meta.executionId);
|
|
521
|
+
const newPart = {
|
|
522
|
+
type: "handoff",
|
|
523
|
+
agentName: event.data.agentName,
|
|
524
|
+
sequence: event.meta.sequence
|
|
525
|
+
};
|
|
526
|
+
const updated = {
|
|
527
|
+
...agentMsg,
|
|
528
|
+
parts: [...agentMsg.parts || [], newPart]
|
|
529
|
+
};
|
|
530
|
+
const updatedMessages = replaceLastAgent(msgs, updated);
|
|
531
|
+
if (syncSessionRef.current) syncSessionRef.current(updatedMessages);
|
|
532
|
+
return updatedMessages;
|
|
533
|
+
});
|
|
534
|
+
}
|
|
535
|
+
function handleRunError(event, setMessages, syncSessionRef) {
|
|
536
|
+
setMessages((prev) => {
|
|
537
|
+
const [msgs, agentMsg] = ensureAgentMessage(prev, event.meta.executionId);
|
|
538
|
+
const newPart = {
|
|
539
|
+
type: "run_error",
|
|
540
|
+
message: event.data.message,
|
|
541
|
+
code: event.data.code,
|
|
542
|
+
sequence: event.meta.sequence
|
|
543
|
+
};
|
|
544
|
+
const updated = {
|
|
545
|
+
...agentMsg,
|
|
546
|
+
parts: [...agentMsg.parts || [], newPart]
|
|
547
|
+
};
|
|
548
|
+
const updatedMessages = replaceLastAgent(msgs, updated);
|
|
549
|
+
if (syncSessionRef.current) syncSessionRef.current(updatedMessages);
|
|
550
|
+
return updatedMessages;
|
|
551
|
+
});
|
|
552
|
+
}
|
|
559
553
|
|
|
560
554
|
// src/react/use-agent.ts
|
|
561
555
|
function useAgent(agent, options) {
|
|
562
556
|
const agentId = agent._agentId;
|
|
563
|
-
const { allSessions, setAllSessions
|
|
557
|
+
const { allSessions, setAllSessions } = useAgentGlobalState();
|
|
564
558
|
const toolContext = (0, import_react3.useContext)(AgentToolContext);
|
|
565
559
|
const [inProgress, setInProgress] = (0, import_react3.useState)(false);
|
|
566
560
|
const [messages, setMessages] = (0, import_react3.useState)([]);
|
|
@@ -578,7 +572,6 @@ function useAgent(agent, options) {
|
|
|
578
572
|
const initialSessionId = sessionUtils.getInitialSessionId();
|
|
579
573
|
setCurrentSessionId(initialSessionId);
|
|
580
574
|
}, [agentId]);
|
|
581
|
-
const debugHandlers = (0, import_react3.useMemo)(() => createDebugHandlers(setDebugData), [setDebugData]);
|
|
582
575
|
(0, import_react3.useEffect)(() => {
|
|
583
576
|
messagesRef.current = messages;
|
|
584
577
|
}, [messages]);
|
|
@@ -611,7 +604,6 @@ function useAgent(agent, options) {
|
|
|
611
604
|
async (input, runOptions) => {
|
|
612
605
|
const isNewSession = !currentSessionId || currentSessionId === TEMPORARY_SESSION_ID;
|
|
613
606
|
setInProgress(true);
|
|
614
|
-
const debugKey = runOptions?.optimisticExecutionId || messagesRef.current.findLast((m) => m.role === "user")?.executionId;
|
|
615
607
|
const deps = {
|
|
616
608
|
agentId,
|
|
617
609
|
currentSessionId,
|
|
@@ -619,12 +611,11 @@ function useAgent(agent, options) {
|
|
|
619
611
|
setMessages,
|
|
620
612
|
setInProgress,
|
|
621
613
|
syncSessionRef: sessionUtils.syncSessionRef,
|
|
622
|
-
debugHandlers,
|
|
623
614
|
toolContext,
|
|
624
615
|
textDeltaModifier: optionsRef.current?.textDeltaModifier,
|
|
625
616
|
fullTextModifier: optionsRef.current?.fullTextModifier
|
|
626
617
|
};
|
|
627
|
-
const callbacks = buildStreamCallbacks(deps
|
|
618
|
+
const callbacks = buildStreamCallbacks(deps);
|
|
628
619
|
const executeOptions = {
|
|
629
620
|
context: runOptions?.context,
|
|
630
621
|
headers: runOptions?.additionalHeaders,
|
|
@@ -686,7 +677,7 @@ function useAgent(agent, options) {
|
|
|
686
677
|
activeSessionRef.current = null;
|
|
687
678
|
}
|
|
688
679
|
},
|
|
689
|
-
[currentSessionId, sessionUtils,
|
|
680
|
+
[currentSessionId, sessionUtils, agentId, toolContext, agent, getClientToolsMap]
|
|
690
681
|
);
|
|
691
682
|
const handleSend = (0, import_react3.useCallback)(
|
|
692
683
|
async (input, options2) => {
|
|
@@ -785,14 +776,6 @@ function useAgent(agent, options) {
|
|
|
785
776
|
return updatedMessages;
|
|
786
777
|
});
|
|
787
778
|
const lastUserMessage = messagesRef.current.findLast((m) => m.role === "user");
|
|
788
|
-
const debugKey = lastUserMessage?.executionId;
|
|
789
|
-
if (debugKey) {
|
|
790
|
-
debugHandlers.handleStreamEvent({
|
|
791
|
-
type: "tool_call_end",
|
|
792
|
-
data: { callId, toolName: "", toolType: "client", result },
|
|
793
|
-
meta: { executionId: debugKey, sequence: 0 }
|
|
794
|
-
});
|
|
795
|
-
}
|
|
796
779
|
await runAgent(void 0, {
|
|
797
780
|
resumeToolCallId: callId,
|
|
798
781
|
resumeToolResult: result,
|
|
@@ -801,7 +784,7 @@ function useAgent(agent, options) {
|
|
|
801
784
|
context: lastUserMessage?.context ?? lastRunOptionsRef.current.context
|
|
802
785
|
});
|
|
803
786
|
},
|
|
804
|
-
[runAgent, sessionUtils.syncSessionRef
|
|
787
|
+
[runAgent, sessionUtils.syncSessionRef]
|
|
805
788
|
);
|
|
806
789
|
const addOptimisticMessage = (0, import_react3.useCallback)(
|
|
807
790
|
(input) => {
|
|
@@ -857,8 +840,7 @@ function useAgent(agent, options) {
|
|
|
857
840
|
sessionId: currentSessionId,
|
|
858
841
|
switchSession: sessionUtils.switchSession,
|
|
859
842
|
deleteSession: sessionUtils.deleteSession,
|
|
860
|
-
sessions: sessionUtils.sessionsList
|
|
861
|
-
debugData
|
|
843
|
+
sessions: sessionUtils.sessionsList
|
|
862
844
|
};
|
|
863
845
|
}
|
|
864
846
|
|
|
@@ -1466,10 +1448,6 @@ function AgentContextProvider({ children }) {
|
|
|
1466
1448
|
const toolRegistryRef = (0, import_react5.useRef)(/* @__PURE__ */ new Map());
|
|
1467
1449
|
const [, forceUpdate] = (0, import_react5.useState)({});
|
|
1468
1450
|
const [allSessions, setAllSessions] = useSyncedLocalStorage(AGENT_SESSIONS_KEY, {});
|
|
1469
|
-
const [debugData, setDebugData] = useSyncedLocalStorage(
|
|
1470
|
-
AGENT_DEBUG_DATA_KEY,
|
|
1471
|
-
{}
|
|
1472
|
-
);
|
|
1473
1451
|
const initializeAgent = (0, import_react5.useCallback)(
|
|
1474
1452
|
(agentId, agentUrl, accessKey, options) => {
|
|
1475
1453
|
const existing = activeAgentsRef.current.get(agentId);
|
|
@@ -1526,8 +1504,6 @@ function AgentContextProvider({ children }) {
|
|
|
1526
1504
|
getRunner,
|
|
1527
1505
|
allSessions,
|
|
1528
1506
|
setAllSessions,
|
|
1529
|
-
debugData,
|
|
1530
|
-
setDebugData,
|
|
1531
1507
|
runnersRef,
|
|
1532
1508
|
listenersRef
|
|
1533
1509
|
}),
|
|
@@ -1536,9 +1512,7 @@ function AgentContextProvider({ children }) {
|
|
|
1536
1512
|
registerRunner,
|
|
1537
1513
|
getRunner,
|
|
1538
1514
|
allSessions,
|
|
1539
|
-
setAllSessions
|
|
1540
|
-
debugData,
|
|
1541
|
-
setDebugData
|
|
1515
|
+
setAllSessions
|
|
1542
1516
|
]
|
|
1543
1517
|
);
|
|
1544
1518
|
const toolContextValue = (0, import_react5.useMemo)(
|
|
@@ -1623,7 +1597,6 @@ function useAgentContext(agentId, agentUrl, accessKey, options) {
|
|
|
1623
1597
|
inProgress: false,
|
|
1624
1598
|
sessionId: "",
|
|
1625
1599
|
sessions: [],
|
|
1626
|
-
debugData: {},
|
|
1627
1600
|
handleSend: async () => {
|
|
1628
1601
|
},
|
|
1629
1602
|
resumeTool: async () => {
|
|
@@ -1648,9 +1621,7 @@ function useAgentGlobalState() {
|
|
|
1648
1621
|
}
|
|
1649
1622
|
return {
|
|
1650
1623
|
allSessions: context.allSessions,
|
|
1651
|
-
setAllSessions: context.setAllSessions
|
|
1652
|
-
debugData: context.debugData,
|
|
1653
|
-
setDebugData: context.setDebugData
|
|
1624
|
+
setAllSessions: context.setAllSessions
|
|
1654
1625
|
};
|
|
1655
1626
|
}
|
|
1656
1627
|
|
|
@@ -1699,7 +1670,6 @@ function ToolRenderer({ agentId, part }) {
|
|
|
1699
1670
|
}
|
|
1700
1671
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1701
1672
|
0 && (module.exports = {
|
|
1702
|
-
AGENT_DEBUG_DATA_KEY,
|
|
1703
1673
|
AGENT_SESSIONS_KEY,
|
|
1704
1674
|
AgentContextProvider,
|
|
1705
1675
|
AgentToolContext,
|