ai-design-system 0.1.54 → 0.1.56
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/components/ai-elements/reasoning.tsx +6 -6
- package/components/blocks/AIConversation/AIConversation.tsx +27 -5
- package/components/composites/FileTreeExplorer/FileTreeExplorer.tsx +24 -4
- package/components/composites/ReasoningDisplay/ReasoningDisplay.stories.tsx +76 -0
- package/components/composites/ReasoningDisplay/ReasoningDisplay.tsx +46 -0
- package/components/composites/ReasoningDisplay/index.ts +2 -0
- package/components/composites/ToolCallDisplay/ToolCallDisplay.tsx +1 -0
- package/components/composites/index.ts +4 -0
- package/dist/index.cjs +241 -34
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +11 -0
- package/dist/index.js +243 -36
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -22,7 +22,7 @@ type ReasoningContextValue = {
|
|
|
22
22
|
|
|
23
23
|
const ReasoningContext = createContext<ReasoningContextValue | null>(null);
|
|
24
24
|
|
|
25
|
-
const useReasoning = () => {
|
|
25
|
+
export const useReasoning = () => {
|
|
26
26
|
const context = useContext(ReasoningContext);
|
|
27
27
|
if (!context) {
|
|
28
28
|
throw new Error("Reasoning components must be used within Reasoning");
|
|
@@ -124,14 +124,14 @@ export const Reasoning = memo(
|
|
|
124
124
|
|
|
125
125
|
export type ReasoningTriggerProps = ComponentProps<typeof CollapsibleTrigger>;
|
|
126
126
|
|
|
127
|
-
const getThinkingMessage = (isStreaming: boolean, duration?: number) => {
|
|
128
|
-
if (isStreaming
|
|
127
|
+
export const getThinkingMessage = (isStreaming: boolean, duration?: number) => {
|
|
128
|
+
if (isStreaming) {
|
|
129
129
|
return <Shimmer duration={1}>Thinking...</Shimmer>;
|
|
130
130
|
}
|
|
131
|
-
if (duration === undefined) {
|
|
132
|
-
return <
|
|
131
|
+
if (duration === undefined || duration === 0) {
|
|
132
|
+
return <span>Thought for a few seconds</span>;
|
|
133
133
|
}
|
|
134
|
-
return <
|
|
134
|
+
return <span>Thought for {duration} seconds</span>;
|
|
135
135
|
};
|
|
136
136
|
|
|
137
137
|
export const ReasoningTrigger = memo(
|
|
@@ -11,6 +11,7 @@ import { UserMessage } from "@/components/composites/UserMessage"
|
|
|
11
11
|
import { SpecialistMessage } from "@/components/composites/SpecialistMessage"
|
|
12
12
|
import { OrchestratorMessage } from "@/components/composites/OrchestratorMessage"
|
|
13
13
|
import { ToolCallDisplay } from "@/components/composites/ToolCallDisplay"
|
|
14
|
+
import { ReasoningDisplay } from "@/components/composites/ReasoningDisplay"
|
|
14
15
|
import { ApprovalCard } from "@/components/composites/ApprovalCard"
|
|
15
16
|
|
|
16
17
|
/**
|
|
@@ -127,28 +128,49 @@ export const AIConversation = React.memo<AIConversationProps>(
|
|
|
127
128
|
|
|
128
129
|
// Filter tool calls that aren't "task" type (those become sub-agents)
|
|
129
130
|
// Also completely hide "ask_user" and "ask_question" tools so they are ONLY rendered in the prompt input area
|
|
130
|
-
const
|
|
131
|
+
const allToolCalls =
|
|
131
132
|
message.toolCalls?.filter(
|
|
132
133
|
(tc) => tc.name !== "task" && tc.name !== "ask_user"
|
|
133
134
|
) || []
|
|
134
135
|
|
|
136
|
+
// Split into reasoning tools (shown collapsed) and direct tools (shown normally)
|
|
137
|
+
const reasoningCalls = allToolCalls.filter((tc) => tc.visibility === "reasoning")
|
|
138
|
+
const directToolCalls = allToolCalls.filter((tc) => tc.visibility !== "reasoning")
|
|
139
|
+
|
|
135
140
|
const hasContent = contentStr.trim() !== ""
|
|
136
|
-
|
|
141
|
+
const hasReasoning = reasoningCalls.length > 0
|
|
142
|
+
const reasoningText = hasReasoning ? contentStr : undefined
|
|
143
|
+
const displayContentStr = hasReasoning ? "" : contentStr
|
|
144
|
+
const hasDisplayContent = displayContentStr.trim() !== ""
|
|
145
|
+
|
|
146
|
+
if (!hasDisplayContent && directToolCalls.length === 0 && reasoningCalls.length === 0 && subAgents.length === 0 && !message.isLoading) {
|
|
137
147
|
return null;
|
|
138
148
|
}
|
|
139
149
|
|
|
150
|
+
const isStreaming = reasoningCalls.some((tc) => tc.status === "pending")
|
|
151
|
+
|
|
140
152
|
return (
|
|
141
153
|
<OrchestratorMessage
|
|
142
154
|
key={message.id}
|
|
143
155
|
message={{
|
|
144
156
|
id: message.id,
|
|
145
|
-
content:
|
|
157
|
+
content: displayContentStr,
|
|
146
158
|
avatarSrc: message.avatarSrc,
|
|
147
159
|
avatarName: message.avatarName,
|
|
148
|
-
isLoading: message.isLoading,
|
|
160
|
+
isLoading: message.isLoading && !hasReasoning,
|
|
149
161
|
}}
|
|
150
|
-
showAvatar={showAvatars}
|
|
162
|
+
showAvatar={showAvatars && hasDisplayContent}
|
|
151
163
|
>
|
|
164
|
+
{/* Render reasoning-section for hidden tool results */}
|
|
165
|
+
{hasReasoning && (
|
|
166
|
+
<ReasoningDisplay
|
|
167
|
+
content={reasoningText}
|
|
168
|
+
items={reasoningCalls}
|
|
169
|
+
isStreaming={isStreaming}
|
|
170
|
+
onToolAction={onToolAction}
|
|
171
|
+
/>
|
|
172
|
+
)}
|
|
173
|
+
|
|
152
174
|
{/* Render direct tool calls */}
|
|
153
175
|
{directToolCalls.map((tc) => (
|
|
154
176
|
<ToolCallDisplay key={tc.id} toolCall={tc} onToolAction={onToolAction} />
|
|
@@ -88,17 +88,36 @@ export const FileTreeExplorer = React.memo<FileTreeExplorerProps>(
|
|
|
88
88
|
className,
|
|
89
89
|
}) => {
|
|
90
90
|
const [searchQuery, setSearchQuery] = React.useState("")
|
|
91
|
+
const [userExpanded, setUserExpanded] = React.useState<Set<string>>(defaultExpanded || new Set())
|
|
92
|
+
|
|
93
|
+
// Auto-expand parents when selectedPath changes
|
|
94
|
+
React.useEffect(() => {
|
|
95
|
+
if (selectedPath) {
|
|
96
|
+
const parts = selectedPath.split('/')
|
|
97
|
+
if (parts.length > 1) {
|
|
98
|
+
setUserExpanded(prev => {
|
|
99
|
+
const next = new Set(prev)
|
|
100
|
+
let currentPath = ''
|
|
101
|
+
for (let i = 0; i < parts.length - 1; i++) {
|
|
102
|
+
currentPath += (i === 0 ? '' : '/') + parts[i]
|
|
103
|
+
next.add(currentPath)
|
|
104
|
+
}
|
|
105
|
+
return next
|
|
106
|
+
})
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}, [selectedPath])
|
|
91
110
|
|
|
92
111
|
const filteredTree = React.useMemo(() => {
|
|
93
112
|
return filterTree(tree, searchQuery)
|
|
94
113
|
}, [tree, searchQuery])
|
|
95
114
|
|
|
96
|
-
const
|
|
115
|
+
const activeExpanded = React.useMemo(() => {
|
|
97
116
|
if (searchQuery) {
|
|
98
117
|
return getAllFolderPaths(filteredTree)
|
|
99
118
|
}
|
|
100
|
-
return
|
|
101
|
-
}, [searchQuery, filteredTree,
|
|
119
|
+
return userExpanded
|
|
120
|
+
}, [searchQuery, filteredTree, userExpanded])
|
|
102
121
|
|
|
103
122
|
return (
|
|
104
123
|
<div className={cn("flex flex-col rounded-lg border bg-background", className)}>
|
|
@@ -130,7 +149,8 @@ export const FileTreeExplorer = React.memo<FileTreeExplorerProps>(
|
|
|
130
149
|
<div className="p-2">
|
|
131
150
|
<FileTree
|
|
132
151
|
className="border-none bg-transparent"
|
|
133
|
-
|
|
152
|
+
expanded={activeExpanded}
|
|
153
|
+
onExpandedChange={setUserExpanded}
|
|
134
154
|
selectedPath={selectedPath}
|
|
135
155
|
onSelect={onSelect}
|
|
136
156
|
>
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react'
|
|
2
|
+
import { ReasoningDisplay } from './ReasoningDisplay'
|
|
3
|
+
|
|
4
|
+
const meta: Meta<typeof ReasoningDisplay> = {
|
|
5
|
+
title: 'Composites/ReasoningDisplay',
|
|
6
|
+
component: ReasoningDisplay,
|
|
7
|
+
parameters: {
|
|
8
|
+
layout: 'padded',
|
|
9
|
+
},
|
|
10
|
+
} satisfies Meta<typeof ReasoningDisplay>
|
|
11
|
+
|
|
12
|
+
export default meta
|
|
13
|
+
type Story = StoryObj<typeof meta>
|
|
14
|
+
|
|
15
|
+
export const Default: Story = {
|
|
16
|
+
args: {
|
|
17
|
+
content: "Let me evaluate the user's request and read the necessary files to propose a solution.",
|
|
18
|
+
isStreaming: false,
|
|
19
|
+
items: [
|
|
20
|
+
{
|
|
21
|
+
id: 'tool_1',
|
|
22
|
+
name: 'read_file',
|
|
23
|
+
args: { file_path: '/workspace/src/main.tsx' },
|
|
24
|
+
result: 'import { App } from "./App"; ...',
|
|
25
|
+
status: 'completed',
|
|
26
|
+
visibility: 'reasoning',
|
|
27
|
+
uiVariant: 'link',
|
|
28
|
+
linkText: 'src/main.tsx',
|
|
29
|
+
linkAction: 'open-file',
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
id: 'tool_2',
|
|
33
|
+
name: 'read_file',
|
|
34
|
+
args: { file_path: '/workspace/src/App.tsx' },
|
|
35
|
+
result: 'export const App = () => <div>Hello</div>;',
|
|
36
|
+
status: 'completed',
|
|
37
|
+
visibility: 'reasoning',
|
|
38
|
+
uiVariant: 'link',
|
|
39
|
+
linkText: 'src/App.tsx',
|
|
40
|
+
linkAction: 'open-file',
|
|
41
|
+
}
|
|
42
|
+
],
|
|
43
|
+
},
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export const Streaming: Story = {
|
|
47
|
+
args: {
|
|
48
|
+
content: "I'll start by listing the directory contents...",
|
|
49
|
+
isStreaming: true,
|
|
50
|
+
items: [
|
|
51
|
+
{
|
|
52
|
+
id: 'tool_1',
|
|
53
|
+
name: 'list_dir',
|
|
54
|
+
args: { path: '/src' },
|
|
55
|
+
status: 'pending',
|
|
56
|
+
visibility: 'reasoning',
|
|
57
|
+
},
|
|
58
|
+
],
|
|
59
|
+
},
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export const OnlyTools: Story = {
|
|
63
|
+
args: {
|
|
64
|
+
isStreaming: false,
|
|
65
|
+
items: [
|
|
66
|
+
{
|
|
67
|
+
id: 'tool_1',
|
|
68
|
+
name: 'write_todos',
|
|
69
|
+
args: { todos: ['Fix layout', 'Update colors'] },
|
|
70
|
+
result: 'Todos written successfully.',
|
|
71
|
+
status: 'completed',
|
|
72
|
+
visibility: 'reasoning',
|
|
73
|
+
},
|
|
74
|
+
],
|
|
75
|
+
},
|
|
76
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
Reasoning,
|
|
5
|
+
ReasoningTrigger,
|
|
6
|
+
} from "@/components/ai-elements/reasoning";
|
|
7
|
+
import { CollapsibleContent } from "@/components/primitives/Collapsible";
|
|
8
|
+
import { Response } from "@/components/ai-elements/response";
|
|
9
|
+
import { ToolCallDisplay } from "@/components/composites/ToolCallDisplay";
|
|
10
|
+
import type { ToolCall } from "@/components/composites/ToolCallDisplay";
|
|
11
|
+
|
|
12
|
+
export interface ReasoningDisplayProps {
|
|
13
|
+
items: ToolCall[];
|
|
14
|
+
isStreaming?: boolean;
|
|
15
|
+
content?: string;
|
|
16
|
+
onToolAction?: (toolCall: ToolCall, action: string) => void;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export const ReasoningDisplay = ({
|
|
20
|
+
items,
|
|
21
|
+
isStreaming = false,
|
|
22
|
+
content,
|
|
23
|
+
onToolAction,
|
|
24
|
+
}: ReasoningDisplayProps) => {
|
|
25
|
+
if (items.length === 0 && !content) return null;
|
|
26
|
+
|
|
27
|
+
return (
|
|
28
|
+
<Reasoning isStreaming={isStreaming} defaultOpen={false}>
|
|
29
|
+
<ReasoningTrigger />
|
|
30
|
+
<CollapsibleContent
|
|
31
|
+
className="mt-4 flex flex-col gap-2 data-[state=closed]:fade-out-0 data-[state=closed]:slide-out-to-top-2 data-[state=open]:slide-in-from-top-2 text-muted-foreground outline-none data-[state=closed]:animate-out data-[state=open]:animate-in"
|
|
32
|
+
>
|
|
33
|
+
{content && content.trim() && (
|
|
34
|
+
<div className="mb-4">
|
|
35
|
+
<Response className="grid gap-2">{content}</Response>
|
|
36
|
+
</div>
|
|
37
|
+
)}
|
|
38
|
+
<div className="flex flex-col gap-2">
|
|
39
|
+
{items.map((item) => (
|
|
40
|
+
<ToolCallDisplay key={item.id} toolCall={item} onToolAction={onToolAction} />
|
|
41
|
+
))}
|
|
42
|
+
</div>
|
|
43
|
+
</CollapsibleContent>
|
|
44
|
+
</Reasoning>
|
|
45
|
+
);
|
|
46
|
+
};
|
|
@@ -9,6 +9,10 @@
|
|
|
9
9
|
export { ToolCallDisplay } from './ToolCallDisplay'
|
|
10
10
|
export type { ToolCallDisplayProps, ToolCall } from './ToolCallDisplay'
|
|
11
11
|
|
|
12
|
+
// ReasoningDisplay Block
|
|
13
|
+
export { ReasoningDisplay } from './ReasoningDisplay'
|
|
14
|
+
export type { ReasoningDisplayProps } from './ReasoningDisplay'
|
|
15
|
+
|
|
12
16
|
// AgentIndicator Block
|
|
13
17
|
export { AgentIndicator } from './AgentIndicator'
|
|
14
18
|
export type { AgentIndicatorProps, SubAgent } from './AgentIndicator'
|
package/dist/index.cjs
CHANGED
|
@@ -20,6 +20,7 @@ var useStickToBottom = require('use-stick-to-bottom');
|
|
|
20
20
|
var radixUi = require('radix-ui');
|
|
21
21
|
var shiki = require('shiki');
|
|
22
22
|
var streamdown = require('streamdown');
|
|
23
|
+
var reactUseControllableState = require('@radix-ui/react-use-controllable-state');
|
|
23
24
|
var ScrollAreaPrimitive = require('@radix-ui/react-scroll-area');
|
|
24
25
|
var HoverCardPrimitive = require('@radix-ui/react-hover-card');
|
|
25
26
|
var SelectPrimitive = require('@radix-ui/react-select');
|
|
@@ -3407,6 +3408,202 @@ var OrchestratorMessage = React3__namespace.memo(
|
|
|
3407
3408
|
}
|
|
3408
3409
|
);
|
|
3409
3410
|
OrchestratorMessage.displayName = "OrchestratorMessage";
|
|
3411
|
+
var ReasoningContext = React3.createContext(null);
|
|
3412
|
+
var useReasoning = () => {
|
|
3413
|
+
const context = React3.useContext(ReasoningContext);
|
|
3414
|
+
if (!context) {
|
|
3415
|
+
throw new Error("Reasoning components must be used within Reasoning");
|
|
3416
|
+
}
|
|
3417
|
+
return context;
|
|
3418
|
+
};
|
|
3419
|
+
var AUTO_CLOSE_DELAY = 1e3;
|
|
3420
|
+
var MS_IN_S = 1e3;
|
|
3421
|
+
var Reasoning = React3.memo(
|
|
3422
|
+
(_a) => {
|
|
3423
|
+
var _b = _a, {
|
|
3424
|
+
className,
|
|
3425
|
+
isStreaming = false,
|
|
3426
|
+
open,
|
|
3427
|
+
defaultOpen = true,
|
|
3428
|
+
onOpenChange,
|
|
3429
|
+
duration: durationProp,
|
|
3430
|
+
children
|
|
3431
|
+
} = _b, props = __objRest(_b, [
|
|
3432
|
+
"className",
|
|
3433
|
+
"isStreaming",
|
|
3434
|
+
"open",
|
|
3435
|
+
"defaultOpen",
|
|
3436
|
+
"onOpenChange",
|
|
3437
|
+
"duration",
|
|
3438
|
+
"children"
|
|
3439
|
+
]);
|
|
3440
|
+
const [isOpen, setIsOpen] = reactUseControllableState.useControllableState({
|
|
3441
|
+
prop: open,
|
|
3442
|
+
defaultProp: defaultOpen,
|
|
3443
|
+
onChange: onOpenChange
|
|
3444
|
+
});
|
|
3445
|
+
const [duration, setDuration] = reactUseControllableState.useControllableState({
|
|
3446
|
+
prop: durationProp,
|
|
3447
|
+
defaultProp: 0
|
|
3448
|
+
});
|
|
3449
|
+
const [hasAutoClosed, setHasAutoClosed] = React3.useState(false);
|
|
3450
|
+
const [startTime, setStartTime] = React3.useState(null);
|
|
3451
|
+
React3.useEffect(() => {
|
|
3452
|
+
if (isStreaming) {
|
|
3453
|
+
if (startTime === null) {
|
|
3454
|
+
const timer = setTimeout(() => {
|
|
3455
|
+
setStartTime(Date.now());
|
|
3456
|
+
}, 0);
|
|
3457
|
+
return () => clearTimeout(timer);
|
|
3458
|
+
}
|
|
3459
|
+
} else if (startTime !== null) {
|
|
3460
|
+
const calculatedDuration = Math.ceil((Date.now() - startTime) / MS_IN_S);
|
|
3461
|
+
const timer = setTimeout(() => {
|
|
3462
|
+
setDuration(calculatedDuration);
|
|
3463
|
+
setStartTime(null);
|
|
3464
|
+
}, 0);
|
|
3465
|
+
return () => clearTimeout(timer);
|
|
3466
|
+
}
|
|
3467
|
+
return void 0;
|
|
3468
|
+
}, [isStreaming, startTime, setDuration]);
|
|
3469
|
+
React3.useEffect(() => {
|
|
3470
|
+
if (defaultOpen && !isStreaming && isOpen && !hasAutoClosed) {
|
|
3471
|
+
const timer = setTimeout(() => {
|
|
3472
|
+
setIsOpen(false);
|
|
3473
|
+
setHasAutoClosed(true);
|
|
3474
|
+
}, AUTO_CLOSE_DELAY);
|
|
3475
|
+
return () => clearTimeout(timer);
|
|
3476
|
+
}
|
|
3477
|
+
return void 0;
|
|
3478
|
+
}, [isStreaming, isOpen, defaultOpen, setIsOpen, hasAutoClosed]);
|
|
3479
|
+
const handleOpenChange = (newOpen) => {
|
|
3480
|
+
setIsOpen(newOpen);
|
|
3481
|
+
};
|
|
3482
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
3483
|
+
ReasoningContext.Provider,
|
|
3484
|
+
{
|
|
3485
|
+
value: { isStreaming, isOpen, setIsOpen, duration },
|
|
3486
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3487
|
+
Collapsible,
|
|
3488
|
+
__spreadProps(__spreadValues({
|
|
3489
|
+
className: cn("not-prose mb-4", className),
|
|
3490
|
+
onOpenChange: handleOpenChange,
|
|
3491
|
+
open: isOpen
|
|
3492
|
+
}, props), {
|
|
3493
|
+
children
|
|
3494
|
+
})
|
|
3495
|
+
)
|
|
3496
|
+
}
|
|
3497
|
+
);
|
|
3498
|
+
}
|
|
3499
|
+
);
|
|
3500
|
+
var getThinkingMessage = (isStreaming, duration) => {
|
|
3501
|
+
if (isStreaming) {
|
|
3502
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Shimmer, { duration: 1, children: "Thinking..." });
|
|
3503
|
+
}
|
|
3504
|
+
if (duration === void 0 || duration === 0) {
|
|
3505
|
+
return /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Thought for a few seconds" });
|
|
3506
|
+
}
|
|
3507
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
3508
|
+
"Thought for ",
|
|
3509
|
+
duration,
|
|
3510
|
+
" seconds"
|
|
3511
|
+
] });
|
|
3512
|
+
};
|
|
3513
|
+
var ReasoningTrigger = React3.memo(
|
|
3514
|
+
(_a) => {
|
|
3515
|
+
var _b = _a, { className, children } = _b, props = __objRest(_b, ["className", "children"]);
|
|
3516
|
+
const { isStreaming, isOpen, duration } = useReasoning();
|
|
3517
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
3518
|
+
CollapsibleTrigger,
|
|
3519
|
+
__spreadProps(__spreadValues({
|
|
3520
|
+
className: cn(
|
|
3521
|
+
"flex w-full items-center gap-2 text-muted-foreground text-sm transition-colors hover:text-foreground",
|
|
3522
|
+
className
|
|
3523
|
+
)
|
|
3524
|
+
}, props), {
|
|
3525
|
+
children: children != null ? children : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
3526
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.BrainIcon, { className: "size-4" }),
|
|
3527
|
+
getThinkingMessage(isStreaming, duration),
|
|
3528
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3529
|
+
lucideReact.ChevronDownIcon,
|
|
3530
|
+
{
|
|
3531
|
+
className: cn(
|
|
3532
|
+
"size-4 transition-transform",
|
|
3533
|
+
isOpen ? "rotate-180" : "rotate-0"
|
|
3534
|
+
)
|
|
3535
|
+
}
|
|
3536
|
+
)
|
|
3537
|
+
] })
|
|
3538
|
+
})
|
|
3539
|
+
);
|
|
3540
|
+
}
|
|
3541
|
+
);
|
|
3542
|
+
var ReasoningContent = React3.memo(
|
|
3543
|
+
(_a) => {
|
|
3544
|
+
var _b = _a, { className, children } = _b, props = __objRest(_b, ["className", "children"]);
|
|
3545
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
3546
|
+
CollapsibleContent,
|
|
3547
|
+
__spreadProps(__spreadValues({
|
|
3548
|
+
className: cn(
|
|
3549
|
+
"mt-4 text-sm",
|
|
3550
|
+
"data-[state=closed]:fade-out-0 data-[state=closed]:slide-out-to-top-2 data-[state=open]:slide-in-from-top-2 text-muted-foreground outline-none data-[state=closed]:animate-out data-[state=open]:animate-in",
|
|
3551
|
+
className
|
|
3552
|
+
)
|
|
3553
|
+
}, props), {
|
|
3554
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(Response, { className: "grid gap-2", children })
|
|
3555
|
+
})
|
|
3556
|
+
);
|
|
3557
|
+
}
|
|
3558
|
+
);
|
|
3559
|
+
Reasoning.displayName = "Reasoning";
|
|
3560
|
+
ReasoningTrigger.displayName = "ReasoningTrigger";
|
|
3561
|
+
ReasoningContent.displayName = "ReasoningContent";
|
|
3562
|
+
var Collapsible2 = React3__namespace.memo(
|
|
3563
|
+
React3__namespace.forwardRef(
|
|
3564
|
+
(props, ref) => {
|
|
3565
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Collapsible, __spreadValues({}, props));
|
|
3566
|
+
}
|
|
3567
|
+
)
|
|
3568
|
+
);
|
|
3569
|
+
Collapsible2.displayName = "Collapsible";
|
|
3570
|
+
var CollapsibleTrigger2 = React3__namespace.memo(
|
|
3571
|
+
React3__namespace.forwardRef(
|
|
3572
|
+
(props, ref) => {
|
|
3573
|
+
return /* @__PURE__ */ jsxRuntime.jsx(CollapsibleTrigger, __spreadValues({ ref }, props));
|
|
3574
|
+
}
|
|
3575
|
+
)
|
|
3576
|
+
);
|
|
3577
|
+
CollapsibleTrigger2.displayName = "CollapsibleTrigger";
|
|
3578
|
+
var CollapsibleContent2 = React3__namespace.memo(
|
|
3579
|
+
React3__namespace.forwardRef(
|
|
3580
|
+
(props, ref) => {
|
|
3581
|
+
return /* @__PURE__ */ jsxRuntime.jsx(CollapsibleContent, __spreadValues({ ref }, props));
|
|
3582
|
+
}
|
|
3583
|
+
)
|
|
3584
|
+
);
|
|
3585
|
+
CollapsibleContent2.displayName = "CollapsibleContent";
|
|
3586
|
+
var ReasoningDisplay = ({
|
|
3587
|
+
items,
|
|
3588
|
+
isStreaming = false,
|
|
3589
|
+
content,
|
|
3590
|
+
onToolAction
|
|
3591
|
+
}) => {
|
|
3592
|
+
if (items.length === 0 && !content) return null;
|
|
3593
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(Reasoning, { isStreaming, defaultOpen: false, children: [
|
|
3594
|
+
/* @__PURE__ */ jsxRuntime.jsx(ReasoningTrigger, {}),
|
|
3595
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
3596
|
+
CollapsibleContent2,
|
|
3597
|
+
{
|
|
3598
|
+
className: "mt-4 flex flex-col gap-2 data-[state=closed]:fade-out-0 data-[state=closed]:slide-out-to-top-2 data-[state=open]:slide-in-from-top-2 text-muted-foreground outline-none data-[state=closed]:animate-out data-[state=open]:animate-in",
|
|
3599
|
+
children: [
|
|
3600
|
+
content && content.trim() && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-4", children: /* @__PURE__ */ jsxRuntime.jsx(Response, { className: "grid gap-2", children: content }) }),
|
|
3601
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-2", children: items.map((item) => /* @__PURE__ */ jsxRuntime.jsx(ToolCallDisplay, { toolCall: item, onToolAction }, item.id)) })
|
|
3602
|
+
]
|
|
3603
|
+
}
|
|
3604
|
+
)
|
|
3605
|
+
] });
|
|
3606
|
+
};
|
|
3410
3607
|
var AIConversation = React3__namespace.memo(
|
|
3411
3608
|
(_a) => {
|
|
3412
3609
|
var _b = _a, {
|
|
@@ -3458,25 +3655,41 @@ var AIConversation = React3__namespace.memo(
|
|
|
3458
3655
|
}
|
|
3459
3656
|
if (message.role === "orchestrator") {
|
|
3460
3657
|
const subAgents = message.subAgents || [];
|
|
3461
|
-
const
|
|
3658
|
+
const allToolCalls = ((_a2 = message.toolCalls) == null ? void 0 : _a2.filter(
|
|
3462
3659
|
(tc) => tc.name !== "task" && tc.name !== "ask_user"
|
|
3463
3660
|
)) || [];
|
|
3464
|
-
const
|
|
3465
|
-
|
|
3661
|
+
const reasoningCalls = allToolCalls.filter((tc) => tc.visibility === "reasoning");
|
|
3662
|
+
const directToolCalls = allToolCalls.filter((tc) => tc.visibility !== "reasoning");
|
|
3663
|
+
contentStr.trim() !== "";
|
|
3664
|
+
const hasReasoning = reasoningCalls.length > 0;
|
|
3665
|
+
const reasoningText = hasReasoning ? contentStr : void 0;
|
|
3666
|
+
const displayContentStr = hasReasoning ? "" : contentStr;
|
|
3667
|
+
const hasDisplayContent = displayContentStr.trim() !== "";
|
|
3668
|
+
if (!hasDisplayContent && directToolCalls.length === 0 && reasoningCalls.length === 0 && subAgents.length === 0 && !message.isLoading) {
|
|
3466
3669
|
return null;
|
|
3467
3670
|
}
|
|
3671
|
+
const isStreaming = reasoningCalls.some((tc) => tc.status === "pending");
|
|
3468
3672
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3469
3673
|
OrchestratorMessage,
|
|
3470
3674
|
{
|
|
3471
3675
|
message: {
|
|
3472
3676
|
id: message.id,
|
|
3473
|
-
content:
|
|
3677
|
+
content: displayContentStr,
|
|
3474
3678
|
avatarSrc: message.avatarSrc,
|
|
3475
3679
|
avatarName: message.avatarName,
|
|
3476
|
-
isLoading: message.isLoading
|
|
3680
|
+
isLoading: message.isLoading && !hasReasoning
|
|
3477
3681
|
},
|
|
3478
|
-
showAvatar: showAvatars,
|
|
3682
|
+
showAvatar: showAvatars && hasDisplayContent,
|
|
3479
3683
|
children: [
|
|
3684
|
+
hasReasoning && /* @__PURE__ */ jsxRuntime.jsx(
|
|
3685
|
+
ReasoningDisplay,
|
|
3686
|
+
{
|
|
3687
|
+
content: reasoningText,
|
|
3688
|
+
items: reasoningCalls,
|
|
3689
|
+
isStreaming,
|
|
3690
|
+
onToolAction
|
|
3691
|
+
}
|
|
3692
|
+
),
|
|
3480
3693
|
directToolCalls.map((tc) => /* @__PURE__ */ jsxRuntime.jsx(ToolCallDisplay, { toolCall: tc, onToolAction }, tc.id)),
|
|
3481
3694
|
subAgents.map((subAgent) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
3482
3695
|
SpecialistMessage,
|
|
@@ -6475,30 +6688,6 @@ var ChartLegendContent2 = React3__namespace.memo(
|
|
|
6475
6688
|
})
|
|
6476
6689
|
);
|
|
6477
6690
|
ChartLegendContent2.displayName = "ChartLegendContent";
|
|
6478
|
-
var Collapsible2 = React3__namespace.memo(
|
|
6479
|
-
React3__namespace.forwardRef(
|
|
6480
|
-
(props, ref) => {
|
|
6481
|
-
return /* @__PURE__ */ jsxRuntime.jsx(Collapsible, __spreadValues({}, props));
|
|
6482
|
-
}
|
|
6483
|
-
)
|
|
6484
|
-
);
|
|
6485
|
-
Collapsible2.displayName = "Collapsible";
|
|
6486
|
-
var CollapsibleTrigger2 = React3__namespace.memo(
|
|
6487
|
-
React3__namespace.forwardRef(
|
|
6488
|
-
(props, ref) => {
|
|
6489
|
-
return /* @__PURE__ */ jsxRuntime.jsx(CollapsibleTrigger, __spreadValues({ ref }, props));
|
|
6490
|
-
}
|
|
6491
|
-
)
|
|
6492
|
-
);
|
|
6493
|
-
CollapsibleTrigger2.displayName = "CollapsibleTrigger";
|
|
6494
|
-
var CollapsibleContent2 = React3__namespace.memo(
|
|
6495
|
-
React3__namespace.forwardRef(
|
|
6496
|
-
(props, ref) => {
|
|
6497
|
-
return /* @__PURE__ */ jsxRuntime.jsx(CollapsibleContent, __spreadValues({ ref }, props));
|
|
6498
|
-
}
|
|
6499
|
-
)
|
|
6500
|
-
);
|
|
6501
|
-
CollapsibleContent2.displayName = "CollapsibleContent";
|
|
6502
6691
|
var Drawer = (_a) => {
|
|
6503
6692
|
var _b = _a, {
|
|
6504
6693
|
shouldScaleBackground = true
|
|
@@ -10824,15 +11013,32 @@ var FileTreeExplorer = React3__namespace.memo(
|
|
|
10824
11013
|
className
|
|
10825
11014
|
}) => {
|
|
10826
11015
|
const [searchQuery, setSearchQuery] = React3__namespace.useState("");
|
|
11016
|
+
const [userExpanded, setUserExpanded] = React3__namespace.useState(defaultExpanded || /* @__PURE__ */ new Set());
|
|
11017
|
+
React3__namespace.useEffect(() => {
|
|
11018
|
+
if (selectedPath) {
|
|
11019
|
+
const parts = selectedPath.split("/");
|
|
11020
|
+
if (parts.length > 1) {
|
|
11021
|
+
setUserExpanded((prev) => {
|
|
11022
|
+
const next = new Set(prev);
|
|
11023
|
+
let currentPath = "";
|
|
11024
|
+
for (let i = 0; i < parts.length - 1; i++) {
|
|
11025
|
+
currentPath += (i === 0 ? "" : "/") + parts[i];
|
|
11026
|
+
next.add(currentPath);
|
|
11027
|
+
}
|
|
11028
|
+
return next;
|
|
11029
|
+
});
|
|
11030
|
+
}
|
|
11031
|
+
}
|
|
11032
|
+
}, [selectedPath]);
|
|
10827
11033
|
const filteredTree = React3__namespace.useMemo(() => {
|
|
10828
11034
|
return filterTree(tree, searchQuery);
|
|
10829
11035
|
}, [tree, searchQuery]);
|
|
10830
|
-
const
|
|
11036
|
+
const activeExpanded = React3__namespace.useMemo(() => {
|
|
10831
11037
|
if (searchQuery) {
|
|
10832
11038
|
return getAllFolderPaths(filteredTree);
|
|
10833
11039
|
}
|
|
10834
|
-
return
|
|
10835
|
-
}, [searchQuery, filteredTree,
|
|
11040
|
+
return userExpanded;
|
|
11041
|
+
}, [searchQuery, filteredTree, userExpanded]);
|
|
10836
11042
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex flex-col rounded-lg border bg-background", className), children: [
|
|
10837
11043
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex items-center gap-2 border-b px-3 py-2", headerClassName), children: [
|
|
10838
11044
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex-1", children: [
|
|
@@ -10871,7 +11077,8 @@ var FileTreeExplorer = React3__namespace.memo(
|
|
|
10871
11077
|
FileTree,
|
|
10872
11078
|
{
|
|
10873
11079
|
className: "border-none bg-transparent",
|
|
10874
|
-
|
|
11080
|
+
expanded: activeExpanded,
|
|
11081
|
+
onExpandedChange: setUserExpanded,
|
|
10875
11082
|
selectedPath,
|
|
10876
11083
|
onSelect,
|
|
10877
11084
|
children: renderTree(filteredTree)
|