bs-agent 0.0.27 → 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 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
- - 🐛 **Debug data** — structured debug entries for every tool call, reasoning
14
- step & handoff
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
- sessions, and debug data.
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",
@@ -416,9 +415,9 @@ raw delta → textDeltaModifier(delta) → accumulated text → fullTextModifier
416
415
  `textDeltaModifier` acts as a per-chunk preprocessor; `fullTextModifier` acts as
417
416
  a post-accumulation formatter on top of the already-modified text.
418
417
 
419
- > **Note:** `_rawText` stores the `textDeltaModifier`-processed accumulation,
420
- > not the original unmodified stream. If `textDeltaModifier` strips content,
421
- > `fullTextModifier` will never see it.
418
+ > **Note:** If `textDeltaModifier` strips or transforms content,
419
+ > `fullTextModifier` will only see the already-modified accumulation the
420
+ > original unmodified stream text is not preserved.
422
421
 
423
422
  ## `useAgentContext` Hook
424
423
 
@@ -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 + widgets)
568
- executionId?: string; // Links to debug data
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 both text and widgets interleaved in the correct order.
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 Data
635
+ ## Inline Debug Info
622
636
 
623
- Debug data captures structured information about every tool call, reasoning
624
- step, and agent handoff during execution. It's stored by `executionId` (matching
625
- the user message it belongs to).
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 { debugData, messages } = useAgent(...);
629
-
630
- // Get debug data for a specific message
631
- const messageDebug = debugData[message.executionId];
632
-
633
- // Each entry is one of:
634
- type DebugDataType = Array<ToolExecutionItem | ReasoningItem | HandoffItem>;
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
- ### Debug Entry Types
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, debug |
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, debug data) |
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, debugData } =
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={part.firstSequence}>{part.text}</span>
754
- ) : (
755
- <ToolRenderer key={part.callId} agentId={AGENT_ID} part={part} />
756
- ),
757
- ) ?? msg.content}
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