@townco/ui 0.1.109 → 0.1.111

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.
@@ -0,0 +1,226 @@
1
+ import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
+ import JsonView from "@uiw/react-json-view";
3
+ import { AlertCircle, CheckSquare, ChevronDown, ChevronRight, CircleDot, Cloud, Edit, FileText, Globe, Image, Link, Search, Wrench, } from "lucide-react";
4
+ import React, { useState } from "react";
5
+ import { ChatLayout } from "./index.js";
6
+ import { SubAgentDetails } from "./SubAgentDetails.js";
7
+ import { useTheme } from "./ThemeProvider.js";
8
+ /**
9
+ * Map of icon names to Lucide components
10
+ */
11
+ const ICON_MAP = {
12
+ Globe: Globe,
13
+ Image: Image,
14
+ Link: Link,
15
+ Cloud: Cloud,
16
+ CheckSquare: CheckSquare,
17
+ Search: Search,
18
+ FileText: FileText,
19
+ Edit: Edit,
20
+ Wrench: Wrench,
21
+ CircleDot: CircleDot,
22
+ };
23
+ /**
24
+ * Tool call kind icons (using emoji for simplicity)
25
+ */
26
+ const _kindIcons = {
27
+ read: "\u{1F4C4}",
28
+ edit: "\u{270F}\u{FE0F}",
29
+ delete: "\u{1F5D1}\u{FE0F}",
30
+ move: "\u{1F4E6}",
31
+ search: "\u{1F50D}",
32
+ execute: "\u{2699}\u{FE0F}",
33
+ think: "\u{1F4AD}",
34
+ fetch: "\u{1F310}",
35
+ switch_mode: "\u{1F501}",
36
+ other: "\u{1F527}",
37
+ };
38
+ /**
39
+ * ToolCall component - displays a single tool call with collapsible details
40
+ */
41
+ export function ToolCall({ toolCall }) {
42
+ const [isExpanded, setIsExpanded] = useState(false);
43
+ const [isSubagentExpanded, setIsSubagentExpanded] = useState(false);
44
+ const { resolvedTheme } = useTheme();
45
+ // Detect TodoWrite tool and subagent
46
+ const isTodoWrite = toolCall.title === "todo_write";
47
+ const isSubagentCall = !!(toolCall.subagentPort && toolCall.subagentSessionId);
48
+ // Safely access ChatLayout context - will be undefined if not within ChatLayout
49
+ const layoutContext = React.useContext(ChatLayout.Context);
50
+ // Click handler: toggle sidepanel for TodoWrite, subagent details for subagents, expand for others
51
+ const handleHeaderClick = React.useCallback(() => {
52
+ if (isTodoWrite && layoutContext) {
53
+ // Toggle sidepanel - close if already open on todo tab, otherwise open
54
+ if (layoutContext.panelSize !== "hidden" &&
55
+ layoutContext.activeTab === "todo") {
56
+ layoutContext.setPanelSize("hidden");
57
+ }
58
+ else {
59
+ layoutContext.setPanelSize("small");
60
+ layoutContext.setActiveTab("todo");
61
+ }
62
+ }
63
+ else if (isSubagentCall) {
64
+ // Toggle subagent details
65
+ setIsSubagentExpanded(!isSubagentExpanded);
66
+ }
67
+ else {
68
+ // Normal expand/collapse
69
+ setIsExpanded(!isExpanded);
70
+ }
71
+ }, [
72
+ isTodoWrite,
73
+ layoutContext,
74
+ isExpanded,
75
+ isSubagentCall,
76
+ isSubagentExpanded,
77
+ ]);
78
+ // Determine which icon to show
79
+ const IconComponent = toolCall.icon && ICON_MAP[toolCall.icon]
80
+ ? ICON_MAP[toolCall.icon]
81
+ : CircleDot;
82
+ // Determine display name
83
+ const displayName = toolCall.prettyName || toolCall.title;
84
+ // Determine icon color based on status (especially for subagents)
85
+ const isSubagentRunning = isSubagentCall &&
86
+ (toolCall.status === "in_progress" || toolCall.status === "pending");
87
+ const isSubagentFailed = isSubagentCall && toolCall.status === "failed";
88
+ const iconColorClass = isSubagentCall
89
+ ? isSubagentFailed
90
+ ? "text-destructive"
91
+ : isSubagentRunning
92
+ ? "text-foreground animate-pulse"
93
+ : "text-green-500"
94
+ : "text-muted-foreground";
95
+ const statusTooltip = isSubagentCall
96
+ ? isSubagentFailed
97
+ ? "Sub-agent failed"
98
+ : isSubagentRunning
99
+ ? "Sub-agent running"
100
+ : "Sub-agent completed"
101
+ : undefined;
102
+ // Check if there's an error
103
+ const hasError = toolCall.status === "failed" || !!toolCall.error;
104
+ // Check if this is a preliminary (pending) tool call without full details yet
105
+ const isPreliminary = toolCall.status === "pending" &&
106
+ (!toolCall.rawInput || Object.keys(toolCall.rawInput).length === 0);
107
+ // JSON View style based on theme
108
+ const jsonStyle = {
109
+ fontSize: "11px",
110
+ backgroundColor: "transparent",
111
+ fontFamily: "inherit",
112
+ "--w-rjv-color": resolvedTheme === "dark" ? "#fafafa" : "#09090b",
113
+ "--w-rjv-key-string": resolvedTheme === "dark" ? "#fafafa" : "#09090b",
114
+ "--w-rjv-background-color": "transparent",
115
+ "--w-rjv-line-color": resolvedTheme === "dark" ? "#27272a" : "#e4e4e7",
116
+ "--w-rjv-arrow-color": resolvedTheme === "dark" ? "#a1a1aa" : "#71717a",
117
+ "--w-rjv-edit-color": resolvedTheme === "dark" ? "#fafafa" : "#09090b",
118
+ "--w-rjv-info-color": resolvedTheme === "dark" ? "#a1a1aa" : "#71717a",
119
+ "--w-rjv-update-color": resolvedTheme === "dark" ? "#fafafa" : "#09090b",
120
+ "--w-rjv-copied-color": resolvedTheme === "dark" ? "#fafafa" : "#09090b",
121
+ "--w-rjv-copied-success-color": resolvedTheme === "dark" ? "#22c55e" : "#16a34a",
122
+ "--w-rjv-curlybraces-color": resolvedTheme === "dark" ? "#a1a1aa" : "#71717a",
123
+ "--w-rjv-colon-color": resolvedTheme === "dark" ? "#a1a1aa" : "#71717a",
124
+ "--w-rjv-brackets-color": resolvedTheme === "dark" ? "#a1a1aa" : "#71717a",
125
+ "--w-rjv-quotes-color": resolvedTheme === "dark" ? "#a1a1aa" : "#71717a",
126
+ "--w-rjv-quotes-string-color": resolvedTheme === "dark" ? "#a1a1aa" : "#71717a",
127
+ "--w-rjv-type-string-color": resolvedTheme === "dark" ? "#22c55e" : "#16a34a",
128
+ "--w-rjv-type-int-color": resolvedTheme === "dark" ? "#f59e0b" : "#d97706",
129
+ "--w-rjv-type-float-color": resolvedTheme === "dark" ? "#f59e0b" : "#d97706",
130
+ "--w-rjv-type-bigint-color": resolvedTheme === "dark" ? "#f59e0b" : "#d97706",
131
+ "--w-rjv-type-boolean-color": resolvedTheme === "dark" ? "#3b82f6" : "#2563eb",
132
+ "--w-rjv-type-date-color": resolvedTheme === "dark" ? "#ec4899" : "#db2777",
133
+ "--w-rjv-type-url-color": resolvedTheme === "dark" ? "#3b82f6" : "#2563eb",
134
+ "--w-rjv-type-null-color": resolvedTheme === "dark" ? "#ef4444" : "#dc2626",
135
+ "--w-rjv-type-nan-color": resolvedTheme === "dark" ? "#ef4444" : "#dc2626",
136
+ "--w-rjv-type-undefined-color": resolvedTheme === "dark" ? "#ef4444" : "#dc2626",
137
+ };
138
+ // Preliminary tool calls show as simple light gray text without expansion
139
+ if (isPreliminary) {
140
+ return (_jsx("div", { className: "flex flex-col my-4", children: _jsxs("span", { className: "text-paragraph-sm text-muted-foreground/50", children: ["Invoking ", displayName] }) }));
141
+ }
142
+ return (_jsxs("div", { className: "flex flex-col my-4", children: [_jsxs("button", { type: "button", className: "flex flex-col items-start gap-0.5 cursor-pointer bg-transparent border-none p-0 text-left group w-fit", onClick: handleHeaderClick, "aria-expanded": isTodoWrite ? undefined : isExpanded, children: [_jsxs("div", { className: "flex items-center gap-1.5 text-[11px] font-medium text-muted-foreground", children: [_jsx("div", { className: iconColorClass, title: statusTooltip, children: _jsx(IconComponent, { className: "h-3 w-3" }) }), _jsx("span", { className: "text-paragraph-sm text-muted-foreground", children: displayName }), hasError && _jsx(AlertCircle, { className: "h-3 w-3 text-destructive" }), isTodoWrite ? (_jsx(ChevronRight, { className: "h-3 w-3 text-muted-foreground/70" })) : (_jsx(ChevronDown, { className: `h-3 w-3 text-muted-foreground/70 transition-transform duration-200 ${isExpanded ? "rotate-180" : ""}` }))] }), toolCall.subline && (_jsx("span", { className: "text-paragraph-sm text-muted-foreground/70 pl-4.5", children: toolCall.subline }))] }), !isTodoWrite && isSubagentCall && (_jsx("div", { className: "pl-4.5", children: _jsx(SubAgentDetails, { port: toolCall.subagentPort, sessionId: toolCall.subagentSessionId, parentStatus: toolCall.status, agentName: toolCall.rawInput?.agentName, query: toolCall.rawInput?.query, isExpanded: isSubagentExpanded, onExpandChange: setIsSubagentExpanded }) })), !isTodoWrite && !isSubagentCall && isExpanded && (_jsxs("div", { className: "mt-2 text-sm border border-border rounded-lg bg-card overflow-hidden w-full", children: [toolCall.rawInput &&
143
+ Object.keys(toolCall.rawInput).length > 0 &&
144
+ !toolCall.subagentPort && (_jsxs("div", { className: "p-3 border-b border-border", children: [_jsx("div", { className: "text-[10px] font-bold text-muted-foreground uppercase tracking-wider mb-1.5 font-sans", children: "Input" }), _jsx("div", { className: "text-[11px] font-mono text-foreground", children: _jsx(JsonView, { value: toolCall.rawInput, collapsed: false, displayDataTypes: false, displayObjectSize: false, enableClipboard: true, style: jsonStyle }) })] })), toolCall.locations && toolCall.locations.length > 0 && (_jsxs("div", { className: "p-3 border-b border-border", children: [_jsx("div", { className: "text-[10px] font-bold text-muted-foreground uppercase tracking-wider mb-1.5 font-sans", children: "Files" }), _jsx("ul", { className: "space-y-1", children: toolCall.locations.map((loc) => (_jsxs("li", { className: "font-mono text-[11px] text-foreground bg-muted px-1.5 py-0.5 rounded w-fit", children: [loc.path, loc.line !== null &&
145
+ loc.line !== undefined &&
146
+ `:${loc.line}`] }, `${loc.path}:${loc.line ?? ""}`))) })] })), (toolCall.content && toolCall.content.length > 0) ||
147
+ toolCall.error ? (_jsxs("div", { className: "p-3 border-b border-border last:border-0", children: [_jsx("div", { className: "text-[10px] font-bold text-muted-foreground uppercase tracking-wider mb-1.5 font-sans", children: "Output" }), _jsxs("div", { className: "space-y-2 text-[11px] text-foreground", children: [toolCall.content?.map((block, idx) => {
148
+ // Generate a stable key based on content
149
+ const getBlockKey = () => {
150
+ if (block.type === "diff" && "path" in block) {
151
+ return `diff-${block.path}-${idx}`;
152
+ }
153
+ if (block.type === "terminal" && "terminalId" in block) {
154
+ return `terminal-${block.terminalId}`;
155
+ }
156
+ if (block.type === "text" && "text" in block) {
157
+ return `text-${block.text.substring(0, 20)}-${idx}`;
158
+ }
159
+ if (block.type === "content" && "content" in block) {
160
+ const innerContent = block.content;
161
+ return `content-${innerContent.text?.substring(0, 20)}-${idx}`;
162
+ }
163
+ return `block-${idx}`;
164
+ };
165
+ // Helper to render text content (with JSON parsing if applicable)
166
+ const renderTextContent = (text, key) => {
167
+ // Try to parse as JSON
168
+ try {
169
+ const parsed = JSON.parse(text);
170
+ // If it's an object or array, render with JsonView
171
+ if (typeof parsed === "object" && parsed !== null) {
172
+ return (_jsx("div", { className: "text-[11px]", children: _jsx(JsonView, { value: parsed, collapsed: false, displayDataTypes: false, displayObjectSize: false, enableClipboard: true, style: jsonStyle }) }, key));
173
+ }
174
+ }
175
+ catch {
176
+ // Not valid JSON, render as plain text
177
+ }
178
+ // Render as plain text
179
+ return (_jsx("pre", { className: "whitespace-pre-wrap font-mono text-[11px] text-foreground overflow-x-auto", children: text }, key));
180
+ };
181
+ // Handle nested content blocks (ACP format)
182
+ if (block.type === "content" && "content" in block) {
183
+ const innerContent = block.content;
184
+ if (innerContent.type === "text" && innerContent.text) {
185
+ return renderTextContent(innerContent.text, getBlockKey());
186
+ }
187
+ }
188
+ // Handle direct text blocks
189
+ if (block.type === "text" && "text" in block) {
190
+ return renderTextContent(block.text, getBlockKey());
191
+ }
192
+ // Handle image blocks
193
+ if (block.type === "image") {
194
+ const alt = block.alt || "Generated image";
195
+ let imageSrc;
196
+ if ("data" in block) {
197
+ // Base64 encoded image
198
+ const mimeType = block.mimeType || "image/png";
199
+ imageSrc = `data:${mimeType};base64,${block.data}`;
200
+ }
201
+ else if ("url" in block) {
202
+ // URL or file path
203
+ imageSrc = block.url;
204
+ }
205
+ else {
206
+ return null;
207
+ }
208
+ return (_jsx("div", { className: "my-2", children: _jsx("img", { src: imageSrc, alt: alt, className: "max-w-full h-auto rounded-md border border-border" }) }, getBlockKey()));
209
+ }
210
+ // Handle diff blocks
211
+ if (block.type === "diff" &&
212
+ "path" in block &&
213
+ "oldText" in block &&
214
+ "newText" in block) {
215
+ return (_jsxs("div", { className: "border border-border rounded bg-card", children: [_jsxs("div", { className: "bg-muted px-2 py-1 text-[10px] font-mono text-muted-foreground border-b border-border", children: [block.path, "line" in block &&
216
+ block.line !== null &&
217
+ block.line !== undefined &&
218
+ `:${block.line}`] }), _jsxs("div", { className: "p-2 font-mono text-[11px]", children: [_jsxs("div", { className: "text-red-500 dark:text-red-400", children: ["- ", block.oldText] }), _jsxs("div", { className: "text-green-500 dark:text-green-400", children: ["+ ", block.newText] })] })] }, getBlockKey()));
219
+ }
220
+ // Handle terminal blocks
221
+ if (block.type === "terminal" && "terminalId" in block) {
222
+ return (_jsxs("div", { className: "bg-neutral-900 text-neutral-100 p-2 rounded text-[11px] font-mono", children: ["Terminal: ", block.terminalId] }, getBlockKey()));
223
+ }
224
+ return null;
225
+ }), toolCall.error && (_jsxs("div", { className: "text-destructive font-mono text-[11px] mt-2", children: ["Error: ", toolCall.error] }))] })] })) : null, toolCall._meta?.truncationWarning && (_jsxs("div", { className: "mx-3 mt-3 mb-0 flex items-center gap-2 rounded-md bg-yellow-50 dark:bg-yellow-950/20 px-3 py-2 text-[11px] text-yellow-800 dark:text-yellow-200 border border-yellow-200 dark:border-yellow-900", children: [_jsx("span", { className: "text-yellow-600 dark:text-yellow-500", children: "\u26A0\uFE0F" }), _jsx("span", { children: toolCall._meta.truncationWarning })] })), (toolCall.tokenUsage || toolCall.startedAt) && (_jsxs("div", { className: "p-2 bg-muted/50 border-t border-border flex flex-wrap gap-4 text-[10px] text-muted-foreground font-sans", children: [toolCall.tokenUsage && (_jsxs("div", { className: "flex gap-3", children: [toolCall.tokenUsage.inputTokens !== undefined && (_jsxs("div", { children: [_jsx("span", { className: "uppercase tracking-wide font-semibold mr-1", children: "Input:" }), toolCall.tokenUsage.inputTokens.toLocaleString()] })), toolCall.tokenUsage.outputTokens !== undefined && (_jsxs("div", { children: [_jsx("span", { className: "uppercase tracking-wide font-semibold mr-1", children: "Output:" }), toolCall.tokenUsage.outputTokens.toLocaleString()] })), toolCall.tokenUsage.totalTokens !== undefined && (_jsxs("div", { children: [_jsx("span", { className: "uppercase tracking-wide font-semibold mr-1", children: "Total:" }), toolCall.tokenUsage.totalTokens.toLocaleString()] }))] })), toolCall.startedAt && (_jsxs("div", { className: "flex gap-3 ml-auto", children: [_jsxs("span", { children: ["Started: ", new Date(toolCall.startedAt).toLocaleTimeString()] }), toolCall.completedAt && (_jsxs("span", { children: ["Completed:", " ", new Date(toolCall.completedAt).toLocaleTimeString(), " (", Math.round((toolCall.completedAt - toolCall.startedAt) / 1000), "s)"] }))] }))] }))] }))] }));
226
+ }
@@ -0,0 +1,8 @@
1
+ import type { ToolCall as ToolCallType } from "../../core/schemas/tool-call.js";
2
+ export interface ToolCallGroupProps {
3
+ toolCalls: ToolCallType[];
4
+ }
5
+ /**
6
+ * ToolCallGroup component - displays a group of parallel tool calls with collapsible details
7
+ */
8
+ export declare function ToolCallGroup({ toolCalls }: ToolCallGroupProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,29 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { ChevronDown, ListVideo } from "lucide-react";
3
+ import React, { useState } from "react";
4
+ import { ToolCall } from "./ToolCall.js";
5
+ /**
6
+ * ToolCallGroup component - displays a group of parallel tool calls with collapsible details
7
+ */
8
+ export function ToolCallGroup({ toolCalls }) {
9
+ const [isExpanded, setIsExpanded] = useState(false);
10
+ // Calculate group status based on individual tool call statuses
11
+ const getGroupStatus = () => {
12
+ const statuses = toolCalls.map((tc) => tc.status);
13
+ if (statuses.some((s) => s === "failed"))
14
+ return "failed";
15
+ if (statuses.some((s) => s === "in_progress"))
16
+ return "in_progress";
17
+ if (statuses.every((s) => s === "completed"))
18
+ return "completed";
19
+ return "pending";
20
+ };
21
+ const groupStatus = getGroupStatus();
22
+ // Generate summary of tool names
23
+ const toolNames = toolCalls.map((tc) => tc.prettyName || tc.title);
24
+ const uniqueNames = [...new Set(toolNames)];
25
+ const summary = uniqueNames.length <= 2
26
+ ? uniqueNames.join(", ")
27
+ : `${uniqueNames.slice(0, 2).join(", ")} +${uniqueNames.length - 2} more`;
28
+ return (_jsxs("div", { className: "flex flex-col my-4", children: [_jsxs("button", { type: "button", className: "flex flex-col items-start gap-0.5 cursor-pointer bg-transparent border-none p-0 text-left group w-fit", onClick: () => setIsExpanded(!isExpanded), "aria-expanded": isExpanded, children: [_jsxs("div", { className: "flex items-center gap-1.5 text-[11px] font-medium text-muted-foreground", children: [_jsx("div", { className: "text-muted-foreground", children: _jsx(ListVideo, { className: "h-3 w-3" }) }), _jsx("span", { className: "text-paragraph-sm text-muted-foreground", children: "Parallel operation" }), _jsx("span", { className: "text-[10px] bg-muted px-1.5 py-0.5 rounded text-muted-foreground/70", children: toolCalls.length }), _jsx(ChevronDown, { className: `h-3 w-3 text-muted-foreground/70 transition-transform duration-200 ${isExpanded ? "rotate-180" : ""}` })] }), !isExpanded && (_jsx("span", { className: "text-paragraph-sm text-muted-foreground/70 pl-4.5", children: summary }))] }), isExpanded && (_jsx("div", { className: "mt-1", children: toolCalls.map((toolCall) => (_jsxs("div", { className: "flex items-start", children: [_jsx("div", { className: "w-2.5 h-4 border-l-2 border-b-2 border-border rounded-bl-[6px] mt-1 mr-0.5 shrink-0" }), _jsx("div", { className: "flex-1 -mt-2", children: _jsx(ToolCall, { toolCall: toolCall }) })] }, toolCall.id))) }))] }));
29
+ }
@@ -637,6 +637,74 @@ export declare const SessionUpdate: z.ZodUnion<readonly [z.ZodObject<{
637
637
  rawOutput: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
638
638
  }, z.core.$strip>;
639
639
  messageId: z.ZodOptional<z.ZodString>;
640
+ }, z.core.$strip>, z.ZodObject<{
641
+ sessionId: z.ZodString;
642
+ status: z.ZodOptional<z.ZodEnum<{
643
+ active: "active";
644
+ connected: "connected";
645
+ connecting: "connecting";
646
+ disconnected: "disconnected";
647
+ error: "error";
648
+ idle: "idle";
649
+ streaming: "streaming";
650
+ }>>;
651
+ message: z.ZodOptional<z.ZodObject<{
652
+ id: z.ZodString;
653
+ role: z.ZodEnum<{
654
+ assistant: "assistant";
655
+ system: "system";
656
+ tool: "tool";
657
+ user: "user";
658
+ }>;
659
+ content: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
660
+ type: z.ZodLiteral<"text">;
661
+ text: z.ZodString;
662
+ }, z.core.$strip>, z.ZodObject<{
663
+ type: z.ZodLiteral<"image">;
664
+ url: z.ZodOptional<z.ZodString>;
665
+ source: z.ZodOptional<z.ZodObject<{
666
+ type: z.ZodLiteral<"base64">;
667
+ media_type: z.ZodEnum<{
668
+ "image/gif": "image/gif";
669
+ "image/jpeg": "image/jpeg";
670
+ "image/png": "image/png";
671
+ "image/webp": "image/webp";
672
+ }>;
673
+ data: z.ZodString;
674
+ }, z.core.$strip>>;
675
+ }, z.core.$strip>, z.ZodObject<{
676
+ type: z.ZodLiteral<"file">;
677
+ name: z.ZodString;
678
+ path: z.ZodOptional<z.ZodString>;
679
+ url: z.ZodOptional<z.ZodString>;
680
+ mimeType: z.ZodString;
681
+ size: z.ZodOptional<z.ZodNumber>;
682
+ }, z.core.$strip>, z.ZodObject<{
683
+ type: z.ZodLiteral<"tool_call">;
684
+ id: z.ZodString;
685
+ name: z.ZodString;
686
+ arguments: z.ZodRecord<z.ZodString, z.ZodUnknown>;
687
+ }, z.core.$strip>, z.ZodObject<{
688
+ type: z.ZodLiteral<"tool_result">;
689
+ callId: z.ZodString;
690
+ result: z.ZodUnknown;
691
+ error: z.ZodOptional<z.ZodString>;
692
+ }, z.core.$strip>], "type">>;
693
+ timestamp: z.ZodISODateTime;
694
+ metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
695
+ }, z.core.$strip>>;
696
+ error: z.ZodOptional<z.ZodString>;
697
+ _meta: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
698
+ type: z.ZodLiteral<"sources">;
699
+ sources: z.ZodArray<z.ZodObject<{
700
+ id: z.ZodString;
701
+ url: z.ZodString;
702
+ title: z.ZodString;
703
+ snippet: z.ZodOptional<z.ZodString>;
704
+ favicon: z.ZodOptional<z.ZodString>;
705
+ toolCallId: z.ZodString;
706
+ sourceName: z.ZodOptional<z.ZodString>;
707
+ }, z.core.$strip>>;
640
708
  }, z.core.$strip>, z.ZodObject<{
641
709
  sessionId: z.ZodString;
642
710
  status: z.ZodOptional<z.ZodEnum<{
@@ -1,6 +1,6 @@
1
1
  import { z } from "zod";
2
2
  import { ToolCallSchema, ToolCallUpdateSchema, } from "../../core/schemas/tool-call.js";
3
- import { Message } from "./message.js";
3
+ import { CitationSource, Message } from "./message.js";
4
4
  /**
5
5
  * Session status
6
6
  */
@@ -83,6 +83,14 @@ const ToolOutputSessionUpdate = BaseSessionUpdate.extend({
83
83
  }),
84
84
  messageId: z.string().optional(),
85
85
  });
86
+ /**
87
+ * Session update with sources (sessionUpdate: "sources")
88
+ * Sent during replay to restore persisted citation sources
89
+ */
90
+ const SourcesSessionUpdate = BaseSessionUpdate.extend({
91
+ type: z.literal("sources"),
92
+ sources: z.array(CitationSource),
93
+ });
86
94
  /**
87
95
  * Generic session update
88
96
  */
@@ -96,5 +104,6 @@ export const SessionUpdate = z.union([
96
104
  ToolCallSessionUpdate,
97
105
  ToolCallUpdateSessionUpdate,
98
106
  ToolOutputSessionUpdate,
107
+ SourcesSessionUpdate,
99
108
  GenericSessionUpdate,
100
109
  ]);
@@ -22,6 +22,7 @@ export declare class HttpTransport implements Transport {
22
22
  private options;
23
23
  private isReceivingMessages;
24
24
  private isInReplayMode;
25
+ private pendingReplayUpdates;
25
26
  private agentInfo?;
26
27
  constructor(options: HttpTransportOptions);
27
28
  connect(): Promise<void>;