@townco/ui 0.1.75 → 0.1.76
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/dist/core/hooks/use-chat-messages.d.ts +5 -4
- package/dist/core/hooks/use-chat-session.d.ts +1 -1
- package/dist/core/hooks/use-tool-calls.d.ts +3 -3
- package/dist/core/schemas/chat.d.ts +13 -10
- package/dist/core/schemas/chat.js +2 -0
- package/dist/core/schemas/tool-call.d.ts +8 -8
- package/dist/core/store/chat-store.js +2 -0
- package/dist/gui/components/Button.d.ts +1 -1
- package/dist/gui/components/HookNotification.js +11 -4
- package/dist/gui/components/InvokingGroup.d.ts +9 -0
- package/dist/gui/components/InvokingGroup.js +16 -0
- package/dist/gui/components/MessageContent.js +11 -3
- package/dist/gui/components/SubagentStream.d.ts +23 -0
- package/dist/gui/components/SubagentStream.js +98 -0
- package/dist/gui/components/ToolCall.d.ts +8 -0
- package/dist/gui/components/ToolCall.js +234 -0
- package/dist/gui/components/ToolCallGroup.d.ts +8 -0
- package/dist/gui/components/ToolCallGroup.js +29 -0
- package/dist/gui/components/ToolOperation.d.ts +4 -1
- package/dist/gui/components/ToolOperation.js +45 -8
- package/dist/sdk/schemas/message.d.ts +12 -0
- package/dist/sdk/schemas/message.js +3 -0
- package/dist/sdk/schemas/session.d.ts +24 -24
- package/package.json +3 -3
|
@@ -15,7 +15,7 @@ export declare function useChatMessages(client: AcpClient | null, startSession:
|
|
|
15
15
|
id: string;
|
|
16
16
|
title: string;
|
|
17
17
|
kind: "read" | "edit" | "delete" | "move" | "search" | "execute" | "think" | "fetch" | "switch_mode" | "other";
|
|
18
|
-
status: "
|
|
18
|
+
status: "completed" | "pending" | "in_progress" | "failed";
|
|
19
19
|
batchId?: string | undefined;
|
|
20
20
|
prettyName?: string | undefined;
|
|
21
21
|
icon?: string | undefined;
|
|
@@ -82,7 +82,7 @@ export declare function useChatMessages(client: AcpClient | null, startSession:
|
|
|
82
82
|
toolCalls?: {
|
|
83
83
|
id: string;
|
|
84
84
|
title: string;
|
|
85
|
-
status: "
|
|
85
|
+
status: "completed" | "pending" | "in_progress" | "failed";
|
|
86
86
|
prettyName?: string | undefined;
|
|
87
87
|
icon?: string | undefined;
|
|
88
88
|
content?: ({
|
|
@@ -122,7 +122,7 @@ export declare function useChatMessages(client: AcpClient | null, startSession:
|
|
|
122
122
|
toolCall: {
|
|
123
123
|
id: string;
|
|
124
124
|
title: string;
|
|
125
|
-
status: "
|
|
125
|
+
status: "completed" | "pending" | "in_progress" | "failed";
|
|
126
126
|
prettyName?: string | undefined;
|
|
127
127
|
icon?: string | undefined;
|
|
128
128
|
content?: ({
|
|
@@ -163,7 +163,7 @@ export declare function useChatMessages(client: AcpClient | null, startSession:
|
|
|
163
163
|
id: string;
|
|
164
164
|
hookType: "context_size" | "tool_response";
|
|
165
165
|
callback: string;
|
|
166
|
-
status: "error" | "
|
|
166
|
+
status: "error" | "triggered" | "completed";
|
|
167
167
|
threshold?: number | undefined;
|
|
168
168
|
currentPercentage?: number | undefined;
|
|
169
169
|
metadata?: {
|
|
@@ -181,6 +181,7 @@ export declare function useChatMessages(client: AcpClient | null, startSession:
|
|
|
181
181
|
triggeredAt?: number | undefined;
|
|
182
182
|
completedAt?: number | undefined;
|
|
183
183
|
contentPosition?: number | undefined;
|
|
184
|
+
toolCallId?: string | undefined;
|
|
184
185
|
}[] | undefined;
|
|
185
186
|
tokenUsage?: {
|
|
186
187
|
inputTokens?: number | undefined;
|
|
@@ -3,7 +3,7 @@ import type { AcpClient } from "../../sdk/client/index.js";
|
|
|
3
3
|
* Hook for managing chat session lifecycle
|
|
4
4
|
*/
|
|
5
5
|
export declare function useChatSession(client: AcpClient | null, initialSessionId?: string | null): {
|
|
6
|
-
connectionStatus: "error" | "
|
|
6
|
+
connectionStatus: "error" | "disconnected" | "connecting" | "connected";
|
|
7
7
|
sessionId: string | null;
|
|
8
8
|
connect: () => Promise<void>;
|
|
9
9
|
loadSession: (sessionIdToLoad: string) => Promise<void>;
|
|
@@ -13,7 +13,7 @@ export declare function useToolCalls(client: AcpClient | null): {
|
|
|
13
13
|
id: string;
|
|
14
14
|
title: string;
|
|
15
15
|
kind: "read" | "edit" | "delete" | "move" | "search" | "execute" | "think" | "fetch" | "switch_mode" | "other";
|
|
16
|
-
status: "
|
|
16
|
+
status: "completed" | "pending" | "in_progress" | "failed";
|
|
17
17
|
batchId?: string | undefined;
|
|
18
18
|
prettyName?: string | undefined;
|
|
19
19
|
icon?: string | undefined;
|
|
@@ -80,7 +80,7 @@ export declare function useToolCalls(client: AcpClient | null): {
|
|
|
80
80
|
toolCalls?: {
|
|
81
81
|
id: string;
|
|
82
82
|
title: string;
|
|
83
|
-
status: "
|
|
83
|
+
status: "completed" | "pending" | "in_progress" | "failed";
|
|
84
84
|
prettyName?: string | undefined;
|
|
85
85
|
icon?: string | undefined;
|
|
86
86
|
content?: ({
|
|
@@ -120,7 +120,7 @@ export declare function useToolCalls(client: AcpClient | null): {
|
|
|
120
120
|
toolCall: {
|
|
121
121
|
id: string;
|
|
122
122
|
title: string;
|
|
123
|
-
status: "
|
|
123
|
+
status: "completed" | "pending" | "in_progress" | "failed";
|
|
124
124
|
prettyName?: string | undefined;
|
|
125
125
|
icon?: string | undefined;
|
|
126
126
|
content?: ({
|
|
@@ -23,8 +23,8 @@ export declare const HookNotificationDisplay: z.ZodObject<{
|
|
|
23
23
|
callback: z.ZodString;
|
|
24
24
|
status: z.ZodEnum<{
|
|
25
25
|
error: "error";
|
|
26
|
-
completed: "completed";
|
|
27
26
|
triggered: "triggered";
|
|
27
|
+
completed: "completed";
|
|
28
28
|
}>;
|
|
29
29
|
threshold: z.ZodOptional<z.ZodNumber>;
|
|
30
30
|
currentPercentage: z.ZodOptional<z.ZodNumber>;
|
|
@@ -42,6 +42,7 @@ export declare const HookNotificationDisplay: z.ZodObject<{
|
|
|
42
42
|
triggeredAt: z.ZodOptional<z.ZodNumber>;
|
|
43
43
|
completedAt: z.ZodOptional<z.ZodNumber>;
|
|
44
44
|
contentPosition: z.ZodOptional<z.ZodNumber>;
|
|
45
|
+
toolCallId: z.ZodOptional<z.ZodString>;
|
|
45
46
|
}, z.core.$strip>;
|
|
46
47
|
export type HookNotificationDisplay = z.infer<typeof HookNotificationDisplay>;
|
|
47
48
|
export { HookType, HookNotification };
|
|
@@ -85,9 +86,9 @@ export declare const DisplayMessage: z.ZodObject<{
|
|
|
85
86
|
other: "other";
|
|
86
87
|
}>;
|
|
87
88
|
status: z.ZodEnum<{
|
|
89
|
+
completed: "completed";
|
|
88
90
|
pending: "pending";
|
|
89
91
|
in_progress: "in_progress";
|
|
90
|
-
completed: "completed";
|
|
91
92
|
failed: "failed";
|
|
92
93
|
}>;
|
|
93
94
|
contentPosition: z.ZodOptional<z.ZodNumber>;
|
|
@@ -153,9 +154,9 @@ export declare const DisplayMessage: z.ZodObject<{
|
|
|
153
154
|
prettyName: z.ZodOptional<z.ZodString>;
|
|
154
155
|
icon: z.ZodOptional<z.ZodString>;
|
|
155
156
|
status: z.ZodEnum<{
|
|
157
|
+
completed: "completed";
|
|
156
158
|
pending: "pending";
|
|
157
159
|
in_progress: "in_progress";
|
|
158
|
-
completed: "completed";
|
|
159
160
|
failed: "failed";
|
|
160
161
|
}>;
|
|
161
162
|
content: z.ZodOptional<z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
@@ -198,9 +199,9 @@ export declare const DisplayMessage: z.ZodObject<{
|
|
|
198
199
|
prettyName: z.ZodOptional<z.ZodString>;
|
|
199
200
|
icon: z.ZodOptional<z.ZodString>;
|
|
200
201
|
status: z.ZodEnum<{
|
|
202
|
+
completed: "completed";
|
|
201
203
|
pending: "pending";
|
|
202
204
|
in_progress: "in_progress";
|
|
203
|
-
completed: "completed";
|
|
204
205
|
failed: "failed";
|
|
205
206
|
}>;
|
|
206
207
|
content: z.ZodOptional<z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
@@ -246,8 +247,8 @@ export declare const DisplayMessage: z.ZodObject<{
|
|
|
246
247
|
callback: z.ZodString;
|
|
247
248
|
status: z.ZodEnum<{
|
|
248
249
|
error: "error";
|
|
249
|
-
completed: "completed";
|
|
250
250
|
triggered: "triggered";
|
|
251
|
+
completed: "completed";
|
|
251
252
|
}>;
|
|
252
253
|
threshold: z.ZodOptional<z.ZodNumber>;
|
|
253
254
|
currentPercentage: z.ZodOptional<z.ZodNumber>;
|
|
@@ -265,6 +266,7 @@ export declare const DisplayMessage: z.ZodObject<{
|
|
|
265
266
|
triggeredAt: z.ZodOptional<z.ZodNumber>;
|
|
266
267
|
completedAt: z.ZodOptional<z.ZodNumber>;
|
|
267
268
|
contentPosition: z.ZodOptional<z.ZodNumber>;
|
|
269
|
+
toolCallId: z.ZodOptional<z.ZodString>;
|
|
268
270
|
}, z.core.$strip>>>;
|
|
269
271
|
tokenUsage: z.ZodOptional<z.ZodObject<{
|
|
270
272
|
inputTokens: z.ZodOptional<z.ZodNumber>;
|
|
@@ -336,9 +338,9 @@ export declare const ChatSessionState: z.ZodObject<{
|
|
|
336
338
|
other: "other";
|
|
337
339
|
}>;
|
|
338
340
|
status: z.ZodEnum<{
|
|
341
|
+
completed: "completed";
|
|
339
342
|
pending: "pending";
|
|
340
343
|
in_progress: "in_progress";
|
|
341
|
-
completed: "completed";
|
|
342
344
|
failed: "failed";
|
|
343
345
|
}>;
|
|
344
346
|
contentPosition: z.ZodOptional<z.ZodNumber>;
|
|
@@ -404,9 +406,9 @@ export declare const ChatSessionState: z.ZodObject<{
|
|
|
404
406
|
prettyName: z.ZodOptional<z.ZodString>;
|
|
405
407
|
icon: z.ZodOptional<z.ZodString>;
|
|
406
408
|
status: z.ZodEnum<{
|
|
409
|
+
completed: "completed";
|
|
407
410
|
pending: "pending";
|
|
408
411
|
in_progress: "in_progress";
|
|
409
|
-
completed: "completed";
|
|
410
412
|
failed: "failed";
|
|
411
413
|
}>;
|
|
412
414
|
content: z.ZodOptional<z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
@@ -449,9 +451,9 @@ export declare const ChatSessionState: z.ZodObject<{
|
|
|
449
451
|
prettyName: z.ZodOptional<z.ZodString>;
|
|
450
452
|
icon: z.ZodOptional<z.ZodString>;
|
|
451
453
|
status: z.ZodEnum<{
|
|
454
|
+
completed: "completed";
|
|
452
455
|
pending: "pending";
|
|
453
456
|
in_progress: "in_progress";
|
|
454
|
-
completed: "completed";
|
|
455
457
|
failed: "failed";
|
|
456
458
|
}>;
|
|
457
459
|
content: z.ZodOptional<z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
@@ -497,8 +499,8 @@ export declare const ChatSessionState: z.ZodObject<{
|
|
|
497
499
|
callback: z.ZodString;
|
|
498
500
|
status: z.ZodEnum<{
|
|
499
501
|
error: "error";
|
|
500
|
-
completed: "completed";
|
|
501
502
|
triggered: "triggered";
|
|
503
|
+
completed: "completed";
|
|
502
504
|
}>;
|
|
503
505
|
threshold: z.ZodOptional<z.ZodNumber>;
|
|
504
506
|
currentPercentage: z.ZodOptional<z.ZodNumber>;
|
|
@@ -516,6 +518,7 @@ export declare const ChatSessionState: z.ZodObject<{
|
|
|
516
518
|
triggeredAt: z.ZodOptional<z.ZodNumber>;
|
|
517
519
|
completedAt: z.ZodOptional<z.ZodNumber>;
|
|
518
520
|
contentPosition: z.ZodOptional<z.ZodNumber>;
|
|
521
|
+
toolCallId: z.ZodOptional<z.ZodString>;
|
|
519
522
|
}, z.core.$strip>>>;
|
|
520
523
|
tokenUsage: z.ZodOptional<z.ZodObject<{
|
|
521
524
|
inputTokens: z.ZodOptional<z.ZodNumber>;
|
|
@@ -546,8 +549,8 @@ export type ChatSessionState = z.infer<typeof ChatSessionState>;
|
|
|
546
549
|
*/
|
|
547
550
|
export declare const ConnectionStatus: z.ZodEnum<{
|
|
548
551
|
error: "error";
|
|
552
|
+
disconnected: "disconnected";
|
|
549
553
|
connecting: "connecting";
|
|
550
554
|
connected: "connected";
|
|
551
|
-
disconnected: "disconnected";
|
|
552
555
|
}>;
|
|
553
556
|
export type ConnectionStatus = z.infer<typeof ConnectionStatus>;
|
|
@@ -45,6 +45,8 @@ export const HookNotificationDisplay = z.object({
|
|
|
45
45
|
completedAt: z.number().optional(),
|
|
46
46
|
// Position in content where the hook was triggered (for inline rendering)
|
|
47
47
|
contentPosition: z.number().optional(),
|
|
48
|
+
// For tool_response hooks - associates notification with a specific tool call
|
|
49
|
+
toolCallId: z.string().optional(),
|
|
48
50
|
});
|
|
49
51
|
export { HookType, HookNotification };
|
|
50
52
|
/**
|
|
@@ -13,16 +13,16 @@ export type ToolCallStatus = z.infer<typeof ToolCallStatusSchema>;
|
|
|
13
13
|
* Tool call categories for UI presentation
|
|
14
14
|
*/
|
|
15
15
|
export declare const ToolCallKindSchema: z.ZodEnum<{
|
|
16
|
+
search: "search";
|
|
17
|
+
execute: "execute";
|
|
18
|
+
move: "move";
|
|
19
|
+
other: "other";
|
|
16
20
|
read: "read";
|
|
17
21
|
edit: "edit";
|
|
18
22
|
delete: "delete";
|
|
19
|
-
move: "move";
|
|
20
|
-
search: "search";
|
|
21
|
-
execute: "execute";
|
|
22
23
|
think: "think";
|
|
23
24
|
fetch: "fetch";
|
|
24
25
|
switch_mode: "switch_mode";
|
|
25
|
-
other: "other";
|
|
26
26
|
}>;
|
|
27
27
|
export type ToolCallKind = z.infer<typeof ToolCallKindSchema>;
|
|
28
28
|
/**
|
|
@@ -280,16 +280,16 @@ export declare const ToolCallSchema: z.ZodObject<{
|
|
|
280
280
|
}, z.core.$strip>>;
|
|
281
281
|
subline: z.ZodOptional<z.ZodString>;
|
|
282
282
|
kind: z.ZodEnum<{
|
|
283
|
+
search: "search";
|
|
284
|
+
execute: "execute";
|
|
285
|
+
move: "move";
|
|
286
|
+
other: "other";
|
|
283
287
|
read: "read";
|
|
284
288
|
edit: "edit";
|
|
285
289
|
delete: "delete";
|
|
286
|
-
move: "move";
|
|
287
|
-
search: "search";
|
|
288
|
-
execute: "execute";
|
|
289
290
|
think: "think";
|
|
290
291
|
fetch: "fetch";
|
|
291
292
|
switch_mode: "switch_mode";
|
|
292
|
-
other: "other";
|
|
293
293
|
}>;
|
|
294
294
|
status: z.ZodEnum<{
|
|
295
295
|
pending: "pending";
|
|
@@ -12,6 +12,8 @@ function createHookNotificationDisplay(notification) {
|
|
|
12
12
|
id: `hook_${Date.now()}_${notification.hookType}_${notification.callback}`,
|
|
13
13
|
hookType: notification.hookType,
|
|
14
14
|
callback: notification.callback,
|
|
15
|
+
// Include toolCallId if present (for tool_response hooks)
|
|
16
|
+
...(notification.toolCallId ? { toolCallId: notification.toolCallId } : {}),
|
|
15
17
|
};
|
|
16
18
|
switch (notification.type) {
|
|
17
19
|
case "hook_triggered":
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type VariantProps } from "class-variance-authority";
|
|
2
2
|
import * as React from "react";
|
|
3
3
|
declare const buttonVariants: (props?: ({
|
|
4
|
-
variant?: "
|
|
4
|
+
variant?: "link" | "default" | "destructive" | "outline" | "secondary" | "ghost" | null | undefined;
|
|
5
5
|
size?: "default" | "icon" | "sm" | "lg" | null | undefined;
|
|
6
6
|
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
7
7
|
export interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement>, VariantProps<typeof buttonVariants> {
|
|
@@ -4,18 +4,25 @@ import React, { useEffect, useState } from "react";
|
|
|
4
4
|
/**
|
|
5
5
|
* Get display information for a hook type
|
|
6
6
|
*/
|
|
7
|
-
function getHookDisplayInfo(hookType, _callback, status) {
|
|
7
|
+
function getHookDisplayInfo(hookType, _callback, status, action) {
|
|
8
8
|
const isTriggered = status === "triggered";
|
|
9
|
+
const noActionNeeded = action === "no_action_needed";
|
|
9
10
|
if (hookType === "context_size") {
|
|
11
|
+
if (isTriggered) {
|
|
12
|
+
return { icon: Archive, title: "Compacting Context..." };
|
|
13
|
+
}
|
|
10
14
|
return {
|
|
11
15
|
icon: Archive,
|
|
12
|
-
title:
|
|
16
|
+
title: noActionNeeded ? "Context Check" : "Context Compacted",
|
|
13
17
|
};
|
|
14
18
|
}
|
|
15
19
|
if (hookType === "tool_response") {
|
|
20
|
+
if (isTriggered) {
|
|
21
|
+
return { icon: Scissors, title: "Compacting Response..." };
|
|
22
|
+
}
|
|
16
23
|
return {
|
|
17
24
|
icon: Scissors,
|
|
18
|
-
title:
|
|
25
|
+
title: noActionNeeded ? "Response Check" : "Tool Response Compacted",
|
|
19
26
|
};
|
|
20
27
|
}
|
|
21
28
|
// Fallback for unknown hook types
|
|
@@ -37,7 +44,7 @@ function formatNumber(num) {
|
|
|
37
44
|
export function HookNotification({ notification }) {
|
|
38
45
|
const [isExpanded, setIsExpanded] = useState(false);
|
|
39
46
|
const [elapsedTime, setElapsedTime] = useState(0);
|
|
40
|
-
const { icon: IconComponent, title } = getHookDisplayInfo(notification.hookType, notification.callback, notification.status);
|
|
47
|
+
const { icon: IconComponent, title } = getHookDisplayInfo(notification.hookType, notification.callback, notification.status, notification.metadata?.action);
|
|
41
48
|
const isTriggered = notification.status === "triggered";
|
|
42
49
|
const isCompleted = notification.status === "completed";
|
|
43
50
|
const isError = notification.status === "error";
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ToolCall as ToolCallType } from "../../core/schemas/tool-call.js";
|
|
2
|
+
export interface InvokingGroupProps {
|
|
3
|
+
toolCalls: ToolCallType[];
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* InvokingGroup component - displays a group of preliminary (invoking) tool calls
|
|
7
|
+
* Shows as "Invoking parallel operation (N)" with a summary of unique tool names
|
|
8
|
+
*/
|
|
9
|
+
export declare function InvokingGroup({ toolCalls }: InvokingGroupProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { ListVideo } from "lucide-react";
|
|
3
|
+
import React from "react";
|
|
4
|
+
/**
|
|
5
|
+
* InvokingGroup component - displays a group of preliminary (invoking) tool calls
|
|
6
|
+
* Shows as "Invoking parallel operation (N)" with a summary of unique tool names
|
|
7
|
+
*/
|
|
8
|
+
export function InvokingGroup({ toolCalls }) {
|
|
9
|
+
// Get unique display names for the summary
|
|
10
|
+
const displayNames = toolCalls.map((tc) => tc.prettyName || tc.title);
|
|
11
|
+
const uniqueNames = [...new Set(displayNames)];
|
|
12
|
+
const summary = uniqueNames.length <= 2
|
|
13
|
+
? uniqueNames.join(", ")
|
|
14
|
+
: `${uniqueNames.slice(0, 2).join(", ")} +${uniqueNames.length - 2} more`;
|
|
15
|
+
return (_jsxs("div", { className: "flex flex-col my-4", children: [_jsxs("div", { className: "flex items-center gap-1.5 text-paragraph-sm text-muted-foreground/50", children: [_jsx(ListVideo, { className: "h-3 w-3" }), _jsx("span", { children: "Invoking parallel operation" }), _jsx("span", { className: "text-[10px] bg-muted px-1.5 py-0.5 rounded text-muted-foreground/50", children: toolCalls.length })] }), _jsx("span", { className: "text-paragraph-sm text-muted-foreground/50 pl-4.5", children: summary })] }));
|
|
16
|
+
}
|
|
@@ -169,13 +169,17 @@ export const MessageContent = React.forwardRef(({ role: roleProp, variant, isStr
|
|
|
169
169
|
flushConsecutiveGroup();
|
|
170
170
|
return result;
|
|
171
171
|
};
|
|
172
|
+
// Get tool_response hook notifications to associate with tool calls
|
|
173
|
+
const toolResponseHooks = (message.hookNotifications || []).filter((n) => n.hookType === "tool_response");
|
|
172
174
|
// Helper to render a tool call or group
|
|
173
175
|
const renderToolCallOrGroup = (item, index) => {
|
|
174
176
|
// Batch group (parallel operations)
|
|
175
177
|
if (typeof item === "object" &&
|
|
176
178
|
"type" in item &&
|
|
177
179
|
item.type === "batch") {
|
|
178
|
-
|
|
180
|
+
// Get hook notifications for all tool calls in this batch
|
|
181
|
+
const batchHookNotifications = toolResponseHooks.filter((n) => item.toolCalls.some((tc) => tc.id === n.toolCallId));
|
|
182
|
+
return (_jsx(ToolOperation, { toolCalls: item.toolCalls, isGrouped: true, hookNotifications: batchHookNotifications }, `batch-${item.toolCalls[0]?.batchId || index}`));
|
|
179
183
|
}
|
|
180
184
|
// Selecting group (consecutive preliminary tool calls)
|
|
181
185
|
if (typeof item === "object" &&
|
|
@@ -184,10 +188,14 @@ export const MessageContent = React.forwardRef(({ role: roleProp, variant, isStr
|
|
|
184
188
|
return (_jsx(ToolOperation, { toolCalls: item.toolCalls, isGrouped: true }, `selecting-${item.toolCalls[0]?.id || index}`));
|
|
185
189
|
}
|
|
186
190
|
// Single tool call
|
|
187
|
-
|
|
191
|
+
const singleToolCall = item;
|
|
192
|
+
const singleHookNotifications = toolResponseHooks.filter((n) => n.toolCallId === singleToolCall.id);
|
|
193
|
+
return (_jsx(ToolOperation, { toolCalls: [singleToolCall], isGrouped: false, hookNotifications: singleHookNotifications }, singleToolCall.id));
|
|
188
194
|
};
|
|
189
|
-
// Get hook notifications
|
|
195
|
+
// Get hook notifications, filter out tool_response hooks (they're shown as sublines on tool calls)
|
|
196
|
+
// and sort by content position
|
|
190
197
|
const hookNotifications = (message.hookNotifications || [])
|
|
198
|
+
.filter((n) => n.hookType !== "tool_response")
|
|
191
199
|
.slice()
|
|
192
200
|
.sort((a, b) => (a.contentPosition ?? Infinity) -
|
|
193
201
|
(b.contentPosition ?? Infinity));
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export interface SubagentStreamProps {
|
|
2
|
+
/** Sub-agent HTTP port */
|
|
3
|
+
port: number;
|
|
4
|
+
/** Sub-agent session ID */
|
|
5
|
+
sessionId: string;
|
|
6
|
+
/** Optional host (defaults to localhost) */
|
|
7
|
+
host?: string;
|
|
8
|
+
/** Parent tool call status - use this to determine if sub-agent is running */
|
|
9
|
+
parentStatus?: "pending" | "in_progress" | "completed" | "failed";
|
|
10
|
+
/** Sub-agent name (for display) */
|
|
11
|
+
agentName?: string | undefined;
|
|
12
|
+
/** Query sent to the sub-agent */
|
|
13
|
+
query?: string | undefined;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* SubagentStream component - displays streaming content from a sub-agent.
|
|
17
|
+
*
|
|
18
|
+
* This component:
|
|
19
|
+
* - Connects directly to the sub-agent's SSE endpoint
|
|
20
|
+
* - Displays streaming text and tool calls
|
|
21
|
+
* - Renders in a collapsible section (collapsed by default)
|
|
22
|
+
*/
|
|
23
|
+
export declare function SubagentStream({ port, sessionId, host, parentStatus, agentName, query, }: SubagentStreamProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { ChevronDown, CircleDot, Loader2 } from "lucide-react";
|
|
3
|
+
import React, { useCallback, useEffect, useRef, useState } from "react";
|
|
4
|
+
import { useSubagentStream } from "../../core/hooks/use-subagent-stream.js";
|
|
5
|
+
const SCROLL_THRESHOLD = 50; // px from bottom to consider "at bottom"
|
|
6
|
+
/**
|
|
7
|
+
* SubagentStream component - displays streaming content from a sub-agent.
|
|
8
|
+
*
|
|
9
|
+
* This component:
|
|
10
|
+
* - Connects directly to the sub-agent's SSE endpoint
|
|
11
|
+
* - Displays streaming text and tool calls
|
|
12
|
+
* - Renders in a collapsible section (collapsed by default)
|
|
13
|
+
*/
|
|
14
|
+
export function SubagentStream({ port, sessionId, host, parentStatus, agentName, query, }) {
|
|
15
|
+
const [isExpanded, setIsExpanded] = useState(false); // Start collapsed for parallel ops
|
|
16
|
+
const [isThinkingExpanded, setIsThinkingExpanded] = useState(true);
|
|
17
|
+
const [isNearBottom, setIsNearBottom] = useState(true);
|
|
18
|
+
const thinkingContainerRef = useRef(null);
|
|
19
|
+
const { messages, isStreaming: hookIsStreaming, error } = useSubagentStream({
|
|
20
|
+
port,
|
|
21
|
+
sessionId,
|
|
22
|
+
...(host !== undefined ? { host } : {}),
|
|
23
|
+
});
|
|
24
|
+
// Use parent status as primary indicator, fall back to hook's streaming state
|
|
25
|
+
// Parent is "in_progress" means sub-agent is definitely still running
|
|
26
|
+
const isRunning = parentStatus === "in_progress" || parentStatus === "pending" || hookIsStreaming;
|
|
27
|
+
// Get the current/latest message
|
|
28
|
+
const currentMessage = messages[messages.length - 1];
|
|
29
|
+
const hasContent = currentMessage &&
|
|
30
|
+
(currentMessage.content ||
|
|
31
|
+
(currentMessage.toolCalls && currentMessage.toolCalls.length > 0));
|
|
32
|
+
// Auto-collapse Thinking when completed (so Output is the primary view)
|
|
33
|
+
const prevIsRunningRef = useRef(isRunning);
|
|
34
|
+
useEffect(() => {
|
|
35
|
+
if (prevIsRunningRef.current && !isRunning) {
|
|
36
|
+
// Just completed - collapse thinking to show output
|
|
37
|
+
setIsThinkingExpanded(false);
|
|
38
|
+
}
|
|
39
|
+
prevIsRunningRef.current = isRunning;
|
|
40
|
+
}, [isRunning]);
|
|
41
|
+
// Check if user is near bottom of scroll area
|
|
42
|
+
const checkScrollPosition = useCallback(() => {
|
|
43
|
+
const container = thinkingContainerRef.current;
|
|
44
|
+
if (!container)
|
|
45
|
+
return;
|
|
46
|
+
const { scrollTop, scrollHeight, clientHeight } = container;
|
|
47
|
+
const distanceFromBottom = scrollHeight - scrollTop - clientHeight;
|
|
48
|
+
setIsNearBottom(distanceFromBottom < SCROLL_THRESHOLD);
|
|
49
|
+
}, []);
|
|
50
|
+
// Scroll to bottom
|
|
51
|
+
const scrollToBottom = useCallback(() => {
|
|
52
|
+
const container = thinkingContainerRef.current;
|
|
53
|
+
if (!container)
|
|
54
|
+
return;
|
|
55
|
+
container.scrollTop = container.scrollHeight;
|
|
56
|
+
}, []);
|
|
57
|
+
// Auto-scroll when content changes and user is near bottom
|
|
58
|
+
useEffect(() => {
|
|
59
|
+
if (isNearBottom && (isRunning || hasContent)) {
|
|
60
|
+
scrollToBottom();
|
|
61
|
+
}
|
|
62
|
+
}, [currentMessage?.content, currentMessage?.toolCalls, isNearBottom, isRunning, hasContent, scrollToBottom]);
|
|
63
|
+
// Set up scroll listener
|
|
64
|
+
useEffect(() => {
|
|
65
|
+
const container = thinkingContainerRef.current;
|
|
66
|
+
if (!container)
|
|
67
|
+
return;
|
|
68
|
+
const handleScroll = () => checkScrollPosition();
|
|
69
|
+
container.addEventListener("scroll", handleScroll, { passive: true });
|
|
70
|
+
checkScrollPosition(); // Check initial position
|
|
71
|
+
return () => container.removeEventListener("scroll", handleScroll);
|
|
72
|
+
}, [checkScrollPosition, isThinkingExpanded, isExpanded]);
|
|
73
|
+
// Get last line of streaming content for preview
|
|
74
|
+
const lastLine = currentMessage?.content
|
|
75
|
+
? currentMessage.content.split("\n").filter(Boolean).pop() || ""
|
|
76
|
+
: "";
|
|
77
|
+
const previewText = lastLine.length > 100 ? `${lastLine.slice(0, 100)}...` : lastLine;
|
|
78
|
+
return (_jsxs("div", { children: [!isExpanded && (_jsx("button", { type: "button", onClick: () => setIsExpanded(true), className: "w-full max-w-md text-left cursor-pointer bg-transparent border-none p-0", children: previewText ? (_jsx("p", { className: `text-paragraph-sm text-muted-foreground truncate ${isRunning ? "animate-pulse" : ""}`, children: previewText })) : isRunning ? (_jsx("p", { className: "text-paragraph-sm text-muted-foreground/50 italic animate-pulse", children: "Waiting for response..." })) : null })), isExpanded && (_jsxs("div", { className: "space-y-3", children: [(agentName || query) && (_jsxs("div", { children: [_jsx("div", { className: "text-[10px] font-bold text-muted-foreground uppercase tracking-wider mb-1.5 font-sans", children: "Input" }), _jsxs("div", { className: "text-[11px] font-mono space-y-1", children: [agentName && (_jsxs("div", { children: [_jsx("span", { className: "text-muted-foreground", children: "agentName: " }), _jsx("span", { className: "text-foreground", children: agentName })] })), query && (_jsxs("div", { children: [_jsx("span", { className: "text-muted-foreground", children: "query: " }), _jsx("span", { className: "text-foreground", children: query })] }))] })] })), _jsxs("div", { children: [_jsxs("button", { type: "button", onClick: () => setIsThinkingExpanded(!isThinkingExpanded), className: "flex items-center gap-2 cursor-pointer bg-transparent border-none p-0 text-left group", children: [_jsx("div", { className: "text-[10px] font-bold text-muted-foreground uppercase tracking-wider font-sans", children: "Thinking" }), _jsx(ChevronDown, { className: `h-3 w-3 text-muted-foreground/70 transition-transform duration-200 ${isThinkingExpanded ? "rotate-180" : ""}` })] }), isThinkingExpanded && (_jsxs("div", { ref: thinkingContainerRef, className: "mt-2 rounded-md overflow-hidden bg-muted/30 border border-border/50 max-h-[200px] overflow-y-auto", children: [error && (_jsxs("div", { className: "px-2 py-2 text-[11px] text-destructive", children: ["Error: ", error] })), !error && !hasContent && isRunning && (_jsx("div", { className: "px-2 py-2 text-[11px] text-muted-foreground", children: "Waiting for sub-agent response..." })), currentMessage && (_jsxs("div", { className: "px-2 py-2 space-y-2", children: [currentMessage.toolCalls &&
|
|
79
|
+
currentMessage.toolCalls.length > 0 && (_jsx("div", { className: "space-y-1", children: currentMessage.toolCalls.map((tc) => (_jsx(SubagentToolCallItem, { toolCall: tc }, tc.id))) })), currentMessage.content && (_jsxs("div", { className: "text-[11px] text-foreground whitespace-pre-wrap font-mono", children: [currentMessage.content, currentMessage.isStreaming && (_jsx("span", { className: "inline-block w-1.5 h-3 bg-primary/70 ml-0.5 animate-pulse" }))] }))] }))] }))] }), !isRunning && currentMessage?.content && (_jsxs("div", { children: [_jsx("div", { className: "text-[10px] font-bold text-muted-foreground uppercase tracking-wider mb-1.5 font-sans", children: "Output" }), _jsx("div", { className: "text-[11px] text-foreground whitespace-pre-wrap font-mono max-h-[200px] overflow-y-auto rounded-md bg-muted/30 border border-border/50 px-2 py-2", children: currentMessage.content })] }))] }))] }));
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Simple tool call display for sub-agent tool calls
|
|
83
|
+
*/
|
|
84
|
+
function SubagentToolCallItem({ toolCall }) {
|
|
85
|
+
const statusIcon = {
|
|
86
|
+
pending: "...",
|
|
87
|
+
in_progress: "",
|
|
88
|
+
completed: "",
|
|
89
|
+
failed: "",
|
|
90
|
+
}[toolCall.status];
|
|
91
|
+
const statusColor = {
|
|
92
|
+
pending: "text-muted-foreground",
|
|
93
|
+
in_progress: "text-blue-500",
|
|
94
|
+
completed: "text-green-500",
|
|
95
|
+
failed: "text-destructive",
|
|
96
|
+
}[toolCall.status];
|
|
97
|
+
return (_jsxs("div", { className: "flex items-center gap-2 text-[10px] text-muted-foreground", children: [_jsx("span", { className: statusColor, children: statusIcon }), _jsx("span", { className: "font-medium", children: toolCall.prettyName || toolCall.title }), toolCall.status === "in_progress" && (_jsx(Loader2, { className: "h-2.5 w-2.5 animate-spin" }))] }));
|
|
98
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ToolCall as ToolCallType } from "../../core/schemas/tool-call.js";
|
|
2
|
+
export interface ToolCallProps {
|
|
3
|
+
toolCall: ToolCallType;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* ToolCall component - displays a single tool call with collapsible details
|
|
7
|
+
*/
|
|
8
|
+
export declare function ToolCall({ toolCall }: ToolCallProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,234 @@
|
|
|
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
|
+
// A subagent call can be detected by:
|
|
48
|
+
// - Live: has port and sessionId (but no stored messages yet)
|
|
49
|
+
// - Replay: has stored subagentMessages
|
|
50
|
+
const hasLiveSubagent = !!(toolCall.subagentPort && toolCall.subagentSessionId);
|
|
51
|
+
const hasStoredSubagent = !!(toolCall.subagentMessages && toolCall.subagentMessages.length > 0);
|
|
52
|
+
const isSubagentCall = hasLiveSubagent || hasStoredSubagent;
|
|
53
|
+
// Use replay mode if we have stored messages - they should take precedence
|
|
54
|
+
// over trying to connect to SSE (which won't work for replayed sessions)
|
|
55
|
+
const isReplaySubagent = hasStoredSubagent;
|
|
56
|
+
// Safely access ChatLayout context - will be undefined if not within ChatLayout
|
|
57
|
+
const layoutContext = React.useContext(ChatLayout.Context);
|
|
58
|
+
// Click handler: toggle sidepanel for TodoWrite, subagent details for subagents, expand for others
|
|
59
|
+
const handleHeaderClick = React.useCallback(() => {
|
|
60
|
+
if (isTodoWrite && layoutContext) {
|
|
61
|
+
// Toggle sidepanel - close if already open on todo tab, otherwise open
|
|
62
|
+
if (layoutContext.panelSize !== "hidden" &&
|
|
63
|
+
layoutContext.activeTab === "todo") {
|
|
64
|
+
layoutContext.setPanelSize("hidden");
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
layoutContext.setPanelSize("small");
|
|
68
|
+
layoutContext.setActiveTab("todo");
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
else if (isSubagentCall) {
|
|
72
|
+
// Toggle subagent details
|
|
73
|
+
setIsSubagentExpanded(!isSubagentExpanded);
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
// Normal expand/collapse
|
|
77
|
+
setIsExpanded(!isExpanded);
|
|
78
|
+
}
|
|
79
|
+
}, [
|
|
80
|
+
isTodoWrite,
|
|
81
|
+
layoutContext,
|
|
82
|
+
isExpanded,
|
|
83
|
+
isSubagentCall,
|
|
84
|
+
isSubagentExpanded,
|
|
85
|
+
]);
|
|
86
|
+
// Determine which icon to show
|
|
87
|
+
const IconComponent = toolCall.icon && ICON_MAP[toolCall.icon]
|
|
88
|
+
? ICON_MAP[toolCall.icon]
|
|
89
|
+
: CircleDot;
|
|
90
|
+
// Determine display name
|
|
91
|
+
const displayName = toolCall.prettyName || toolCall.title;
|
|
92
|
+
// Determine icon color based on status (especially for subagents)
|
|
93
|
+
const isSubagentRunning = isSubagentCall &&
|
|
94
|
+
(toolCall.status === "in_progress" || toolCall.status === "pending");
|
|
95
|
+
const isSubagentFailed = isSubagentCall && toolCall.status === "failed";
|
|
96
|
+
const iconColorClass = isSubagentCall
|
|
97
|
+
? isSubagentFailed
|
|
98
|
+
? "text-destructive"
|
|
99
|
+
: isSubagentRunning
|
|
100
|
+
? "text-foreground animate-pulse"
|
|
101
|
+
: "text-green-500"
|
|
102
|
+
: "text-muted-foreground";
|
|
103
|
+
const statusTooltip = isSubagentCall
|
|
104
|
+
? isSubagentFailed
|
|
105
|
+
? "Sub-agent failed"
|
|
106
|
+
: isSubagentRunning
|
|
107
|
+
? "Sub-agent running"
|
|
108
|
+
: "Sub-agent completed"
|
|
109
|
+
: undefined;
|
|
110
|
+
// Check if there's an error
|
|
111
|
+
const hasError = toolCall.status === "failed" || !!toolCall.error;
|
|
112
|
+
// Check if this is a preliminary (pending) tool call without full details yet
|
|
113
|
+
const isPreliminary = toolCall.status === "pending" &&
|
|
114
|
+
(!toolCall.rawInput || Object.keys(toolCall.rawInput).length === 0);
|
|
115
|
+
// JSON View style based on theme
|
|
116
|
+
const jsonStyle = {
|
|
117
|
+
fontSize: "11px",
|
|
118
|
+
backgroundColor: "transparent",
|
|
119
|
+
fontFamily: "inherit",
|
|
120
|
+
"--w-rjv-color": resolvedTheme === "dark" ? "#fafafa" : "#09090b",
|
|
121
|
+
"--w-rjv-key-string": resolvedTheme === "dark" ? "#fafafa" : "#09090b",
|
|
122
|
+
"--w-rjv-background-color": "transparent",
|
|
123
|
+
"--w-rjv-line-color": resolvedTheme === "dark" ? "#27272a" : "#e4e4e7",
|
|
124
|
+
"--w-rjv-arrow-color": resolvedTheme === "dark" ? "#a1a1aa" : "#71717a",
|
|
125
|
+
"--w-rjv-edit-color": resolvedTheme === "dark" ? "#fafafa" : "#09090b",
|
|
126
|
+
"--w-rjv-info-color": resolvedTheme === "dark" ? "#a1a1aa" : "#71717a",
|
|
127
|
+
"--w-rjv-update-color": resolvedTheme === "dark" ? "#fafafa" : "#09090b",
|
|
128
|
+
"--w-rjv-copied-color": resolvedTheme === "dark" ? "#fafafa" : "#09090b",
|
|
129
|
+
"--w-rjv-copied-success-color": resolvedTheme === "dark" ? "#22c55e" : "#16a34a",
|
|
130
|
+
"--w-rjv-curlybraces-color": resolvedTheme === "dark" ? "#a1a1aa" : "#71717a",
|
|
131
|
+
"--w-rjv-colon-color": resolvedTheme === "dark" ? "#a1a1aa" : "#71717a",
|
|
132
|
+
"--w-rjv-brackets-color": resolvedTheme === "dark" ? "#a1a1aa" : "#71717a",
|
|
133
|
+
"--w-rjv-quotes-color": resolvedTheme === "dark" ? "#a1a1aa" : "#71717a",
|
|
134
|
+
"--w-rjv-quotes-string-color": resolvedTheme === "dark" ? "#a1a1aa" : "#71717a",
|
|
135
|
+
"--w-rjv-type-string-color": resolvedTheme === "dark" ? "#22c55e" : "#16a34a",
|
|
136
|
+
"--w-rjv-type-int-color": resolvedTheme === "dark" ? "#f59e0b" : "#d97706",
|
|
137
|
+
"--w-rjv-type-float-color": resolvedTheme === "dark" ? "#f59e0b" : "#d97706",
|
|
138
|
+
"--w-rjv-type-bigint-color": resolvedTheme === "dark" ? "#f59e0b" : "#d97706",
|
|
139
|
+
"--w-rjv-type-boolean-color": resolvedTheme === "dark" ? "#3b82f6" : "#2563eb",
|
|
140
|
+
"--w-rjv-type-date-color": resolvedTheme === "dark" ? "#ec4899" : "#db2777",
|
|
141
|
+
"--w-rjv-type-url-color": resolvedTheme === "dark" ? "#3b82f6" : "#2563eb",
|
|
142
|
+
"--w-rjv-type-null-color": resolvedTheme === "dark" ? "#ef4444" : "#dc2626",
|
|
143
|
+
"--w-rjv-type-nan-color": resolvedTheme === "dark" ? "#ef4444" : "#dc2626",
|
|
144
|
+
"--w-rjv-type-undefined-color": resolvedTheme === "dark" ? "#ef4444" : "#dc2626",
|
|
145
|
+
};
|
|
146
|
+
// Preliminary tool calls show as simple light gray text without expansion
|
|
147
|
+
if (isPreliminary) {
|
|
148
|
+
return (_jsx("div", { className: "flex flex-col my-4", children: _jsxs("span", { className: "text-paragraph-sm text-muted-foreground/50", children: ["Invoking ", displayName] }) }));
|
|
149
|
+
}
|
|
150
|
+
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, storedMessages: toolCall.subagentMessages, isReplay: isReplaySubagent }) })), !isTodoWrite && !isSubagentCall && isExpanded && (_jsxs("div", { className: "mt-2 text-sm border border-border rounded-lg bg-card overflow-hidden w-full", children: [toolCall.rawInput &&
|
|
151
|
+
Object.keys(toolCall.rawInput).length > 0 &&
|
|
152
|
+
!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 &&
|
|
153
|
+
loc.line !== undefined &&
|
|
154
|
+
`:${loc.line}`] }, `${loc.path}:${loc.line ?? ""}`))) })] })), (toolCall.content && toolCall.content.length > 0) ||
|
|
155
|
+
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) => {
|
|
156
|
+
// Generate a stable key based on content
|
|
157
|
+
const getBlockKey = () => {
|
|
158
|
+
if (block.type === "diff" && "path" in block) {
|
|
159
|
+
return `diff-${block.path}-${idx}`;
|
|
160
|
+
}
|
|
161
|
+
if (block.type === "terminal" && "terminalId" in block) {
|
|
162
|
+
return `terminal-${block.terminalId}`;
|
|
163
|
+
}
|
|
164
|
+
if (block.type === "text" && "text" in block) {
|
|
165
|
+
return `text-${block.text.substring(0, 20)}-${idx}`;
|
|
166
|
+
}
|
|
167
|
+
if (block.type === "content" && "content" in block) {
|
|
168
|
+
const innerContent = block.content;
|
|
169
|
+
return `content-${innerContent.text?.substring(0, 20)}-${idx}`;
|
|
170
|
+
}
|
|
171
|
+
return `block-${idx}`;
|
|
172
|
+
};
|
|
173
|
+
// Helper to render text content (with JSON parsing if applicable)
|
|
174
|
+
const renderTextContent = (text, key) => {
|
|
175
|
+
// Try to parse as JSON
|
|
176
|
+
try {
|
|
177
|
+
const parsed = JSON.parse(text);
|
|
178
|
+
// If it's an object or array, render with JsonView
|
|
179
|
+
if (typeof parsed === "object" && parsed !== null) {
|
|
180
|
+
return (_jsx("div", { className: "text-[11px]", children: _jsx(JsonView, { value: parsed, collapsed: false, displayDataTypes: false, displayObjectSize: false, enableClipboard: true, style: jsonStyle }) }, key));
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
catch {
|
|
184
|
+
// Not valid JSON, render as plain text
|
|
185
|
+
}
|
|
186
|
+
// Render as plain text
|
|
187
|
+
return (_jsx("pre", { className: "whitespace-pre-wrap font-mono text-[11px] text-foreground overflow-x-auto", children: text }, key));
|
|
188
|
+
};
|
|
189
|
+
// Handle nested content blocks (ACP format)
|
|
190
|
+
if (block.type === "content" && "content" in block) {
|
|
191
|
+
const innerContent = block.content;
|
|
192
|
+
if (innerContent.type === "text" && innerContent.text) {
|
|
193
|
+
return renderTextContent(innerContent.text, getBlockKey());
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
// Handle direct text blocks
|
|
197
|
+
if (block.type === "text" && "text" in block) {
|
|
198
|
+
return renderTextContent(block.text, getBlockKey());
|
|
199
|
+
}
|
|
200
|
+
// Handle image blocks
|
|
201
|
+
if (block.type === "image") {
|
|
202
|
+
const alt = block.alt || "Generated image";
|
|
203
|
+
let imageSrc;
|
|
204
|
+
if ("data" in block) {
|
|
205
|
+
// Base64 encoded image
|
|
206
|
+
const mimeType = block.mimeType || "image/png";
|
|
207
|
+
imageSrc = `data:${mimeType};base64,${block.data}`;
|
|
208
|
+
}
|
|
209
|
+
else if ("url" in block) {
|
|
210
|
+
// URL or file path
|
|
211
|
+
imageSrc = block.url;
|
|
212
|
+
}
|
|
213
|
+
else {
|
|
214
|
+
return null;
|
|
215
|
+
}
|
|
216
|
+
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()));
|
|
217
|
+
}
|
|
218
|
+
// Handle diff blocks
|
|
219
|
+
if (block.type === "diff" &&
|
|
220
|
+
"path" in block &&
|
|
221
|
+
"oldText" in block &&
|
|
222
|
+
"newText" in block) {
|
|
223
|
+
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 &&
|
|
224
|
+
block.line !== null &&
|
|
225
|
+
block.line !== undefined &&
|
|
226
|
+
`:${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()));
|
|
227
|
+
}
|
|
228
|
+
// Handle terminal blocks
|
|
229
|
+
if (block.type === "terminal" && "terminalId" in block) {
|
|
230
|
+
return (_jsxs("div", { className: "bg-neutral-900 text-neutral-100 p-2 rounded text-[11px] font-mono", children: ["Terminal: ", block.terminalId] }, getBlockKey()));
|
|
231
|
+
}
|
|
232
|
+
return null;
|
|
233
|
+
}), 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)"] }))] }))] }))] }))] }));
|
|
234
|
+
}
|
|
@@ -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
|
+
}
|
|
@@ -1,11 +1,14 @@
|
|
|
1
|
+
import type { HookNotificationDisplay } from "../../core/schemas/chat.js";
|
|
1
2
|
import type { ToolCall as ToolCallType } from "../../core/schemas/tool-call.js";
|
|
2
3
|
export interface ToolOperationProps {
|
|
3
4
|
toolCalls: ToolCallType[];
|
|
4
5
|
isGrouped?: boolean;
|
|
5
6
|
autoMinimize?: boolean;
|
|
7
|
+
/** Hook notifications associated with these tool calls (for showing compaction status) */
|
|
8
|
+
hookNotifications?: HookNotificationDisplay[];
|
|
6
9
|
}
|
|
7
10
|
/**
|
|
8
11
|
* ToolOperation component - unified display for tool calls
|
|
9
12
|
* Handles both individual and grouped tool calls with smooth transitions
|
|
10
13
|
*/
|
|
11
|
-
export declare function ToolOperation({ toolCalls, isGrouped, autoMinimize, }: ToolOperationProps): import("react/jsx-runtime").JSX.Element;
|
|
14
|
+
export declare function ToolOperation({ toolCalls, isGrouped, autoMinimize, hookNotifications, }: ToolOperationProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -31,7 +31,7 @@ const ICON_MAP = {
|
|
|
31
31
|
* ToolOperation component - unified display for tool calls
|
|
32
32
|
* Handles both individual and grouped tool calls with smooth transitions
|
|
33
33
|
*/
|
|
34
|
-
export function ToolOperation({ toolCalls, isGrouped = false, autoMinimize = true, }) {
|
|
34
|
+
export function ToolOperation({ toolCalls, isGrouped = false, autoMinimize = true, hookNotifications = [], }) {
|
|
35
35
|
const [isExpanded, setIsExpanded] = useState(false);
|
|
36
36
|
const [isMinimized, setIsMinimized] = useState(false);
|
|
37
37
|
const [userInteracted, setUserInteracted] = useState(false);
|
|
@@ -40,6 +40,10 @@ export function ToolOperation({ toolCalls, isGrouped = false, autoMinimize = tru
|
|
|
40
40
|
// For single tool call, extract it
|
|
41
41
|
const singleToolCall = toolCalls.length === 1 ? toolCalls[0] : null;
|
|
42
42
|
const isTodoWrite = singleToolCall?.title === "todo_write";
|
|
43
|
+
// Find hook notification for this tool call (for compaction status)
|
|
44
|
+
const toolHookNotification = singleToolCall
|
|
45
|
+
? hookNotifications.find((n) => n.toolCallId === singleToolCall.id)
|
|
46
|
+
: undefined;
|
|
43
47
|
// Detect subagent calls
|
|
44
48
|
const hasLiveSubagent = !!(singleToolCall?.subagentPort && singleToolCall?.subagentSessionId);
|
|
45
49
|
const hasStoredSubagent = !!(singleToolCall?.subagentMessages &&
|
|
@@ -191,20 +195,48 @@ export function ToolOperation({ toolCalls, isGrouped = false, autoMinimize = tru
|
|
|
191
195
|
ease: motionEasing.smooth,
|
|
192
196
|
}), className: "h-3 w-3 text-text-secondary/70 group-hover:text-text-secondary transition-colors", children: _jsx(ChevronDown, { className: "h-3 w-3" }) }))] }), !isGrouped &&
|
|
193
197
|
singleToolCall &&
|
|
194
|
-
(isTodoWrite && singleToolCall.rawInput?.todos ? (_jsx(TodoSubline, { todos: singleToolCall.rawInput.todos, className: "text-paragraph-sm text-text-secondary/70 pl-4.5" })) : singleToolCall.subline ? (_jsx("span", { className: "text-paragraph-sm text-text-secondary/70 pl-4.5", children: singleToolCall.subline })) : null), isGrouped &&
|
|
198
|
+
(isTodoWrite && singleToolCall.rawInput?.todos ? (_jsx(TodoSubline, { todos: singleToolCall.rawInput.todos, className: "text-paragraph-sm text-text-secondary/70 pl-4.5" })) : singleToolCall.subline ? (_jsx("span", { className: "text-paragraph-sm text-text-secondary/70 pl-4.5", children: singleToolCall.subline })) : null), !isGrouped && toolHookNotification && (_jsx("span", { className: "text-paragraph-sm text-text-secondary/70 pl-4.5", children: toolHookNotification.status === "triggered"
|
|
199
|
+
? "Compacting response..."
|
|
200
|
+
: toolHookNotification.status === "completed"
|
|
201
|
+
? toolHookNotification.metadata?.action === "no_action_needed"
|
|
202
|
+
? `Response checked (${toolHookNotification.currentPercentage?.toFixed(0)}% context)`
|
|
203
|
+
: toolHookNotification.metadata?.tokensSaved
|
|
204
|
+
? `Response compacted (${((toolHookNotification.metadata.tokensSaved / (toolHookNotification.metadata.originalTokens || 1)) * 100).toFixed(0)}% reduced)`
|
|
205
|
+
: "Response compacted"
|
|
206
|
+
: toolHookNotification.status === "error"
|
|
207
|
+
? `Compaction error: ${toolHookNotification.error}`
|
|
208
|
+
: null })), isGrouped && !isExpanded && (_jsx("span", { className: "text-paragraph-sm text-text-secondary/70 pl-4.5", children: displayText })), isGrouped &&
|
|
209
|
+
hookNotifications.length > 0 &&
|
|
210
|
+
(() => {
|
|
211
|
+
const compactedCount = hookNotifications.filter((n) => n.status === "completed" &&
|
|
212
|
+
n.metadata?.action !== "no_action_needed").length;
|
|
213
|
+
const runningCount = hookNotifications.filter((n) => n.status === "triggered").length;
|
|
214
|
+
if (runningCount > 0) {
|
|
215
|
+
return (_jsxs("span", { className: "text-paragraph-sm text-text-secondary/70 pl-4.5", children: ["Compacting ", runningCount, " response", runningCount > 1 ? "s" : "", "..."] }));
|
|
216
|
+
}
|
|
217
|
+
if (compactedCount > 0) {
|
|
218
|
+
return (_jsxs("span", { className: "text-paragraph-sm text-text-secondary/70 pl-4.5", children: [compactedCount, " response", compactedCount > 1 ? "s" : "", " ", "compacted"] }));
|
|
219
|
+
}
|
|
220
|
+
return null;
|
|
221
|
+
})()] }), !isTodoWrite && isSubagentCall && singleToolCall && (_jsx("div", { className: "pl-4.5 mt-2", children: _jsx(SubAgentDetails, { port: singleToolCall.subagentPort, sessionId: singleToolCall.subagentSessionId, parentStatus: singleToolCall.status, agentName: singleToolCall.rawInput?.agentName, query: singleToolCall.rawInput?.query, isExpanded: isSubagentExpanded, onExpandChange: setIsSubagentExpanded, storedMessages: singleToolCall.subagentMessages, isReplay: isReplaySubagent }) })), _jsx(AnimatePresence, { initial: false, children: !isTodoWrite && isExpanded && (_jsx(motion.div, { initial: "collapsed", animate: "expanded", exit: "collapsed", variants: expandCollapseVariants, transition: getTransition(shouldReduceMotion ?? false, {
|
|
195
222
|
duration: motionDuration.normal,
|
|
196
223
|
ease: motionEasing.smooth,
|
|
197
224
|
}), className: "mt-1", children: isGrouped ? (
|
|
198
225
|
// Render individual tool calls in group
|
|
199
|
-
_jsx("div", { className: "flex flex-col gap-4 mt-2", children: toolCalls.map((toolCall) =>
|
|
226
|
+
_jsx("div", { className: "flex flex-col gap-4 mt-2", children: toolCalls.map((toolCall) => {
|
|
227
|
+
const hookNotification = hookNotifications.find((n) => n.toolCallId === toolCall.id);
|
|
228
|
+
return (_jsx(GroupedToolCallItem, { toolCall: toolCall, ...(hookNotification ? { hookNotification } : {}) }, toolCall.id));
|
|
229
|
+
}) })) : (
|
|
200
230
|
// Render single tool call details
|
|
201
|
-
singleToolCall && (_jsx(ToolOperationDetails, { toolCall: singleToolCall
|
|
231
|
+
singleToolCall && (_jsx(ToolOperationDetails, { toolCall: singleToolCall, ...(toolHookNotification
|
|
232
|
+
? { hookNotification: toolHookNotification }
|
|
233
|
+
: {}) }))) }, "expanded-content")) })] }));
|
|
202
234
|
}
|
|
203
235
|
/**
|
|
204
236
|
* Component to render a single tool call within a grouped parallel operation
|
|
205
237
|
* Handles subagent calls with their own expansion state
|
|
206
238
|
*/
|
|
207
|
-
function GroupedToolCallItem({ toolCall }) {
|
|
239
|
+
function GroupedToolCallItem({ toolCall, hookNotification, }) {
|
|
208
240
|
const [isSubagentExpanded, setIsSubagentExpanded] = useState(false);
|
|
209
241
|
// Detect subagent calls
|
|
210
242
|
const hasLiveSubagent = !!(toolCall.subagentPort && toolCall.subagentSessionId);
|
|
@@ -216,12 +248,12 @@ function GroupedToolCallItem({ toolCall }) {
|
|
|
216
248
|
return (_jsxs("div", { className: "flex flex-col ml-5", children: [_jsxs("button", { type: "button", className: "flex items-center gap-1.5 cursor-pointer bg-transparent border-none p-0 text-left group w-fit", onClick: () => setIsSubagentExpanded(!isSubagentExpanded), "aria-expanded": isSubagentExpanded, children: [_jsx("div", { className: "text-text-secondary/70 group-hover:text-text-secondary transition-colors", children: _jsx(CircleDot, { className: "h-3 w-3" }) }), _jsx("span", { className: "text-paragraph-sm text-text-secondary/70 group-hover:text-text-secondary transition-colors", children: toolCall.rawInput?.agentName || "Subagent" }), _jsx(ChevronDown, { className: `h-3 w-3 text-text-secondary/70 group-hover:text-text-secondary transition-colors transition-transform duration-200 ${isSubagentExpanded ? "rotate-180" : ""}` })] }), _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, storedMessages: toolCall.subagentMessages, isReplay: isReplaySubagent }) })] }));
|
|
217
249
|
}
|
|
218
250
|
// Regular tool call - show details
|
|
219
|
-
return (_jsx("div", { className: "flex items-start gap-1.5", children: _jsx("div", { className: "flex-1 ml-5", children: _jsx(ToolOperationDetails, { toolCall: toolCall }) }) }));
|
|
251
|
+
return (_jsx("div", { className: "flex items-start gap-1.5", children: _jsx("div", { className: "flex-1 ml-5", children: _jsx(ToolOperationDetails, { toolCall: toolCall, ...(hookNotification ? { hookNotification } : {}) }) }) }));
|
|
220
252
|
}
|
|
221
253
|
/**
|
|
222
254
|
* Component to display detailed tool call information
|
|
223
255
|
*/
|
|
224
|
-
function ToolOperationDetails({ toolCall }) {
|
|
256
|
+
function ToolOperationDetails({ toolCall, hookNotification, }) {
|
|
225
257
|
const { resolvedTheme } = useTheme();
|
|
226
258
|
// Don't show details for preliminary tool calls
|
|
227
259
|
if (isPreliminaryToolCall(toolCall)) {
|
|
@@ -328,5 +360,10 @@ function ToolOperationDetails({ toolCall }) {
|
|
|
328
360
|
`:${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()));
|
|
329
361
|
}
|
|
330
362
|
return null;
|
|
331
|
-
}), toolCall.error && (_jsxs("div", { className: "text-destructive font-mono text-[11px] mt-2", children: ["Error: ", toolCall.error] }))] })] })), 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 })] })),
|
|
363
|
+
}), toolCall.error && (_jsxs("div", { className: "text-destructive font-mono text-[11px] mt-2", children: ["Error: ", toolCall.error] }))] })] })), 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 })] })), hookNotification &&
|
|
364
|
+
hookNotification.status === "completed" &&
|
|
365
|
+
hookNotification.metadata?.action !== "no_action_needed" && (_jsxs("div", { className: "p-3 border-b border-border last:border-0", children: [_jsx("div", { className: "text-[10px] font-bold text-text-secondary uppercase tracking-wider mb-1.5 font-sans", children: "Response Compaction" }), _jsxs("div", { className: "space-y-1 text-[11px]", children: [hookNotification.metadata?.originalTokens !== undefined && (_jsxs("div", { className: "flex gap-2", children: [_jsx("span", { className: "text-text-secondary", children: "Original:" }), _jsxs("span", { className: "text-foreground", children: [hookNotification.metadata.originalTokens.toLocaleString(), " ", "tokens"] })] })), hookNotification.metadata?.finalTokens !== undefined && (_jsxs("div", { className: "flex gap-2", children: [_jsx("span", { className: "text-text-secondary", children: "Compacted:" }), _jsxs("span", { className: "text-foreground", children: [hookNotification.metadata.finalTokens.toLocaleString(), " ", "tokens"] })] })), hookNotification.metadata?.tokensSaved !== undefined && (_jsxs("div", { className: "flex gap-2", children: [_jsx("span", { className: "text-text-secondary", children: "Saved:" }), _jsxs("span", { className: "text-green-500 font-medium", children: [hookNotification.metadata.tokensSaved.toLocaleString(), " ", "tokens", hookNotification.metadata?.originalTokens && (_jsxs("span", { className: "text-text-secondary font-normal ml-1", children: ["(", ((hookNotification.metadata.tokensSaved /
|
|
366
|
+
hookNotification.metadata
|
|
367
|
+
.originalTokens) *
|
|
368
|
+
100).toFixed(0), "% reduced)"] }))] })] }))] })] })), (toolCall.tokenUsage || toolCall.startedAt) && (_jsxs("div", { className: "p-2 bg-muted/50 border-b border-border last:border-0 flex flex-wrap gap-4 text-[10px] text-text-secondary 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)"] }))] }))] }))] }));
|
|
332
369
|
}
|
|
@@ -284,6 +284,7 @@ export declare const HookTriggeredNotification: z.ZodObject<{
|
|
|
284
284
|
currentPercentage: z.ZodNumber;
|
|
285
285
|
callback: z.ZodString;
|
|
286
286
|
triggeredAt: z.ZodOptional<z.ZodNumber>;
|
|
287
|
+
toolCallId: z.ZodOptional<z.ZodString>;
|
|
287
288
|
}, z.core.$strip>;
|
|
288
289
|
export type HookTriggeredNotification = z.infer<typeof HookTriggeredNotification>;
|
|
289
290
|
/**
|
|
@@ -302,6 +303,7 @@ export declare const HookCompletedNotification: z.ZodObject<{
|
|
|
302
303
|
tokensSaved: z.ZodOptional<z.ZodNumber>;
|
|
303
304
|
}, z.core.$loose>>;
|
|
304
305
|
completedAt: z.ZodOptional<z.ZodNumber>;
|
|
306
|
+
toolCallId: z.ZodOptional<z.ZodString>;
|
|
305
307
|
}, z.core.$strip>;
|
|
306
308
|
export type HookCompletedNotification = z.infer<typeof HookCompletedNotification>;
|
|
307
309
|
/**
|
|
@@ -316,6 +318,7 @@ export declare const HookErrorNotification: z.ZodObject<{
|
|
|
316
318
|
callback: z.ZodString;
|
|
317
319
|
error: z.ZodString;
|
|
318
320
|
completedAt: z.ZodOptional<z.ZodNumber>;
|
|
321
|
+
toolCallId: z.ZodOptional<z.ZodString>;
|
|
319
322
|
}, z.core.$strip>;
|
|
320
323
|
export type HookErrorNotification = z.infer<typeof HookErrorNotification>;
|
|
321
324
|
/**
|
|
@@ -331,6 +334,7 @@ export declare const HookNotification: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
331
334
|
currentPercentage: z.ZodNumber;
|
|
332
335
|
callback: z.ZodString;
|
|
333
336
|
triggeredAt: z.ZodOptional<z.ZodNumber>;
|
|
337
|
+
toolCallId: z.ZodOptional<z.ZodString>;
|
|
334
338
|
}, z.core.$strip>, z.ZodObject<{
|
|
335
339
|
type: z.ZodLiteral<"hook_completed">;
|
|
336
340
|
hookType: z.ZodEnum<{
|
|
@@ -344,6 +348,7 @@ export declare const HookNotification: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
344
348
|
tokensSaved: z.ZodOptional<z.ZodNumber>;
|
|
345
349
|
}, z.core.$loose>>;
|
|
346
350
|
completedAt: z.ZodOptional<z.ZodNumber>;
|
|
351
|
+
toolCallId: z.ZodOptional<z.ZodString>;
|
|
347
352
|
}, z.core.$strip>, z.ZodObject<{
|
|
348
353
|
type: z.ZodLiteral<"hook_error">;
|
|
349
354
|
hookType: z.ZodEnum<{
|
|
@@ -353,6 +358,7 @@ export declare const HookNotification: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
353
358
|
callback: z.ZodString;
|
|
354
359
|
error: z.ZodString;
|
|
355
360
|
completedAt: z.ZodOptional<z.ZodNumber>;
|
|
361
|
+
toolCallId: z.ZodOptional<z.ZodString>;
|
|
356
362
|
}, z.core.$strip>], "type">;
|
|
357
363
|
export type HookNotification = z.infer<typeof HookNotification>;
|
|
358
364
|
/**
|
|
@@ -371,6 +377,7 @@ export declare const HookNotificationChunk: z.ZodObject<{
|
|
|
371
377
|
currentPercentage: z.ZodNumber;
|
|
372
378
|
callback: z.ZodString;
|
|
373
379
|
triggeredAt: z.ZodOptional<z.ZodNumber>;
|
|
380
|
+
toolCallId: z.ZodOptional<z.ZodString>;
|
|
374
381
|
}, z.core.$strip>, z.ZodObject<{
|
|
375
382
|
type: z.ZodLiteral<"hook_completed">;
|
|
376
383
|
hookType: z.ZodEnum<{
|
|
@@ -384,6 +391,7 @@ export declare const HookNotificationChunk: z.ZodObject<{
|
|
|
384
391
|
tokensSaved: z.ZodOptional<z.ZodNumber>;
|
|
385
392
|
}, z.core.$loose>>;
|
|
386
393
|
completedAt: z.ZodOptional<z.ZodNumber>;
|
|
394
|
+
toolCallId: z.ZodOptional<z.ZodString>;
|
|
387
395
|
}, z.core.$strip>, z.ZodObject<{
|
|
388
396
|
type: z.ZodLiteral<"hook_error">;
|
|
389
397
|
hookType: z.ZodEnum<{
|
|
@@ -393,6 +401,7 @@ export declare const HookNotificationChunk: z.ZodObject<{
|
|
|
393
401
|
callback: z.ZodString;
|
|
394
402
|
error: z.ZodString;
|
|
395
403
|
completedAt: z.ZodOptional<z.ZodNumber>;
|
|
404
|
+
toolCallId: z.ZodOptional<z.ZodString>;
|
|
396
405
|
}, z.core.$strip>], "type">;
|
|
397
406
|
messageId: z.ZodOptional<z.ZodString>;
|
|
398
407
|
}, z.core.$strip>;
|
|
@@ -484,6 +493,7 @@ export declare const MessageChunk: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
484
493
|
currentPercentage: z.ZodNumber;
|
|
485
494
|
callback: z.ZodString;
|
|
486
495
|
triggeredAt: z.ZodOptional<z.ZodNumber>;
|
|
496
|
+
toolCallId: z.ZodOptional<z.ZodString>;
|
|
487
497
|
}, z.core.$strip>, z.ZodObject<{
|
|
488
498
|
type: z.ZodLiteral<"hook_completed">;
|
|
489
499
|
hookType: z.ZodEnum<{
|
|
@@ -497,6 +507,7 @@ export declare const MessageChunk: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
497
507
|
tokensSaved: z.ZodOptional<z.ZodNumber>;
|
|
498
508
|
}, z.core.$loose>>;
|
|
499
509
|
completedAt: z.ZodOptional<z.ZodNumber>;
|
|
510
|
+
toolCallId: z.ZodOptional<z.ZodString>;
|
|
500
511
|
}, z.core.$strip>, z.ZodObject<{
|
|
501
512
|
type: z.ZodLiteral<"hook_error">;
|
|
502
513
|
hookType: z.ZodEnum<{
|
|
@@ -506,6 +517,7 @@ export declare const MessageChunk: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
506
517
|
callback: z.ZodString;
|
|
507
518
|
error: z.ZodString;
|
|
508
519
|
completedAt: z.ZodOptional<z.ZodNumber>;
|
|
520
|
+
toolCallId: z.ZodOptional<z.ZodString>;
|
|
509
521
|
}, z.core.$strip>], "type">;
|
|
510
522
|
messageId: z.ZodOptional<z.ZodString>;
|
|
511
523
|
}, z.core.$strip>], "type">;
|
|
@@ -161,6 +161,7 @@ export const HookTriggeredNotification = z.object({
|
|
|
161
161
|
currentPercentage: z.number(),
|
|
162
162
|
callback: z.string(),
|
|
163
163
|
triggeredAt: z.number().optional(), // Unix timestamp (ms) from backend
|
|
164
|
+
toolCallId: z.string().optional(), // For tool_response hooks - associates notification with tool call
|
|
164
165
|
});
|
|
165
166
|
/**
|
|
166
167
|
* Hook completed notification
|
|
@@ -178,6 +179,7 @@ export const HookCompletedNotification = z.object({
|
|
|
178
179
|
.passthrough()
|
|
179
180
|
.optional(),
|
|
180
181
|
completedAt: z.number().optional(), // Unix timestamp (ms) from backend
|
|
182
|
+
toolCallId: z.string().optional(), // For tool_response hooks - associates notification with tool call
|
|
181
183
|
});
|
|
182
184
|
/**
|
|
183
185
|
* Hook error notification
|
|
@@ -188,6 +190,7 @@ export const HookErrorNotification = z.object({
|
|
|
188
190
|
callback: z.string(),
|
|
189
191
|
error: z.string(),
|
|
190
192
|
completedAt: z.number().optional(), // Unix timestamp (ms) from backend
|
|
193
|
+
toolCallId: z.string().optional(), // For tool_response hooks - associates notification with tool call
|
|
191
194
|
});
|
|
192
195
|
/**
|
|
193
196
|
* Union of all hook notification types
|
|
@@ -4,12 +4,12 @@ import { z } from "zod";
|
|
|
4
4
|
*/
|
|
5
5
|
export declare const SessionStatus: z.ZodEnum<{
|
|
6
6
|
error: "error";
|
|
7
|
-
|
|
7
|
+
active: "active";
|
|
8
|
+
disconnected: "disconnected";
|
|
8
9
|
connecting: "connecting";
|
|
9
10
|
connected: "connected";
|
|
10
|
-
|
|
11
|
+
idle: "idle";
|
|
11
12
|
streaming: "streaming";
|
|
12
|
-
disconnected: "disconnected";
|
|
13
13
|
}>;
|
|
14
14
|
export type SessionStatus = z.infer<typeof SessionStatus>;
|
|
15
15
|
/**
|
|
@@ -41,12 +41,12 @@ export declare const Session: z.ZodObject<{
|
|
|
41
41
|
id: z.ZodString;
|
|
42
42
|
status: z.ZodEnum<{
|
|
43
43
|
error: "error";
|
|
44
|
-
|
|
44
|
+
active: "active";
|
|
45
|
+
disconnected: "disconnected";
|
|
45
46
|
connecting: "connecting";
|
|
46
47
|
connected: "connected";
|
|
47
|
-
|
|
48
|
+
idle: "idle";
|
|
48
49
|
streaming: "streaming";
|
|
49
|
-
disconnected: "disconnected";
|
|
50
50
|
}>;
|
|
51
51
|
config: z.ZodObject<{
|
|
52
52
|
agentPath: z.ZodString;
|
|
@@ -117,12 +117,12 @@ export declare const SessionUpdate: z.ZodUnion<readonly [z.ZodObject<{
|
|
|
117
117
|
sessionId: z.ZodString;
|
|
118
118
|
status: z.ZodOptional<z.ZodEnum<{
|
|
119
119
|
error: "error";
|
|
120
|
-
|
|
120
|
+
active: "active";
|
|
121
|
+
disconnected: "disconnected";
|
|
121
122
|
connecting: "connecting";
|
|
122
123
|
connected: "connected";
|
|
123
|
-
|
|
124
|
+
idle: "idle";
|
|
124
125
|
streaming: "streaming";
|
|
125
|
-
disconnected: "disconnected";
|
|
126
126
|
}>>;
|
|
127
127
|
message: z.ZodOptional<z.ZodObject<{
|
|
128
128
|
id: z.ZodString;
|
|
@@ -197,9 +197,9 @@ export declare const SessionUpdate: z.ZodUnion<readonly [z.ZodObject<{
|
|
|
197
197
|
other: "other";
|
|
198
198
|
}>;
|
|
199
199
|
status: z.ZodEnum<{
|
|
200
|
+
completed: "completed";
|
|
200
201
|
pending: "pending";
|
|
201
202
|
in_progress: "in_progress";
|
|
202
|
-
completed: "completed";
|
|
203
203
|
failed: "failed";
|
|
204
204
|
}>;
|
|
205
205
|
contentPosition: z.ZodOptional<z.ZodNumber>;
|
|
@@ -265,9 +265,9 @@ export declare const SessionUpdate: z.ZodUnion<readonly [z.ZodObject<{
|
|
|
265
265
|
prettyName: z.ZodOptional<z.ZodString>;
|
|
266
266
|
icon: z.ZodOptional<z.ZodString>;
|
|
267
267
|
status: z.ZodEnum<{
|
|
268
|
+
completed: "completed";
|
|
268
269
|
pending: "pending";
|
|
269
270
|
in_progress: "in_progress";
|
|
270
|
-
completed: "completed";
|
|
271
271
|
failed: "failed";
|
|
272
272
|
}>;
|
|
273
273
|
content: z.ZodOptional<z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
@@ -310,9 +310,9 @@ export declare const SessionUpdate: z.ZodUnion<readonly [z.ZodObject<{
|
|
|
310
310
|
prettyName: z.ZodOptional<z.ZodString>;
|
|
311
311
|
icon: z.ZodOptional<z.ZodString>;
|
|
312
312
|
status: z.ZodEnum<{
|
|
313
|
+
completed: "completed";
|
|
313
314
|
pending: "pending";
|
|
314
315
|
in_progress: "in_progress";
|
|
315
|
-
completed: "completed";
|
|
316
316
|
failed: "failed";
|
|
317
317
|
}>;
|
|
318
318
|
content: z.ZodOptional<z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
@@ -354,12 +354,12 @@ export declare const SessionUpdate: z.ZodUnion<readonly [z.ZodObject<{
|
|
|
354
354
|
sessionId: z.ZodString;
|
|
355
355
|
status: z.ZodOptional<z.ZodEnum<{
|
|
356
356
|
error: "error";
|
|
357
|
-
|
|
357
|
+
active: "active";
|
|
358
|
+
disconnected: "disconnected";
|
|
358
359
|
connecting: "connecting";
|
|
359
360
|
connected: "connected";
|
|
360
|
-
|
|
361
|
+
idle: "idle";
|
|
361
362
|
streaming: "streaming";
|
|
362
|
-
disconnected: "disconnected";
|
|
363
363
|
}>>;
|
|
364
364
|
message: z.ZodOptional<z.ZodObject<{
|
|
365
365
|
id: z.ZodString;
|
|
@@ -412,9 +412,9 @@ export declare const SessionUpdate: z.ZodUnion<readonly [z.ZodObject<{
|
|
|
412
412
|
toolCallUpdate: z.ZodObject<{
|
|
413
413
|
id: z.ZodString;
|
|
414
414
|
status: z.ZodOptional<z.ZodEnum<{
|
|
415
|
+
completed: "completed";
|
|
415
416
|
pending: "pending";
|
|
416
417
|
in_progress: "in_progress";
|
|
417
|
-
completed: "completed";
|
|
418
418
|
failed: "failed";
|
|
419
419
|
}>>;
|
|
420
420
|
title: z.ZodOptional<z.ZodString>;
|
|
@@ -473,9 +473,9 @@ export declare const SessionUpdate: z.ZodUnion<readonly [z.ZodObject<{
|
|
|
473
473
|
prettyName: z.ZodOptional<z.ZodString>;
|
|
474
474
|
icon: z.ZodOptional<z.ZodString>;
|
|
475
475
|
status: z.ZodEnum<{
|
|
476
|
+
completed: "completed";
|
|
476
477
|
pending: "pending";
|
|
477
478
|
in_progress: "in_progress";
|
|
478
|
-
completed: "completed";
|
|
479
479
|
failed: "failed";
|
|
480
480
|
}>;
|
|
481
481
|
content: z.ZodOptional<z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
@@ -518,9 +518,9 @@ export declare const SessionUpdate: z.ZodUnion<readonly [z.ZodObject<{
|
|
|
518
518
|
prettyName: z.ZodOptional<z.ZodString>;
|
|
519
519
|
icon: z.ZodOptional<z.ZodString>;
|
|
520
520
|
status: z.ZodEnum<{
|
|
521
|
+
completed: "completed";
|
|
521
522
|
pending: "pending";
|
|
522
523
|
in_progress: "in_progress";
|
|
523
|
-
completed: "completed";
|
|
524
524
|
failed: "failed";
|
|
525
525
|
}>;
|
|
526
526
|
content: z.ZodOptional<z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
@@ -561,12 +561,12 @@ export declare const SessionUpdate: z.ZodUnion<readonly [z.ZodObject<{
|
|
|
561
561
|
sessionId: z.ZodString;
|
|
562
562
|
status: z.ZodOptional<z.ZodEnum<{
|
|
563
563
|
error: "error";
|
|
564
|
-
|
|
564
|
+
active: "active";
|
|
565
|
+
disconnected: "disconnected";
|
|
565
566
|
connecting: "connecting";
|
|
566
567
|
connected: "connected";
|
|
567
|
-
|
|
568
|
+
idle: "idle";
|
|
568
569
|
streaming: "streaming";
|
|
569
|
-
disconnected: "disconnected";
|
|
570
570
|
}>>;
|
|
571
571
|
message: z.ZodOptional<z.ZodObject<{
|
|
572
572
|
id: z.ZodString;
|
|
@@ -626,12 +626,12 @@ export declare const SessionUpdate: z.ZodUnion<readonly [z.ZodObject<{
|
|
|
626
626
|
sessionId: z.ZodString;
|
|
627
627
|
status: z.ZodOptional<z.ZodEnum<{
|
|
628
628
|
error: "error";
|
|
629
|
-
|
|
629
|
+
active: "active";
|
|
630
|
+
disconnected: "disconnected";
|
|
630
631
|
connecting: "connecting";
|
|
631
632
|
connected: "connected";
|
|
632
|
-
|
|
633
|
+
idle: "idle";
|
|
633
634
|
streaming: "streaming";
|
|
634
|
-
disconnected: "disconnected";
|
|
635
635
|
}>>;
|
|
636
636
|
message: z.ZodOptional<z.ZodObject<{
|
|
637
637
|
id: z.ZodString;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@townco/ui",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.76",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
"@radix-ui/react-slot": "^1.2.4",
|
|
50
50
|
"@radix-ui/react-tabs": "^1.1.13",
|
|
51
51
|
"@radix-ui/react-tooltip": "^1.2.8",
|
|
52
|
-
"@townco/core": "0.0.
|
|
52
|
+
"@townco/core": "0.0.54",
|
|
53
53
|
"@uiw/react-json-view": "^2.0.0-alpha.39",
|
|
54
54
|
"bun": "^1.3.1",
|
|
55
55
|
"class-variance-authority": "^0.7.1",
|
|
@@ -67,7 +67,7 @@
|
|
|
67
67
|
},
|
|
68
68
|
"devDependencies": {
|
|
69
69
|
"@tailwindcss/postcss": "^4.1.17",
|
|
70
|
-
"@townco/tsconfig": "0.1.
|
|
70
|
+
"@townco/tsconfig": "0.1.73",
|
|
71
71
|
"@types/node": "^24.10.0",
|
|
72
72
|
"@types/react": "^19.2.2",
|
|
73
73
|
"ink": "^6.4.0",
|