opencandle 0.8.0 → 0.10.0
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/cli-main.js +48 -24
- package/dist/cli-main.js.map +1 -1
- package/dist/pi/session-writer-lock.d.ts +30 -0
- package/dist/pi/session-writer-lock.js +111 -0
- package/dist/pi/session-writer-lock.js.map +1 -0
- package/dist/prompts/workflow-prompts.js +15 -0
- package/dist/prompts/workflow-prompts.js.map +1 -1
- package/dist/routing/classify-intent.js +8 -9
- package/dist/routing/classify-intent.js.map +1 -1
- package/dist/routing/entity-extractor.js +1 -1
- package/dist/routing/entity-extractor.js.map +1 -1
- package/dist/routing/router-llm-client.d.ts +1 -1
- package/dist/routing/router-llm-client.js +1 -1
- package/dist/routing/router-llm-client.js.map +1 -1
- package/dist/routing/router.js +37 -0
- package/dist/routing/router.js.map +1 -1
- package/dist/workflows/compare-assets.js +4 -1
- package/dist/workflows/compare-assets.js.map +1 -1
- package/gui/server/ask-user-bridge.ts +26 -19
- package/gui/server/chat-event-adapter.ts +49 -3
- package/gui/server/http-routes.ts +173 -15
- package/gui/server/invoke-tool.ts +102 -7
- package/gui/server/live-chat-event-adapter.ts +16 -4
- package/gui/server/server.ts +42 -5
- package/gui/server/session-actions.ts +7 -1
- package/gui/server/session-entry-wait.ts +79 -0
- package/gui/server/writer-lock.ts +1 -122
- package/gui/server/ws-hub.ts +25 -0
- package/gui/shared/chat-events.ts +42 -19
- package/gui/shared/event-reducer.ts +41 -26
- package/gui/web/dist/assets/CatalogOverlay-CYptsda-.js +1 -0
- package/gui/web/dist/assets/index-B7QAjY5g.js +65 -0
- package/gui/web/dist/assets/index-D5dbWPfM.css +2 -0
- package/gui/web/dist/index.html +2 -2
- package/package.json +16 -16
- package/src/cli-main.ts +64 -27
- package/src/pi/session-writer-lock.ts +156 -0
- package/src/prompts/workflow-prompts.ts +15 -0
- package/src/routing/classify-intent.ts +11 -11
- package/src/routing/entity-extractor.ts +1 -1
- package/src/routing/router-llm-client.ts +2 -1
- package/src/routing/router.ts +46 -0
- package/src/workflows/compare-assets.ts +4 -2
- package/gui/web/dist/assets/CatalogOverlay-CCVKwBUB.js +0 -1
- package/gui/web/dist/assets/index-Dm4Aom2_.js +0 -69
- package/gui/web/dist/assets/index-UzZUg3dx.css +0 -1
|
@@ -44,37 +44,56 @@ export interface Usage {
|
|
|
44
44
|
cost?: unknown;
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
+
interface ChatEventBase {
|
|
48
|
+
sessionId: string;
|
|
49
|
+
seq: number;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
interface RunScopedChatEventBase extends ChatEventBase {
|
|
53
|
+
runId: string;
|
|
54
|
+
}
|
|
55
|
+
|
|
47
56
|
export type ChatEvent =
|
|
48
|
-
| { type: "run.started"
|
|
49
|
-
| { type: "thinking.delta";
|
|
50
|
-
| { type: "thinking.completed";
|
|
51
|
-
| { type: "message.created"; messageId: string; role: ChatRole;
|
|
52
|
-
| { type: "message.delta"; messageId: string; text: string;
|
|
53
|
-
| {
|
|
54
|
-
|
|
57
|
+
| ({ type: "run.started" } & RunScopedChatEventBase)
|
|
58
|
+
| ({ type: "thinking.delta"; text: string } & RunScopedChatEventBase)
|
|
59
|
+
| ({ type: "thinking.completed"; text?: string } & RunScopedChatEventBase)
|
|
60
|
+
| ({ type: "message.created"; messageId: string; role: ChatRole; runId?: string } & ChatEventBase)
|
|
61
|
+
| ({ type: "message.delta"; messageId: string; text: string; runId?: string } & ChatEventBase)
|
|
62
|
+
| ({
|
|
63
|
+
type: "message.completed";
|
|
64
|
+
messageId: string;
|
|
65
|
+
content: MessageContent[];
|
|
66
|
+
runId?: string;
|
|
67
|
+
} & ChatEventBase)
|
|
68
|
+
| ({
|
|
55
69
|
type: "custom.message";
|
|
56
70
|
messageId: string;
|
|
57
71
|
customType: string;
|
|
58
72
|
content: MessageContent[];
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
| {
|
|
73
|
+
} & ChatEventBase)
|
|
74
|
+
| ({
|
|
62
75
|
type: "tool.started";
|
|
63
76
|
toolCallId: string;
|
|
64
77
|
messageId: string;
|
|
65
78
|
name: string;
|
|
66
79
|
input: unknown;
|
|
67
|
-
|
|
68
|
-
}
|
|
69
|
-
| { type: "tool.delta"; toolCallId: string; chunk: unknown;
|
|
70
|
-
| {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
80
|
+
runId?: string;
|
|
81
|
+
} & ChatEventBase)
|
|
82
|
+
| ({ type: "tool.delta"; toolCallId: string; chunk: unknown; runId?: string } & ChatEventBase)
|
|
83
|
+
| ({
|
|
84
|
+
type: "tool.completed";
|
|
85
|
+
toolCallId: string;
|
|
86
|
+
output: ToolOutput;
|
|
87
|
+
runId?: string;
|
|
88
|
+
} & ChatEventBase)
|
|
89
|
+
| ({ type: "tool.failed"; toolCallId: string; error: ToolError; runId?: string } & ChatEventBase)
|
|
90
|
+
| ({ type: "run.completed"; usage?: Usage } & RunScopedChatEventBase)
|
|
91
|
+
| ({ type: "run.failed"; error: RunError } & RunScopedChatEventBase)
|
|
92
|
+
| ({ type: "session.updated"; title?: string; updatedAt: string } & ChatEventBase);
|
|
75
93
|
|
|
76
94
|
export interface RenderMessage {
|
|
77
95
|
id: string;
|
|
96
|
+
sessionId?: string;
|
|
78
97
|
role: ChatRole;
|
|
79
98
|
status: "streaming" | "completed";
|
|
80
99
|
content: MessageContent[];
|
|
@@ -84,6 +103,7 @@ export interface RenderMessage {
|
|
|
84
103
|
|
|
85
104
|
export interface RenderToolCall {
|
|
86
105
|
id: string;
|
|
106
|
+
sessionId?: string;
|
|
87
107
|
messageId: string;
|
|
88
108
|
name: string;
|
|
89
109
|
input: unknown;
|
|
@@ -95,6 +115,7 @@ export interface RenderToolCall {
|
|
|
95
115
|
|
|
96
116
|
export interface RenderThinking {
|
|
97
117
|
runId: string;
|
|
118
|
+
sessionId?: string;
|
|
98
119
|
status: "streaming" | "completed";
|
|
99
120
|
text: string;
|
|
100
121
|
}
|
|
@@ -109,7 +130,8 @@ export interface ChatRunState {
|
|
|
109
130
|
|
|
110
131
|
export interface ChatRenderState {
|
|
111
132
|
lastSeq: number;
|
|
112
|
-
seenSeq: Set<
|
|
133
|
+
seenSeq: Set<string>;
|
|
134
|
+
lastSeqBySession: Map<string, number>;
|
|
113
135
|
messages: RenderMessage[];
|
|
114
136
|
messageById: Map<string, RenderMessage>;
|
|
115
137
|
tools: Map<string, RenderToolCall>;
|
|
@@ -123,6 +145,7 @@ export function createChatRenderState(): ChatRenderState {
|
|
|
123
145
|
return {
|
|
124
146
|
lastSeq: 0,
|
|
125
147
|
seenSeq: new Set(),
|
|
148
|
+
lastSeqBySession: new Map(),
|
|
126
149
|
messages: [],
|
|
127
150
|
messageById: new Map(),
|
|
128
151
|
tools: new Map(),
|
|
@@ -8,23 +8,26 @@ import {
|
|
|
8
8
|
|
|
9
9
|
export function reduceChatEvents(events: ChatEvent[]): ChatRenderState {
|
|
10
10
|
return [...events]
|
|
11
|
-
.sort((a, b) => a.seq - b.seq)
|
|
11
|
+
.sort((a, b) => (a.sessionId === b.sessionId ? a.seq - b.seq : 0))
|
|
12
12
|
.reduce((state, event) => applyChatEvent(state, event), createChatRenderState());
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
export function applyChatEvent(state: ChatRenderState, event: ChatEvent): ChatRenderState {
|
|
16
|
-
|
|
16
|
+
const eventKey = `${event.sessionId}:${event.seq}`;
|
|
17
|
+
if (state.seenSeq.has(eventKey)) return state;
|
|
17
18
|
|
|
18
19
|
const next = cloneState(state);
|
|
19
|
-
|
|
20
|
-
|
|
20
|
+
const sessionLastSeq = next.lastSeqBySession.get(event.sessionId) ?? 0;
|
|
21
|
+
if (event.seq > sessionLastSeq + 1 && sessionLastSeq !== 0) {
|
|
22
|
+
next.gaps.push({ expected: sessionLastSeq + 1, received: event.seq });
|
|
21
23
|
}
|
|
22
|
-
next.seenSeq.add(
|
|
24
|
+
next.seenSeq.add(eventKey);
|
|
25
|
+
next.lastSeqBySession.set(event.sessionId, Math.max(sessionLastSeq, event.seq));
|
|
23
26
|
next.lastSeq = Math.max(next.lastSeq, event.seq);
|
|
24
27
|
|
|
25
28
|
switch (event.type) {
|
|
26
29
|
case "run.started":
|
|
27
|
-
next.runs.set(event.runId, {
|
|
30
|
+
next.runs.set(scopedId(event.sessionId, event.runId), {
|
|
28
31
|
id: event.runId,
|
|
29
32
|
sessionId: event.sessionId,
|
|
30
33
|
status: "running",
|
|
@@ -33,25 +36,25 @@ export function applyChatEvent(state: ChatRenderState, event: ChatEvent): ChatRe
|
|
|
33
36
|
break;
|
|
34
37
|
|
|
35
38
|
case "thinking.delta": {
|
|
36
|
-
const thinking = ensureThinking(next, event.runId);
|
|
39
|
+
const thinking = ensureThinking(next, event.sessionId, event.runId);
|
|
37
40
|
thinking.status = "streaming";
|
|
38
41
|
thinking.text += event.text;
|
|
39
42
|
break;
|
|
40
43
|
}
|
|
41
44
|
|
|
42
45
|
case "thinking.completed": {
|
|
43
|
-
const thinking = ensureThinking(next, event.runId);
|
|
46
|
+
const thinking = ensureThinking(next, event.sessionId, event.runId);
|
|
44
47
|
thinking.status = "completed";
|
|
45
48
|
if (event.text !== undefined) thinking.text = event.text;
|
|
46
49
|
break;
|
|
47
50
|
}
|
|
48
51
|
|
|
49
52
|
case "message.created":
|
|
50
|
-
ensureMessage(next, event.messageId, event.role);
|
|
53
|
+
ensureMessage(next, event.sessionId, event.messageId, event.role);
|
|
51
54
|
break;
|
|
52
55
|
|
|
53
56
|
case "message.delta": {
|
|
54
|
-
const message = ensureMessage(next, event.messageId, "assistant");
|
|
57
|
+
const message = ensureMessage(next, event.sessionId, event.messageId, "assistant");
|
|
55
58
|
message.status = "streaming";
|
|
56
59
|
message.text += event.text;
|
|
57
60
|
message.content = [{ type: "text", text: message.text }];
|
|
@@ -59,7 +62,7 @@ export function applyChatEvent(state: ChatRenderState, event: ChatEvent): ChatRe
|
|
|
59
62
|
}
|
|
60
63
|
|
|
61
64
|
case "message.completed": {
|
|
62
|
-
const message = ensureMessage(next, event.messageId, "assistant");
|
|
65
|
+
const message = ensureMessage(next, event.sessionId, event.messageId, "assistant");
|
|
63
66
|
message.status = "completed";
|
|
64
67
|
message.content = event.content;
|
|
65
68
|
message.text = contentText(event.content);
|
|
@@ -67,7 +70,7 @@ export function applyChatEvent(state: ChatRenderState, event: ChatEvent): ChatRe
|
|
|
67
70
|
}
|
|
68
71
|
|
|
69
72
|
case "custom.message": {
|
|
70
|
-
const message = ensureMessage(next, event.messageId, "assistant");
|
|
73
|
+
const message = ensureMessage(next, event.sessionId, event.messageId, "assistant");
|
|
71
74
|
message.status = "completed";
|
|
72
75
|
message.content = event.content;
|
|
73
76
|
message.text = contentText(event.content);
|
|
@@ -76,9 +79,10 @@ export function applyChatEvent(state: ChatRenderState, event: ChatEvent): ChatRe
|
|
|
76
79
|
}
|
|
77
80
|
|
|
78
81
|
case "tool.started":
|
|
79
|
-
ensureMessage(next, event.messageId, "assistant");
|
|
80
|
-
next.tools.set(event.toolCallId, {
|
|
82
|
+
ensureMessage(next, event.sessionId, event.messageId, "assistant");
|
|
83
|
+
next.tools.set(scopedId(event.sessionId, event.toolCallId), {
|
|
81
84
|
id: event.toolCallId,
|
|
85
|
+
sessionId: event.sessionId,
|
|
82
86
|
messageId: event.messageId,
|
|
83
87
|
name: event.name,
|
|
84
88
|
input: event.input,
|
|
@@ -88,13 +92,13 @@ export function applyChatEvent(state: ChatRenderState, event: ChatEvent): ChatRe
|
|
|
88
92
|
break;
|
|
89
93
|
|
|
90
94
|
case "tool.delta": {
|
|
91
|
-
const tool = next.tools.get(event.toolCallId);
|
|
95
|
+
const tool = next.tools.get(scopedId(event.sessionId, event.toolCallId));
|
|
92
96
|
if (tool) tool.chunks.push(event.chunk);
|
|
93
97
|
break;
|
|
94
98
|
}
|
|
95
99
|
|
|
96
100
|
case "tool.completed": {
|
|
97
|
-
const tool = next.tools.get(event.toolCallId);
|
|
101
|
+
const tool = next.tools.get(scopedId(event.sessionId, event.toolCallId));
|
|
98
102
|
if (tool) {
|
|
99
103
|
tool.status = event.output.isError ? "failed" : "completed";
|
|
100
104
|
tool.output = event.output;
|
|
@@ -103,7 +107,7 @@ export function applyChatEvent(state: ChatRenderState, event: ChatEvent): ChatRe
|
|
|
103
107
|
}
|
|
104
108
|
|
|
105
109
|
case "tool.failed": {
|
|
106
|
-
const tool = next.tools.get(event.toolCallId);
|
|
110
|
+
const tool = next.tools.get(scopedId(event.sessionId, event.toolCallId));
|
|
107
111
|
if (tool) {
|
|
108
112
|
tool.status = "failed";
|
|
109
113
|
tool.error = event.error;
|
|
@@ -112,7 +116,7 @@ export function applyChatEvent(state: ChatRenderState, event: ChatEvent): ChatRe
|
|
|
112
116
|
}
|
|
113
117
|
|
|
114
118
|
case "run.completed": {
|
|
115
|
-
const run = next.runs.get(event.runId);
|
|
119
|
+
const run = next.runs.get(scopedId(event.sessionId, event.runId));
|
|
116
120
|
if (run) {
|
|
117
121
|
run.status = "completed";
|
|
118
122
|
run.usage = event.usage;
|
|
@@ -121,7 +125,7 @@ export function applyChatEvent(state: ChatRenderState, event: ChatEvent): ChatRe
|
|
|
121
125
|
}
|
|
122
126
|
|
|
123
127
|
case "run.failed": {
|
|
124
|
-
const run = next.runs.get(event.runId);
|
|
128
|
+
const run = next.runs.get(scopedId(event.sessionId, event.runId));
|
|
125
129
|
if (run) {
|
|
126
130
|
run.status = "failed";
|
|
127
131
|
run.error = event.error;
|
|
@@ -143,20 +147,23 @@ export function applyChatEvent(state: ChatRenderState, event: ChatEvent): ChatRe
|
|
|
143
147
|
|
|
144
148
|
function ensureMessage(
|
|
145
149
|
state: ChatRenderState,
|
|
150
|
+
sessionId: string,
|
|
146
151
|
id: string,
|
|
147
152
|
role: RenderMessage["role"],
|
|
148
153
|
): RenderMessage {
|
|
149
|
-
const
|
|
154
|
+
const key = scopedId(sessionId, id);
|
|
155
|
+
const existing = state.messageById.get(key);
|
|
150
156
|
if (existing) return existing;
|
|
151
157
|
|
|
152
158
|
const message: RenderMessage = {
|
|
153
159
|
id,
|
|
160
|
+
sessionId,
|
|
154
161
|
role,
|
|
155
162
|
status: "streaming",
|
|
156
163
|
content: [],
|
|
157
164
|
text: "",
|
|
158
165
|
};
|
|
159
|
-
state.messageById.set(
|
|
166
|
+
state.messageById.set(key, message);
|
|
160
167
|
state.messages.push(message);
|
|
161
168
|
return message;
|
|
162
169
|
}
|
|
@@ -166,10 +173,13 @@ function cloneState(state: ChatRenderState): ChatRenderState {
|
|
|
166
173
|
...message,
|
|
167
174
|
content: [...message.content],
|
|
168
175
|
}));
|
|
169
|
-
const messageById = new Map(
|
|
176
|
+
const messageById = new Map(
|
|
177
|
+
messages.map((message) => [scopedId(message.sessionId ?? "", message.id), message]),
|
|
178
|
+
);
|
|
170
179
|
return {
|
|
171
180
|
...state,
|
|
172
181
|
seenSeq: new Set(state.seenSeq),
|
|
182
|
+
lastSeqBySession: new Map(state.lastSeqBySession),
|
|
173
183
|
messages,
|
|
174
184
|
messageById,
|
|
175
185
|
tools: new Map(
|
|
@@ -188,14 +198,19 @@ function cloneState(state: ChatRenderState): ChatRenderState {
|
|
|
188
198
|
};
|
|
189
199
|
}
|
|
190
200
|
|
|
191
|
-
function ensureThinking(state: ChatRenderState, runId: string) {
|
|
192
|
-
const
|
|
201
|
+
function ensureThinking(state: ChatRenderState, sessionId: string, runId: string) {
|
|
202
|
+
const key = scopedId(sessionId, runId);
|
|
203
|
+
const existing = state.thinking.get(key);
|
|
193
204
|
if (existing) return existing;
|
|
194
|
-
const thinking = { runId, status: "streaming" as const, text: "" };
|
|
195
|
-
state.thinking.set(
|
|
205
|
+
const thinking = { runId, sessionId, status: "streaming" as const, text: "" };
|
|
206
|
+
state.thinking.set(key, thinking);
|
|
196
207
|
return thinking;
|
|
197
208
|
}
|
|
198
209
|
|
|
210
|
+
function scopedId(sessionId: string, id: string): string {
|
|
211
|
+
return `${sessionId ?? ""}::${id}`;
|
|
212
|
+
}
|
|
213
|
+
|
|
199
214
|
function contentText(content: MessageContent[]): string {
|
|
200
215
|
return content
|
|
201
216
|
.filter((part): part is Extract<MessageContent, { type: "text" }> => part.type === "text")
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{_ as e,a as t,c as n,d as r,f as i,g as a,h as o,i as s,l as c,m as l,n as u,o as d,p as f,r as p,s as m,t as h,u as g,v as _,y as v}from"./index-B7QAjY5g.js";var y=o(`earth`,[[`path`,{d:`M21.54 15H17a2 2 0 0 0-2 2v4.54`,key:`1djwo0`}],[`path`,{d:`M7 3.34V5a3 3 0 0 0 3 3a2 2 0 0 1 2 2c0 1.1.9 2 2 2a2 2 0 0 0 2-2c0-1.1.9-2 2-2h3.17`,key:`1tzkfa`}],[`path`,{d:`M11 21.95V18a2 2 0 0 0-2-2a2 2 0 0 1-2-2v-1a2 2 0 0 0-2-2H2.05`,key:`14pb5j`}],[`circle`,{cx:`12`,cy:`12`,r:`10`,key:`1mglay`}]]),b=o(`sparkles`,[[`path`,{d:`M11.017 2.814a1 1 0 0 1 1.966 0l1.051 5.558a2 2 0 0 0 1.594 1.594l5.558 1.051a1 1 0 0 1 0 1.966l-5.558 1.051a2 2 0 0 0-1.594 1.594l-1.051 5.558a1 1 0 0 1-1.966 0l-1.051-5.558a2 2 0 0 0-1.594-1.594l-5.558-1.051a1 1 0 0 1 0-1.966l5.558-1.051a2 2 0 0 0 1.594-1.594z`,key:`1s2grr`}],[`path`,{d:`M20 2v4`,key:`1rf3ol`}],[`path`,{d:`M22 4h-4`,key:`gwowj6`}],[`circle`,{cx:`4`,cy:`20`,r:`2`,key:`6kqj1y`}]]),x=o(`arrow-right`,[[`path`,{d:`M5 12h14`,key:`1ays0h`}],[`path`,{d:`m12 5 7 7-7 7`,key:`xquz4c`}]]),S=o(`chevron-left`,[[`path`,{d:`m15 18-6-6 6-6`,key:`1wnfg3`}]]),ee=o(`clipboard`,[[`rect`,{width:`8`,height:`4`,x:`8`,y:`2`,rx:`1`,ry:`1`,key:`tgr4d6`}],[`path`,{d:`M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2`,key:`116196`}]]),te=o(`eye-off`,[[`path`,{d:`M10.733 5.076a10.744 10.744 0 0 1 11.205 6.575 1 1 0 0 1 0 .696 10.747 10.747 0 0 1-1.444 2.49`,key:`ct8e1f`}],[`path`,{d:`M14.084 14.158a3 3 0 0 1-4.242-4.242`,key:`151rxh`}],[`path`,{d:`M17.479 17.499a10.75 10.75 0 0 1-15.417-5.151 1 1 0 0 1 0-.696 10.75 10.75 0 0 1 4.446-5.143`,key:`13bj9a`}],[`path`,{d:`m2 2 20 20`,key:`1ooewy`}]]),ne=o(`eye`,[[`path`,{d:`M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0`,key:`1nclc0`}],[`circle`,{cx:`12`,cy:`12`,r:`3`,key:`1v7zrd`}]]),C=o(`play`,[[`path`,{d:`M5 5a2 2 0 0 1 3.008-1.728l11.997 6.998a2 2 0 0 1 .003 3.458l-12 7A2 2 0 0 1 5 19z`,key:`10ikf1`}]]),w=o(`terminal`,[[`path`,{d:`M12 19h8`,key:`baeox8`}],[`path`,{d:`m4 17 6-6-6-6`,key:`1yngyt`}]]),T=v(_(),1),re=[{value:`1mo`,label:`1M`},{value:`3mo`,label:`3M`},{value:`6mo`,label:`6M`},{value:`1y`,label:`1Y`},{value:`2y`,label:`2Y`},{value:`5y`,label:`5Y`},{value:`max`,label:`Max`}],ie=[{value:`6mo`,label:`6M`},{value:`1y`,label:`1Y`},{value:`2y`,label:`2Y`}],ae=[{value:`hours`,label:`Hours`},{value:`day`,label:`Day`},{value:`week`,label:`Week`},{value:`month`,label:`Month`}],E=[{value:6,label:`6h`},{value:24,label:`24h`},{value:72,label:`3d`},{value:168,label:`7d`}],D=[{value:7,label:`7d`},{value:30,label:`30d`},{value:90,label:`90d`},{value:180,label:`6M`},{value:365,label:`1Y`}],O=e();function k({label:e,hint:t,required:n=!1,children:r,className:i}){return(0,O.jsxs)(`label`,{className:a(`grid gap-1.5`,i),children:[(0,O.jsxs)(`span`,{className:`flex items-baseline justify-between gap-3 text-xs font-medium text-foreground`,children:[(0,O.jsxs)(`span`,{children:[e,n?(0,O.jsxs)(`span`,{className:`text-foreground/40`,"aria-hidden":`true`,children:[` `,`*`]}):null]}),t?(0,O.jsx)(`span`,{className:`text-[11px] font-normal text-muted-foreground`,children:t}):null]}),r]})}function oe({value:e,onChange:t,options:n,ariaLabel:r}){return(0,O.jsx)(`div`,{role:`radiogroup`,"aria-label":r,className:`inline-flex h-9 items-center rounded-md border border-border bg-card p-0.5`,children:n.map(n=>{let r=n.value===e;return(0,O.jsx)(`button`,{type:`button`,role:`radio`,"aria-checked":r,onClick:()=>t(n.value),className:a(`inline-flex h-8 min-w-9 items-center justify-center rounded-[4px] px-2.5 text-xs font-medium tabular-nums transition-colors`,r?`bg-foreground text-background`:`text-muted-foreground hover:text-foreground`),children:n.label},n.value)})})}function se({value:e,onChange:t,options:n,placeholder:r,ariaLabel:i}){return(0,O.jsxs)(`div`,{className:`relative`,children:[(0,O.jsxs)(`select`,{"aria-label":i,value:e??``,onChange:e=>t(e.target.value||void 0),className:`h-9 w-full appearance-none rounded-md border border-border bg-card px-3 pr-9 text-sm text-foreground transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background`,children:[r?(0,O.jsx)(`option`,{value:``,disabled:!0,hidden:!0,children:r}):null,n.map(e=>(0,O.jsx)(`option`,{value:e.value,children:e.label},e.value))]}),(0,O.jsx)(f,{"aria-hidden":`true`,className:`pointer-events-none absolute right-2.5 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground`})]})}function ce({value:e,onChange:t,presets:n,suffix:r,min:i,max:o,step:s=1,placeholder:c}){let l=n.some(t=>t.value===e);return(0,O.jsxs)(`div`,{className:`grid gap-2`,children:[(0,O.jsx)(`div`,{className:`flex flex-wrap items-center gap-1.5`,children:n.map(n=>(0,O.jsx)(`button`,{type:`button`,onClick:()=>t(n.value),className:a(`inline-flex h-7 items-center rounded-full border px-2.5 text-xs font-medium tabular-nums transition-colors`,n.value===e?`border-foreground bg-foreground text-background`:`border-border bg-card text-muted-foreground hover:border-border hover:text-foreground`),children:n.label},String(n.value)))}),(0,O.jsxs)(`div`,{className:`relative w-32`,children:[(0,O.jsx)(p,{type:`number`,inputMode:`numeric`,value:l?``:e??``,min:i,max:o,step:s,placeholder:c??`Custom`,onChange:e=>{t(e.target.value===``?void 0:Number(e.target.value))},className:`h-8 pr-8 text-xs tabular-nums`}),r?(0,O.jsx)(`span`,{className:`pointer-events-none absolute right-2 top-1/2 -translate-y-1/2 text-[11px] text-muted-foreground`,children:r}):null]})]})}function le({value:e,onChange:t,lookup:n,placeholder:r=`AAPL`,ariaLabel:i}){let[a,o]=(0,T.useState)(!1),[s,c]=(0,T.useState)({query:``,items:[]}),[l,u]=(0,T.useState)(``),d=(0,T.useRef)(null),f=String(e||``).trim(),m=s.query===f?s.items:[],h=l===f&&f.length>0;return(0,T.useEffect)(()=>{if(n&&!(f.length<1))return d.current&&clearTimeout(d.current),d.current=setTimeout(async()=>{u(f);try{c({query:f,items:(await n(f)).slice(0,6)})}catch{c({query:f,items:[]})}finally{u(e=>e===f?``:e)}},180),()=>{d.current&&clearTimeout(d.current)}},[f,n]),(0,O.jsxs)(`div`,{className:`relative`,children:[(0,O.jsx)(p,{"aria-label":i,value:e??``,placeholder:r,onChange:e=>t(e.target.value.toUpperCase()),onFocus:()=>o(!0),onBlur:()=>setTimeout(()=>o(!1),120),className:`h-9 tabular-nums`,autoCapitalize:`characters`}),a&&m.length>0?(0,O.jsx)(`div`,{className:`absolute left-0 right-0 top-full z-20 mt-1 max-h-60 overflow-auto rounded-md border border-border bg-card shadow-subtle-sm`,children:m.map(e=>(0,O.jsxs)(`button`,{type:`button`,onMouseDown:e=>e.preventDefault(),onClick:()=>{t(e.symbol),o(!1)},className:`flex w-full items-center justify-between gap-3 px-3 py-2 text-left text-sm hover:bg-secondary`,children:[(0,O.jsx)(`span`,{className:`font-medium tabular-nums text-foreground`,children:e.symbol}),(0,O.jsx)(`span`,{className:`truncate text-xs text-muted-foreground`,children:e.name})]},e.symbol))}):null,h?(0,O.jsx)(`span`,{className:`absolute right-3 top-1/2 -translate-y-1/2 text-[10px] uppercase tracking-wider text-muted-foreground`,children:`…`}):null]})}function ue({value:e=[],onChange:n,placeholder:r=`Add ticker`,min:i,max:a,ariaLabel:o=`Ticker symbols`}){let[s,c]=(0,T.useState)(``),l=a!=null&&e.length>=a,u=()=>{let t=s.trim().toUpperCase();if(t){if(e.includes(t)){c(``);return}l||(n([...e,t]),c(``))}},f=t=>n(e.filter(e=>e!==t));return(0,O.jsxs)(`div`,{children:[(0,O.jsxs)(`div`,{className:`flex min-h-9 flex-wrap items-center gap-1.5 rounded-md border border-border bg-card px-2 py-1.5 focus-within:ring-2 focus-within:ring-ring focus-within:ring-offset-2 focus-within:ring-offset-background`,children:[e.map(e=>(0,O.jsxs)(`span`,{className:`inline-flex items-center gap-1 rounded-md border border-border bg-secondary px-1.5 py-0.5 text-xs font-medium tabular-nums text-foreground`,children:[e,(0,O.jsx)(`button`,{type:`button`,"aria-label":`Remove ${e}`,onClick:()=>f(e),className:`text-muted-foreground hover:text-foreground`,children:(0,O.jsx)(d,{className:`h-3 w-3`})})]},e)),(0,O.jsx)(`input`,{"aria-label":o,value:s,onChange:e=>c(e.target.value.toUpperCase()),onKeyDown:t=>{t.key===`Enter`||t.key===`,`?(t.preventDefault(),u()):t.key===`Backspace`&&!s&&e.length>0&&(t.preventDefault(),n(e.slice(0,-1)))},placeholder:e.length===0?r:``,disabled:l,className:`min-w-[80px] flex-1 bg-transparent py-1 text-xs tabular-nums text-foreground outline-none placeholder:text-muted-foreground disabled:opacity-40`,autoCapitalize:`characters`}),s.trim()?(0,O.jsx)(t,{type:`button`,variant:`ghost`,size:`icon-xs`,"aria-label":`Add ticker`,onClick:u,children:(0,O.jsx)(g,{})}):null]}),i!=null&&e.length<i?(0,O.jsxs)(`p`,{className:`mt-1 text-[11px] text-muted-foreground`,children:[`Add at least `,i,` symbol`,i===1?``:`s`,`.`]}):null,a==null?null:(0,O.jsxs)(`p`,{className:`mt-1 text-[11px] text-muted-foreground tabular-nums`,children:[e.length,`/`,a]})]})}function de({value:e=[],onChange:t,options:n}){let r=n=>{e.includes(n)?t(e.filter(e=>e!==n)):t([...e,n])};return(0,O.jsx)(`div`,{className:`flex flex-wrap gap-1.5`,children:n.map(t=>{let n=e.includes(t.value);return(0,O.jsxs)(`button`,{type:`button`,onClick:()=>r(t.value),className:a(`inline-flex h-7 items-center gap-1 rounded-full border px-2.5 text-xs font-medium transition-colors`,n?`border-foreground bg-foreground text-background`:`border-border bg-card text-muted-foreground hover:text-foreground`),children:[n?(0,O.jsx)(l,{className:`h-3 w-3`,"aria-hidden":`true`}):null,t.label]},t.value)})})}function fe({value:e,onChange:t,min:n,max:r,placeholder:i=`YYYY-MM-DD`}){return(0,O.jsx)(p,{type:`date`,value:e??``,min:n,max:r,placeholder:i,onChange:e=>t(e.target.value||void 0),className:`h-9 tabular-nums`})}function pe({value:e,onChange:t,placeholder:n,rows:r=3,maxLength:i,ariaLabel:a=`Text input`}){return(0,O.jsxs)(`div`,{children:[(0,O.jsx)(`textarea`,{"aria-label":a,value:e??``,onChange:e=>t(e.target.value),placeholder:n,maxLength:i,rows:r,className:`block w-full resize-y rounded-md border border-border bg-card px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background`}),i?(0,O.jsxs)(`div`,{className:`mt-1 text-right text-[11px] tabular-nums text-muted-foreground`,children:[(e||``).length,`/`,i]}):null]})}function me({value:e,onChange:t,currency:n=`USD`,min:r=0,placeholder:i=`0`}){let[a,o]=(0,T.useState)(!1),[s,c]=(0,T.useState)(A(e,!1));(0,T.useEffect)(()=>{a||c(A(e,!1))},[e,a]);let l=he(n),u=e=>{if(o(!1),!e||!e.replace(/[^0-9.]/g,``)){t(void 0),c(``);return}let n=Number(e.replace(/[^0-9.]/g,``));Number.isFinite(n)&&(t(n),c(A(n,!1)))};return(0,O.jsxs)(`div`,{className:`relative`,children:[(0,O.jsx)(`span`,{className:`pointer-events-none absolute left-3 top-1/2 -translate-y-1/2 text-sm text-muted-foreground`,children:l}),(0,O.jsx)(p,{value:a?s:A(e,!1),inputMode:`decimal`,placeholder:i,onChange:e=>c(e.target.value.replace(/[^0-9.]/g,``)),onFocus:()=>{o(!0),c(e==null?``:String(e))},onBlur:e=>u(e.target.value),min:r,className:`h-9 pl-7 tabular-nums`})]})}function A(e,t){if(e==null||e===``)return``;let n=Number(e);return Number.isFinite(n)?t?String(n):n.toLocaleString(`en-US`):String(e)}function he(e){return!e||e===`USD`||e===`CAD`||e===`AUD`?`$`:e===`EUR`?`€`:e===`GBP`?`£`:e===`JPY`?`¥`:e}function ge({value:e,onChange:t,min:n,max:r,step:i=.5,placeholder:a}){return(0,O.jsxs)(`div`,{className:`relative`,children:[(0,O.jsx)(p,{type:`number`,inputMode:`decimal`,value:e==null||e===``?``:String(Number((Number(e)*100).toFixed(4))),placeholder:a,min:n,max:r,step:i,onChange:e=>{let n=e.target.value;if(n===``){t(void 0);return}let r=Number(n);Number.isFinite(r)&&t(r/100)},className:`h-9 pr-7 tabular-nums`}),(0,O.jsx)(`span`,{className:`pointer-events-none absolute right-3 top-1/2 -translate-y-1/2 text-sm text-muted-foreground`,children:`%`})]})}function _e({suggestions:e,onPick:t,label:n=`Suggestions`}){return e?.length?(0,O.jsxs)(`div`,{className:`grid gap-1.5`,children:[(0,O.jsx)(`span`,{className:`text-[11px] font-medium uppercase tracking-wider text-muted-foreground`,children:n}),(0,O.jsx)(`div`,{className:`flex flex-wrap gap-1.5`,children:e.map(e=>(0,O.jsx)(`button`,{type:`button`,onClick:()=>t(e.value||e.label),className:`inline-flex h-7 items-center rounded-full border border-border bg-card px-2.5 text-xs font-medium text-muted-foreground transition-colors hover:text-foreground`,children:e.label},e.value||e.label))})]}):null}var ve={DAYS_PRESETS:D,HOURS_PRESETS:E,RANGE_OPTIONS:re,PERIOD_OPTIONS:ie,FRESHNESS_OPTIONS:ae};function j(e){return typeof e==`string`?ve[e]??[]:e??[]}function M({field:e,value:t,onChange:n,lookupSymbol:r}){let i=t=>n(e.name,t);switch(e.label,e.required,e.helper&&e.helper,e.kind){case`symbol`:return(0,O.jsx)(k,{label:e.label,hint:e.helper,required:e.required,children:(0,O.jsx)(le,{value:t,onChange:i,lookup:r,placeholder:e.placeholder,ariaLabel:e.label})});case`symbols`:return(0,O.jsx)(k,{label:e.label,hint:e.helper,required:e.required,children:(0,O.jsx)(ue,{value:t||[],onChange:i,min:e.min,max:e.max,placeholder:e.placeholder,ariaLabel:e.label})});case`segmented`:return(0,O.jsx)(k,{label:e.label,hint:e.helper,required:e.required,children:(0,O.jsx)(oe,{value:t,onChange:i,options:j(e.options),ariaLabel:e.label})});case`select`:return(0,O.jsx)(k,{label:e.label,hint:e.helper,required:e.required,children:(0,O.jsx)(se,{value:t,onChange:i,options:j(e.options),placeholder:e.placeholder,ariaLabel:e.label})});case`number-chips`:return(0,O.jsx)(k,{label:e.label,hint:e.helper,required:e.required,children:(0,O.jsx)(ce,{value:t,onChange:i,presets:j(e.presets),suffix:e.suffix,min:e.min,max:e.max,step:e.step,placeholder:e.placeholder})});case`multi-chips`:return(0,O.jsx)(k,{label:e.label,hint:e.helper,required:e.required,children:(0,O.jsx)(de,{value:t||[],onChange:i,options:j(e.options)})});case`date`:return(0,O.jsx)(k,{label:e.label,hint:e.helper,required:e.required,children:(0,O.jsx)(fe,{value:t,onChange:i,min:e.min,max:e.max})});case`freetext`:return(0,O.jsx)(k,{label:e.label,hint:e.helper,required:e.required,children:(0,O.jsx)(pe,{value:t,onChange:i,placeholder:e.placeholder,maxLength:e.maxLength,rows:e.rows,ariaLabel:e.label})});case`money`:return(0,O.jsx)(k,{label:e.label,hint:e.helper,required:e.required,children:(0,O.jsx)(me,{value:t,onChange:i,currency:e.currency,placeholder:e.placeholder})});case`percent`:return(0,O.jsx)(k,{label:e.label,hint:e.helper,required:e.required,children:(0,O.jsx)(ge,{value:t,onChange:i,min:e.min,max:e.max,step:e.step,placeholder:e.placeholder})});default:return(0,O.jsxs)(k,{label:e.label,hint:e.helper,required:e.required,children:[(0,O.jsx)(p,{value:t??``,placeholder:e.placeholder,onChange:e=>i(e.target.value),className:`h-9`}),e.suggestions?.length?(0,O.jsx)(`div`,{className:`mt-2`,children:(0,O.jsx)(_e,{suggestions:e.suggestions,onPick:i,label:`Try`})}):null]})}}function N(e){let t={};for(let n of e)n.default!==void 0&&(t[n.name]=n.default);return t}function P(e,t){let n=[];for(let r of e){if(!r.required)continue;let e=t[r.name];if(e==null||e===``){n.push(`${r.label} is required.`);continue}Array.isArray(e)&&(e.length===0?n.push(`${r.label} is required.`):r.min!=null&&e.length<r.min&&n.push(`${r.label} needs at least ${r.min} entr${r.min===1?`y`:`ies`}.`))}return n}var F=(e={})=>({name:`symbol`,kind:`symbol`,label:`Symbol`,required:!0,default:`NVDA`,placeholder:`AAPL`,...e}),I=(e={})=>({name:`query`,kind:`text`,label:`Ticker or topic`,required:!0,placeholder:`AAPL or AI infrastructure`,...e}),ye={search_ticker:[{name:`query`,kind:`text`,label:`Search query`,required:!0,placeholder:`apple, AAPL, ethereum…`,helper:`Company name, ticker, or crypto. Returns the best matches.`}],get_stock_quote:[F()],get_stock_history:[F(),{name:`range`,kind:`segmented`,label:`Range`,default:`6mo`,options:`RANGE_OPTIONS`},{name:`interval`,kind:`select`,label:`Interval`,default:`1d`,options:[{value:`1d`,label:`Daily`},{value:`1wk`,label:`Weekly`},{value:`1mo`,label:`Monthly`},{value:`1h`,label:`Hourly`},{value:`5m`,label:`5 min`}]}],get_crypto_price:[{name:`id`,kind:`text`,label:`Coin ID`,required:!0,default:`bitcoin`,placeholder:`bitcoin, ethereum, solana`,helper:`CoinGecko coin id (lowercase, hyphenated).`}],get_crypto_history:[{name:`id`,kind:`text`,label:`Coin ID`,required:!0,default:`bitcoin`,placeholder:`bitcoin`,helper:`CoinGecko coin id.`},{name:`days`,kind:`number-chips`,label:`History window`,default:180,presets:`DAYS_PRESETS`,suffix:`days`,helper:`1, 7, 14, 30, 90, 180, 365, or 'max'.`}],get_company_overview:[F()],get_financials:[F(),{name:`statement`,kind:`select`,label:`Statement`,default:`income`,options:[{value:`income`,label:`Income statement`},{value:`balance`,label:`Balance sheet`},{value:`cashflow`,label:`Cash flow`}]}],get_earnings:[F()],calculate_dcf:[F(),{name:`growth_rate`,kind:`percent`,label:`FCF growth rate`,helper:`Annual. Estimated from history if blank.`},{name:`discount_rate`,kind:`percent`,label:`Discount rate (WACC)`,default:.1,helper:`Default 10%.`},{name:`terminal_growth`,kind:`percent`,label:`Terminal growth`,default:.03,helper:`Default 3%.`},{name:`projection_years`,kind:`number-chips`,label:`Projection years`,default:5,presets:[{value:3,label:`3y`},{value:5,label:`5y`},{value:7,label:`7y`},{value:10,label:`10y`}],suffix:`yrs`}],compare_companies:[{name:`symbols`,kind:`symbols`,label:`Tickers`,required:!0,min:2,max:6,default:[`AAPL`,`MSFT`,`GOOGL`],helper:`Pick 2 to 6 tickers to compare side by side.`}],get_sec_filings:[F(),{name:`form_types`,kind:`multi-chips`,label:`Filing types`,default:[`10-K`,`10-Q`,`8-K`],options:[{value:`10-K`,label:`10-K (annual)`},{value:`10-Q`,label:`10-Q (quarterly)`},{value:`8-K`,label:`8-K (material)`},{value:`S-1`,label:`S-1`},{value:`DEF 14A`,label:`Proxy (DEF 14A)`}]},{name:`limit`,kind:`number-chips`,label:`Max results`,default:10,presets:[{value:5,label:`5`},{value:10,label:`10`},{value:25,label:`25`},{value:50,label:`50`}]}],get_economic_data:[{name:`series_id`,kind:`text`,label:`FRED series`,required:!0,default:`CPIAUCSL`,placeholder:`CPIAUCSL`,helper:`Common: CPIAUCSL (CPI), DGS10 (10Y), UNRATE (unemployment), FEDFUNDS.`,suggestions:[{value:`CPIAUCSL`,label:`CPI`},{value:`DGS10`,label:`10Y Treasury`},{value:`UNRATE`,label:`Unemployment`},{value:`FEDFUNDS`,label:`Fed Funds`},{value:`GDP`,label:`GDP`}]},{name:`limit`,kind:`number-chips`,label:`Observations`,default:30,presets:[{value:12,label:`12`},{value:30,label:`30`},{value:60,label:`60`},{value:120,label:`120`}]}],get_fear_greed:[],get_technical_indicators:[F(),{name:`range`,kind:`segmented`,label:`Range`,default:`1y`,options:[{value:`3mo`,label:`3M`},{value:`6mo`,label:`6M`},{value:`1y`,label:`1Y`},{value:`2y`,label:`2Y`}]}],backtest_strategy:[F(),{name:`strategy`,kind:`select`,label:`Strategy`,required:!0,default:`sma_crossover`,options:[{value:`sma_crossover`,label:`SMA crossover (20/50)`},{value:`rsi_mean_reversion`,label:`RSI mean reversion (30/70)`}]},{name:`period`,kind:`segmented`,label:`Lookback`,default:`2y`,options:[{value:`1y`,label:`1Y`},{value:`2y`,label:`2Y`},{value:`5y`,label:`5Y`}]}],manage_portfolio:[{name:`action`,kind:`segmented`,label:`Action`,required:!0,default:`check`,options:[{value:`add`,label:`Add`},{value:`remove`,label:`Remove`},{value:`check`,label:`Check`},{value:`list`,label:`List`}]},F({required:!1,helper:`Required for add/remove.`}),{name:`shares`,kind:`number-chips`,label:`Shares`,presets:[{value:10,label:`10`},{value:100,label:`100`},{value:500,label:`500`}],helper:`Required when adding a position.`},{name:`avg_cost`,kind:`money`,label:`Average cost basis`,helper:`Per share, in your portfolio currency.`}],watchlist:[{name:`action`,kind:`segmented`,label:`Action`,required:!0,default:`check`,options:[{value:`add`,label:`Add`},{value:`remove`,label:`Remove`},{value:`check`,label:`Check`}]},F({required:!1}),{name:`target_price`,kind:`money`,label:`Target (alert ↑)`},{name:`stop_price`,kind:`money`,label:`Stop (alert ↓)`}],analyze_correlation:[{name:`symbols`,kind:`symbols`,label:`Tickers`,required:!0,min:2,max:12,default:[`SPY`,`QQQ`,`TLT`],helper:`2 or more tickers.`},{name:`period`,kind:`segmented`,label:`Window`,default:`1y`,options:`PERIOD_OPTIONS`}],analyze_risk:[F(),{name:`period`,kind:`segmented`,label:`Window`,default:`1y`,options:`PERIOD_OPTIONS`}],predict_returns:[{name:`symbols`,kind:`symbols`,label:`Tickers`,required:!0,min:1,max:8,default:[`NVDA`,`AAPL`],helper:`Forecast 1-week and 1-month return ranges.`}],get_option_chain:[F(),{name:`expiration`,kind:`date`,label:`Expiration`,helper:`Defaults to nearest expiration.`},{name:`type`,kind:`segmented`,label:`Type`,options:[{value:``,label:`Both`},{value:`call`,label:`Calls`},{value:`put`,label:`Puts`}]}],get_reddit_sentiment:[{name:`subreddit`,kind:`text`,label:`Subreddit`,placeholder:`wallstreetbets, stocks, all`,helper:`Leave blank to search defaults.`},{name:`query`,kind:`text`,label:`Filter query`,placeholder:`AAPL or 'rate cuts'`}],get_twitter_sentiment:[I(),{name:`limit`,kind:`number-chips`,label:`Tweets`,default:50,presets:[{value:25,label:`25`},{value:50,label:`50`},{value:100,label:`100`},{value:200,label:`200`}]},{name:`hours`,kind:`number-chips`,label:`Lookback`,default:24,presets:`HOURS_PRESETS`,suffix:`hr`}],get_web_search:[I({label:`Search query`}),{name:`category`,kind:`segmented`,label:`Category`,default:`news`,options:[{value:`news`,label:`News`},{value:`general`,label:`General`}]},{name:`freshness`,kind:`segmented`,label:`Freshness`,default:`day`,options:`FRESHNESS_OPTIONS`}],get_web_sentiment:[I(),{name:`freshness`,kind:`segmented`,label:`Freshness`,default:`day`,options:`FRESHNESS_OPTIONS`},{name:`limit`,kind:`number-chips`,label:`Articles`,default:10,presets:[{value:5,label:`5`},{value:10,label:`10`},{value:20,label:`20`}]}],get_sentiment_trend:[I(),{name:`days`,kind:`number-chips`,label:`Days of history`,default:7,presets:[{value:3,label:`3d`},{value:7,label:`7d`},{value:14,label:`14d`},{value:30,label:`30d`}]},{name:`source`,kind:`select`,label:`Source`,placeholder:`All sources`,options:[{value:`twitter`,label:`Twitter`},{value:`reddit`,label:`Reddit`},{value:`web`,label:`Web`},{value:`finnhub`,label:`Finnhub`}]}],get_sentiment_summary:[I(),{name:`hours`,kind:`number-chips`,label:`Lookback`,default:24,presets:`HOURS_PRESETS`,suffix:`hr`}]},L={market:`Market`,fundamentals:`Fundamentals`,options:`Options`,portfolio:`Portfolio`,technical:`Technical`,sentiment:`Sentiment`,macro:`Macro`,interaction:`Interaction`};function be(e){return ye[e]??null}var xe={comprehensive_analysis:{headline:`Comprehensive analysis`,description:`Run market, fundamentals, technical, sentiment, and macro analysts on one ticker, then synthesize.`,fields:[{name:`symbol`,kind:`symbol`,label:`Symbol`,required:!0,default:`NVDA`},{name:`depth`,kind:`segmented`,label:`Depth`,default:`standard`,options:[{value:`fast`,label:`Fast`},{value:`standard`,label:`Standard`},{value:`deep`,label:`Deep`}],helper:`Fast: market + fundamentals only. Deep: includes options + macro.`}],buildPrompt:e=>{let t=e.depth&&e.depth!==`standard`?` (${e.depth} depth)`:``;return`/analyze ${e.symbol}${t}`}},portfolio_builder:{headline:`Portfolio builder`,description:`Build a draft portfolio from goals and constraints. The agent will fetch candidates, check correlation, and present an allocation table.`,fields:[{name:`objective`,kind:`freetext`,label:`Objective`,required:!0,placeholder:`Long-term growth with US tech exposure`,maxLength:200,helper:`One or two sentences describing what the portfolio is for.`},{name:`budget`,kind:`money`,label:`Budget`,default:1e5,helper:`Total amount to allocate.`},{name:`riskProfile`,kind:`segmented`,label:`Risk profile`,default:`balanced`,options:[{value:`conservative`,label:`Conservative`},{value:`balanced`,label:`Balanced`},{value:`aggressive`,label:`Aggressive`}]},{name:`timeHorizon`,kind:`segmented`,label:`Time horizon`,default:`5y`,options:[{value:`1y`,label:`1Y`},{value:`3y`,label:`3Y`},{value:`5y`,label:`5Y`},{value:`10y`,label:`10Y+`}]},{name:`assetScope`,kind:`segmented`,label:`Asset scope`,default:`stocks`,options:[{value:`stocks`,label:`Stocks`},{value:`stocks_etfs`,label:`Stocks + ETFs`},{value:`stocks_crypto`,label:`Stocks + Crypto`}]},{name:`positionCount`,kind:`number-chips`,label:`Positions`,default:8,presets:[{value:5,label:`5`},{value:8,label:`8`},{value:12,label:`12`},{value:20,label:`20`}]},{name:`maxSinglePositionPct`,kind:`percent`,label:`Max single position`,default:.15,helper:`Concentration cap, e.g. 15%.`},{name:`excludeSectors`,kind:`multi-chips`,label:`Exclude sectors`,advanced:!0,options:[{value:`energy`,label:`Energy`},{value:`financials`,label:`Financials`},{value:`consumer_discretionary`,label:`Consumer Discr.`},{value:`healthcare`,label:`Healthcare`},{value:`tech`,label:`Technology`},{value:`real_estate`,label:`Real Estate`},{value:`utilities`,label:`Utilities`}]},{name:`incomeVsGrowth`,kind:`segmented`,label:`Tilt`,advanced:!0,options:[{value:`income`,label:`Income`},{value:`balanced`,label:`Balanced`},{value:`growth`,label:`Growth`}]}],buildPrompt:e=>{let t=[`${R(e.budget)} budget`,e.riskProfile&&`${e.riskProfile} risk`,e.timeHorizon&&`${e.timeHorizon} horizon`,e.assetScope&&Se(e.assetScope),e.positionCount&&`${e.positionCount} positions`,e.maxSinglePositionPct!=null&&`max ${(e.maxSinglePositionPct*100).toFixed(0)}% per position`,e.incomeVsGrowth&&`${e.incomeVsGrowth} tilt`,e.excludeSectors?.length&&`exclude ${e.excludeSectors.join(`, `)}`].filter(Boolean).join(`, `);return`Build me a portfolio for ${String(e.objective||``).trim()}. Constraints: ${t}.`}},options_screener:{headline:`Options screener`,description:`Pick contracts from a single ticker's chain that match your direction, DTE, and liquidity preferences.`,fields:[{name:`symbol`,kind:`symbol`,label:`Underlying`,required:!0,default:`NVDA`},{name:`direction`,kind:`segmented`,label:`Direction`,required:!0,default:`bullish`,options:[{value:`bullish`,label:`Bullish (calls)`},{value:`bearish`,label:`Bearish (puts)`}]},{name:`dteTarget`,kind:`segmented`,label:`Days to expiry`,required:!0,default:`30-45`,options:[{value:`0-7`,label:`0–7`},{value:`14-30`,label:`14–30`},{value:`30-45`,label:`30–45`},{value:`45-90`,label:`45–90`},{value:`90+`,label:`90+`}]},{name:`moneynessPreference`,kind:`segmented`,label:`Moneyness`,required:!0,default:`atm`,options:[{value:`itm`,label:`ITM`},{value:`atm`,label:`ATM`},{value:`otm`,label:`OTM`}]},{name:`liquidityMinimum`,kind:`segmented`,label:`Liquidity floor`,required:!0,default:`tight_spreads`,options:[{value:`any`,label:`Any`},{value:`tight_spreads`,label:`Tight spreads`},{value:`high_oi`,label:`High open interest`}]},{name:`objective`,kind:`select`,label:`Objective`,required:!0,default:`directional_leverage`,options:[{value:`directional_leverage`,label:`Directional leverage`},{value:`hedge`,label:`Hedge existing position`},{value:`income`,label:`Income (sell premium)`},{value:`speculative`,label:`Speculative (cheap convexity)`}]},{name:`maxPremium`,kind:`money`,label:`Max premium per contract`,advanced:!0},{name:`ivPreference`,kind:`segmented`,label:`IV preference`,advanced:!0,options:[{value:`any`,label:`Any`},{value:`low`,label:`Low IV`},{value:`high`,label:`High IV`}]}],buildPrompt:e=>{let t=[e.dteTarget&&`DTE ${e.dteTarget}`,e.moneynessPreference&&`${e.moneynessPreference.toUpperCase()} strikes`,e.liquidityMinimum&&Ce(e.liquidityMinimum),e.objective&&we(e.objective),e.maxPremium!=null&&`max premium ${R(e.maxPremium)}`,e.ivPreference&&e.ivPreference!==`any`&&`${e.ivPreference} IV`].filter(Boolean).join(`, `);return`Screen options for ${e.symbol} (${e.direction||`bullish`}). ${t?`Filters: ${t}.`:``}`.trim()}},compare_assets:{headline:`Compare assets`,description:`Side-by-side comparison of two or more tickers across price, technicals, fundamentals, and risk.`,fields:[{name:`symbols`,kind:`symbols`,label:`Tickers`,required:!0,min:2,max:6,default:[`NVDA`,`AMD`],helper:`2 to 6 symbols.`},{name:`metrics`,kind:`multi-chips`,label:`Focus on`,advanced:!0,options:[{value:`valuation`,label:`Valuation`},{value:`growth`,label:`Growth`},{value:`profitability`,label:`Profitability`},{value:`momentum`,label:`Momentum`},{value:`risk`,label:`Risk`}]}],buildPrompt:e=>`Compare ${(e.symbols||[]).join(` vs `)} side by side.${e.metrics?.length?` Focus on ${e.metrics.join(`, `)}.`:``}`}};function Se(e){return e===`stocks_etfs`?`stocks and ETFs`:e===`stocks_crypto`?`stocks and crypto`:`stocks only`}function Ce(e){return e===`tight_spreads`?`tight bid-ask spreads`:e===`high_oi`?`high open interest`:`any liquidity`}function we(e){return e===`directional_leverage`?`directional leverage`:e===`hedge`?`hedge an existing position`:e===`income`?`income via short premium`:e===`speculative`?`speculative cheap convexity`:e}function R(e){if(e==null)return``;let t=Number(e);return Number.isFinite(t)?`$${t.toLocaleString(`en-US`)}`:String(e)}function Te(e){return xe[e]??null}var Ee=[{id:`workflows`,label:`Workflows`,icon:b},{id:`tools`,label:`Tools`,icon:m},{id:`providers`,label:`Providers`,icon:r}],De=`workflows`;function Oe({open:e,initialTab:t,catalog:n,onClose:r,send:i,setToast:a,startChatRun:o,fillComposer:s,sessionId:c}){let l=t??De,d=e?`open:${l}`:`closed`,[f,p]=(0,T.useState)(d),[m,g]=(0,T.useState)(l),[_,v]=(0,T.useState)(``),[y,b]=(0,T.useState)(null),x=(0,T.useRef)(null);f!==d&&(p(d),e&&(g(l),v(``),b(null))),(0,T.useEffect)(()=>{x.current&&(x.current.scrollTop=0)},[y,m]);let S=(0,T.useCallback)(()=>{b(null),v(``),r()},[r]);return(0,O.jsx)(h,{open:e,onOpenChange:e=>{e||S()},children:(0,O.jsx)(u,{width:`xl`,handleLabel:`Catalog`,className:`bg-card p-0`,children:(0,O.jsxs)(`div`,{className:`grid min-h-0 flex-1 grid-rows-[auto_minmax(0,1fr)]`,children:[y?(0,O.jsx)(Fe,{selection:y,catalog:n,onBack:()=>b(null)}):(0,O.jsx)(ke,{tab:m,setTab:g,query:_,setQuery:v,counts:{workflows:n?.workflows?.length??0,tools:n?.tools?.length??0,providers:n?.providers?.length??0}}),(0,O.jsx)(`div`,{ref:x,className:`min-h-0 overflow-y-auto overscroll-contain`,children:y?(0,O.jsx)(Ie,{selection:y,catalog:n,send:i,setToast:a,startChatRun:o,fillComposer:s,onClose:S,lookupSymbol:void 0,sessionId:c}):(0,O.jsx)(je,{tab:m,query:_,catalog:n,onSelect:e=>b(e)})})]})})})}function ke({tab:e,setTab:r,query:i,setQuery:o,counts:s}){return(0,O.jsxs)(`div`,{className:`border-b border-border`,children:[(0,O.jsx)(`div`,{className:`px-3 pt-2 sm:px-4`,children:(0,O.jsx)(`div`,{className:`flex w-full items-center gap-0.5 rounded-md bg-secondary p-0.5`,children:Ee.map(t=>{let n=t.icon,i=e===t.id;return(0,O.jsxs)(`button`,{type:`button`,onClick:()=>r(t.id),"aria-pressed":i,className:a(`inline-flex h-8 min-w-0 flex-1 items-center justify-center gap-1.5 rounded-[5px] px-2 text-xs font-medium transition-colors`,i?`bg-card text-foreground shadow-subtle-xs`:`text-muted-foreground hover:text-foreground`),children:[(0,O.jsx)(n,{className:`hidden h-3.5 w-3.5 sm:inline`,"aria-hidden":`true`}),(0,O.jsx)(`span`,{className:`truncate`,children:t.label}),(0,O.jsx)(`span`,{className:a(`hidden rounded-full px-1.5 text-[10px] tabular-nums sm:inline`,i?`bg-secondary text-muted-foreground`:`text-muted-foreground/70`),children:s[t.id]??0})]},t.id)})})}),(0,O.jsxs)(`div`,{className:`flex items-center gap-2 px-3 py-2 sm:px-4`,children:[(0,O.jsx)(n,{"aria-hidden":`true`,className:`h-4 w-4 shrink-0 text-muted-foreground`}),(0,O.jsx)(p,{variant:`ghost`,value:i,onChange:e=>o(e.target.value),placeholder:Ae(e),autoFocus:!0,className:`h-8 px-0 text-sm shadow-none`}),i?(0,O.jsx)(t,{variant:`ghost`,size:`icon-xs`,"aria-label":`Clear search`,onClick:()=>o(``),children:(0,O.jsx)(d,{})}):null]})]})}function Ae(e){return e===`workflows`?`Search workflows`:e===`providers`?`Search providers`:`Search tools by name, label, or domain`}function je({tab:e,query:t,catalog:n,onSelect:r}){if(e===`workflows`){let e=W(n?.workflows??[],t);return e.length===0?(0,O.jsx)(z,{query:t,kind:`workflows`}):(0,O.jsx)(`ul`,{className:`grid divide-y divide-border`,children:e.map(e=>(0,O.jsx)(Me,{workflow:e,onSelect:r},e.id))})}if(e===`providers`){let e=Ze(n?.providers??[],t);return e.length===0?(0,O.jsx)(z,{query:t,kind:`providers`}):(0,O.jsx)(`ul`,{className:`grid divide-y divide-border`,children:e.map(e=>(0,O.jsx)(Pe,{provider:e,onSelect:r},e.id))})}let i=Xe(n?.tools??[],t);if(i.length===0)return(0,O.jsx)(z,{query:t,kind:`tools`});let o=Qe(i,e=>e.domain??`tool`),s=[`market`,`fundamentals`,`options`,`portfolio`,`technical`,`sentiment`,`macro`,`interaction`];return(0,O.jsx)(`div`,{className:`grid`,children:[...o.keys()].sort((e,t)=>{let n=s.indexOf(e),r=s.indexOf(t);return(n===-1?999:n)-(r===-1?999:r)}).map((e,t)=>(0,O.jsxs)(`section`,{className:a(t===0?``:`mt-2`),children:[(0,O.jsx)(`h4`,{className:`px-4 pb-1 pt-3 text-[11px] font-medium uppercase tracking-[0.08em] text-muted-foreground`,children:L[e]??e}),(0,O.jsx)(`ul`,{className:`grid divide-y divide-border border-y border-border`,children:o.get(e).map(e=>(0,O.jsx)(Ne,{tool:e,onSelect:r},e.name))})]},e))})}function Me({workflow:e,onSelect:t}){return(0,O.jsx)(`li`,{children:(0,O.jsxs)(`button`,{type:`button`,onClick:()=>t({kind:`workflow`,id:e.id}),className:`group flex w-full items-start gap-3 px-4 py-3 text-left transition-colors hover:bg-secondary`,children:[(0,O.jsx)(b,{"aria-hidden":`true`,className:`mt-0.5 h-4 w-4 shrink-0 text-foreground`}),(0,O.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,O.jsx)(`div`,{className:`flex items-center gap-2`,children:(0,O.jsx)(`span`,{className:`text-sm font-semibold text-foreground`,children:e.name})}),(0,O.jsx)(`p`,{className:`mt-0.5 line-clamp-2 text-xs text-muted-foreground`,children:e.description})]}),(0,O.jsx)(x,{"aria-hidden":`true`,className:`mt-1 h-4 w-4 shrink-0 text-muted-foreground opacity-0 transition-opacity group-hover:opacity-100`})]})})}function Ne({tool:e,onSelect:t}){let n=e.enabled===!1;return(0,O.jsx)(`li`,{children:(0,O.jsxs)(`button`,{type:`button`,onClick:()=>t({kind:`tool`,id:e.name}),className:a(`group flex w-full items-start gap-3 px-4 py-2.5 text-left transition-colors hover:bg-secondary`,n&&`opacity-60`),children:[(0,O.jsx)(m,{"aria-hidden":`true`,className:`mt-0.5 h-3.5 w-3.5 shrink-0 text-muted-foreground`}),(0,O.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,O.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,O.jsx)(`span`,{className:`text-sm font-medium text-foreground`,children:e.label||U(e.name)}),(0,O.jsx)(`code`,{className:`hidden truncate text-[11px] tabular-nums text-muted-foreground/70 sm:inline`,children:e.name}),n?(0,O.jsx)(s,{variant:`outline`,className:`h-5 px-1.5 text-[10px]`,children:`disabled`}):null]}),(0,O.jsx)(`p`,{className:`mt-0.5 line-clamp-1 text-xs text-muted-foreground`,children:e.description})]}),(0,O.jsx)(x,{"aria-hidden":`true`,className:`mt-1 h-4 w-4 shrink-0 text-muted-foreground opacity-0 transition-opacity group-hover:opacity-100`})]})})}function Pe({provider:e,onSelect:t}){let n=G(e);return(0,O.jsx)(`li`,{children:(0,O.jsxs)(`button`,{type:`button`,onClick:()=>t({kind:`provider`,id:e.id}),className:`group flex w-full items-start gap-3 px-4 py-3 text-left transition-colors hover:bg-secondary`,children:[(0,O.jsx)(K(e),{"aria-hidden":`true`,className:`mt-0.5 h-4 w-4 shrink-0 text-muted-foreground`}),(0,O.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,O.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,O.jsx)(`span`,{className:`text-sm font-medium text-foreground`,children:e.displayName}),(0,O.jsx)(q,{status:n}),(0,O.jsx)(`span`,{className:a(`text-[11px]`,Y(n)),children:J(n)})]}),(0,O.jsx)(`p`,{className:`mt-0.5 line-clamp-2 text-xs text-muted-foreground`,children:(e.unlocks||[]).join(` · `)})]}),(0,O.jsx)(x,{"aria-hidden":`true`,className:`mt-1 h-4 w-4 shrink-0 text-muted-foreground opacity-0 transition-opacity group-hover:opacity-100`})]})})}function z({query:e,kind:t}){return(0,O.jsxs)(`div`,{className:`grid gap-2 p-12 text-center`,children:[(0,O.jsx)(n,{className:`mx-auto h-5 w-5 text-muted-foreground`,"aria-hidden":`true`}),(0,O.jsx)(`p`,{className:`text-sm font-medium text-foreground`,children:e?`No ${t} match "${e}"`:`No ${t} available`}),(0,O.jsx)(`p`,{className:`mx-auto max-w-xs text-xs text-muted-foreground`,children:e?`Try a shorter query or check spelling.`:`OpenCandle did not return entries for this section.`})]})}function Fe({selection:e,catalog:n,onBack:i}){let a=H(e,n),o=e.kind===`provider`&&a?K(a):r;return(0,O.jsxs)(`div`,{className:`flex items-center gap-2 border-b border-border px-3 py-2 sm:px-4`,children:[(0,O.jsx)(t,{variant:`ghost`,size:`icon-sm`,"aria-label":`Back to catalog`,onClick:i,children:(0,O.jsx)(S,{})}),(0,O.jsxs)(`div`,{className:`flex min-w-0 flex-1 items-center gap-2`,children:[e.kind===`workflow`?(0,O.jsx)(b,{className:`h-4 w-4 text-foreground`,"aria-hidden":`true`}):null,e.kind===`tool`?(0,O.jsx)(m,{className:`h-4 w-4 text-muted-foreground`,"aria-hidden":`true`}):null,e.kind===`provider`?(0,O.jsx)(o,{className:`h-4 w-4 text-muted-foreground`,"aria-hidden":`true`}):null,(0,O.jsx)(`h2`,{className:`truncate text-sm font-semibold text-foreground`,children:Ue(e,a)}),e.kind===`tool`&&a?.domain?(0,O.jsx)(s,{variant:`outline`,className:`hidden h-5 px-1.5 text-[10px] sm:inline-flex`,children:L[a.domain]??a.domain}):null]})]})}function Ie({selection:e,catalog:t,send:n,setToast:r,startChatRun:i,fillComposer:a,onClose:o,lookupSymbol:s,sessionId:c}){let l=H(e,t);return l?e.kind===`workflow`?(0,O.jsx)(Le,{workflow:l,startChatRun:i,fillComposer:a,onClose:o,setToast:r,lookupSymbol:s,sessionId:c}):e.kind===`tool`?(0,O.jsx)(Re,{tool:l,send:n,startChatRun:i,fillComposer:a,onClose:o,setToast:r,lookupSymbol:s}):(0,O.jsx)(ze,{provider:l,send:n,setToast:r}):(0,O.jsxs)(`div`,{className:`grid gap-2 p-12 text-center`,children:[(0,O.jsx)(`p`,{className:`text-sm font-medium text-foreground`,children:`Selection no longer available`}),(0,O.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`The catalog refreshed while you were viewing this entry.`})]})}function Le({workflow:e,startChatRun:n,fillComposer:r,onClose:i,setToast:o,lookupSymbol:s}){let c=Te(e.id),l=c?.fields??[],[u,d]=(0,T.useState)(()=>N(l)),[f,p]=(0,T.useState)(!1),m=(0,T.useCallback)((e,t)=>d(n=>({...n,[e]:t})),[]),h=P(l,u),g=(0,T.useMemo)(()=>c?Ye(c,u):e.prompt||e.name,[c,u,e]),_=l.filter(e=>!e.advanced),v=l.filter(e=>e.advanced);if(!c)return(0,O.jsxs)(`div`,{className:`p-6`,children:[(0,O.jsxs)(`p`,{className:`text-sm text-muted-foreground`,children:[`No builder defined for "`,e.name,`". The agent will use its default planner.`]}),(0,O.jsx)(`div`,{className:`mt-4 flex gap-2`,children:(0,O.jsx)(t,{variant:`brand`,onClick:()=>{n(e.prompt||e.name),i()},children:`Run with defaults`})})]});let y=e=>{if(h.length>0){o?.(h[0]);return}if(e===`send`){n(g),i();return}r?.(g),o?.(`Draft loaded — edit and send when ready.`),i()};return(0,O.jsxs)(`div`,{className:`grid animate-fade-in-once gap-5 px-4 py-4 sm:px-5`,children:[(0,O.jsx)(`p`,{className:`text-sm leading-5 text-muted-foreground`,children:c.description}),(0,O.jsx)(`div`,{className:`grid gap-3.5`,children:_.map(e=>(0,O.jsx)(M,{field:e,value:u[e.name],onChange:m,lookupSymbol:s},e.name))}),v.length>0?(0,O.jsxs)(`div`,{className:`grid gap-3.5 border-t border-border pt-4`,children:[(0,O.jsxs)(`button`,{type:`button`,onClick:()=>p(e=>!e),className:`inline-flex w-fit items-center gap-1.5 text-[11px] font-medium uppercase tracking-wider text-muted-foreground hover:text-foreground`,children:[(0,O.jsxs)(`span`,{children:[f?`Hide`:`Show`,` advanced`]}),(0,O.jsx)(x,{"aria-hidden":`true`,className:a(`h-3 w-3 transition-transform`,f&&`rotate-90`)})]}),f?v.map(e=>(0,O.jsx)(M,{field:e,value:u[e.name],onChange:m,lookupSymbol:s},e.name)):null]}):null,(0,O.jsx)(V,{prompt:g}),(0,O.jsxs)(`div`,{className:`sticky bottom-0 -mx-4 flex flex-wrap items-center justify-end gap-2 border-t border-border bg-card px-4 py-3 sm:-mx-5 sm:px-5`,children:[(0,O.jsx)(t,{variant:`bordered`,onClick:()=>y(`draft`),disabled:!g,children:`Edit in chat`}),(0,O.jsx)(t,{variant:`brand`,onClick:()=>y(`send`),disabled:!g,prefixIcon:C,children:`Run workflow`})]})]})}function B(e,t,n=``){return{toolName:e,args:t,...n?{sessionId:n}:{}}}function Re({tool:e,send:n,startChatRun:r,fillComposer:i,onClose:a,setToast:o,lookupSymbol:s,sessionId:c}){let l=(0,T.useMemo)(()=>be(e.name)??We(e),[e]),[u,d]=(0,T.useState)(()=>N(l)),f=(0,T.useCallback)((e,t)=>d(n=>({...n,[e]:t})),[]),p=P(l,u),m=(0,T.useMemo)(()=>Ke(u),[u]),h=(0,T.useMemo)(()=>`Use ${e.name}${qe(m)}`,[e,m]),g=t=>{if(p.length>0){o?.(p[0]);return}if(t===`send`){r(h),a();return}if(t===`draft`){i?.(h),o?.(`Draft loaded — edit and send when ready.`),a();return}t===`run`&&n?.(`tool.invoke`,B(e.name,m,c))&&(o?.(`Running ${e.label||e.name}…`),a())};return(0,O.jsxs)(`div`,{className:`grid animate-fade-in-once gap-5 px-4 py-4 sm:px-5`,children:[(0,O.jsx)(`p`,{className:`text-sm leading-5 text-muted-foreground`,children:e.description}),l.length===0?(0,O.jsx)(`div`,{className:`rounded-md border border-dashed border-border bg-secondary px-3 py-2.5 text-xs text-muted-foreground`,children:`This tool takes no inputs.`}):(0,O.jsx)(`div`,{className:`grid gap-3.5`,children:l.map(e=>(0,O.jsx)(M,{field:e,value:u[e.name],onChange:f,lookupSymbol:s},e.name))}),(0,O.jsx)(V,{prompt:h,title:`Chat preview`}),(0,O.jsxs)(`div`,{className:`sticky bottom-0 -mx-4 flex flex-wrap items-center justify-end gap-2 border-t border-border bg-card px-4 py-3 sm:-mx-5 sm:px-5`,children:[(0,O.jsx)(t,{variant:`bordered`,size:`sm`,onClick:()=>g(`draft`),children:`Edit in chat`}),(0,O.jsx)(t,{variant:`brand`,size:`sm`,prefixIcon:C,onClick:()=>g(`run`),children:`Run now`})]})]})}function ze({provider:e,send:t,setToast:n}){return e.kind===`external-tool`?(0,O.jsx)(Ve,{provider:e,send:t,setToast:n}):e.kind===`public-http`?(0,O.jsx)(He,{provider:e,send:t,setToast:n}):(0,O.jsx)(Be,{provider:e,send:t,setToast:n})}function Be({provider:e,send:n,setToast:r}){let o=`${e.id}:${e.apiKey||``}`,[s,c]=(0,T.useState)(o),[l,u]=(0,T.useState)(e.apiKey||``),[d,f]=(0,T.useState)(!1),m=G(e),h=m===`env`,g=l.trim(),_=!h&&g.length>0;s!==o&&(c(o),u(e.apiKey||``),f(!1));let v=()=>{if(h){r?.(`${e.displayName} is set via ${e.envVar}. Unset it to override here.`);return}g&&(r?.(`Verifying ${e.displayName} key…`),n?.(`provider.save_api_key`,{providerId:e.id,apiKey:g})&&u(``))};return(0,O.jsxs)(`div`,{className:`grid animate-fade-in-once gap-5 px-4 py-4 sm:px-5`,children:[(0,O.jsxs)(`div`,{className:`grid gap-1.5`,children:[(0,O.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,O.jsx)(q,{status:m}),(0,O.jsx)(`span`,{className:a(`text-xs font-medium`,Y(m)),children:J(m)}),h?(0,O.jsxs)(`code`,{className:`text-[11px] text-muted-foreground`,children:[`env: `,e.envVar]}):null]}),(0,O.jsx)(`p`,{className:`text-sm leading-5 text-muted-foreground`,children:e.fallbackDescription?(0,O.jsxs)(O.Fragment,{children:[`If absent: `,e.fallbackDescription,`.`]}):(0,O.jsxs)(O.Fragment,{children:[`Required for: `,(e.unlocks||[]).join(`, `)||`this provider's tools`,`.`]})})]}),(0,O.jsxs)(`div`,{className:`grid gap-2`,children:[(0,O.jsx)(`span`,{className:`text-[11px] font-medium uppercase tracking-wider text-muted-foreground`,children:`Unlocks`}),(0,O.jsx)(`ul`,{className:`grid gap-1`,children:(e.unlocks||[]).map(e=>(0,O.jsxs)(`li`,{className:`flex items-baseline gap-2 text-sm text-foreground`,children:[(0,O.jsx)(`span`,{"aria-hidden":`true`,className:`mt-1 h-1 w-1 rounded-full bg-foreground/40`}),(0,O.jsx)(`span`,{children:e})]},e))})]}),(0,O.jsxs)(`div`,{className:`grid gap-2`,children:[(0,O.jsx)(`label`,{htmlFor:`provider-api-key-${e.id}`,className:`text-xs font-medium text-foreground`,children:`API key`}),(0,O.jsxs)(`div`,{className:`relative`,children:[(0,O.jsx)(p,{id:`provider-api-key-${e.id}`,type:d?`text`:`password`,value:l,onChange:e=>u(e.target.value),placeholder:`Paste your ${e.displayName} key`,disabled:h,className:`pr-10 font-mono`,autoCapitalize:`none`,autoComplete:`off`,spellCheck:!1,onKeyDown:e=>{e.key===`Enter`&&_&&(e.preventDefault(),v())}}),(0,O.jsx)(t,{type:`button`,variant:`ghost`,size:`icon-xs`,className:`absolute right-1 top-1/2 -translate-y-1/2`,"aria-label":d?`Hide API key`:`Show API key`,tooltip:d?`Hide API key`:`Show API key`,onClick:()=>f(e=>!e),disabled:!l,children:d?(0,O.jsx)(te,{}):(0,O.jsx)(ne,{})})]}),(0,O.jsx)(`p`,{className:`text-[11px] leading-4 text-muted-foreground`,children:h?`Currently set via ${e.envVar}. Unset that variable to manage the key here.`:m===`file`?`Saved to ~/.opencandle/config.json. Paste a new key to replace.`:e.instructionsHint||`Saved to ~/.opencandle/config.json.`})]}),(0,O.jsxs)(`div`,{className:`sticky bottom-0 -mx-4 flex flex-wrap items-center justify-end gap-2 border-t border-border bg-card px-4 py-3 sm:-mx-5 sm:px-5`,children:[e.signupUrl?(0,O.jsx)(t,{variant:`ghost`,size:`sm`,suffixIcon:i,onClick:()=>window.open(e.signupUrl,`_blank`,`noreferrer`),children:`Get a key`}):null,(0,O.jsx)(t,{variant:`brand`,size:`sm`,onClick:v,disabled:!_,children:m===`file`?`Replace key`:`Save key`})]})]})}function Ve({provider:e,send:n,setToast:r}){let i=G(e),o=e.statusDetail,s=i===`skipped`;return(0,O.jsxs)(`div`,{className:`grid animate-fade-in-once gap-5 px-4 py-4 sm:px-5`,children:[(0,O.jsxs)(`div`,{className:`grid gap-1.5`,children:[(0,O.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[(0,O.jsx)(q,{status:i}),(0,O.jsx)(`span`,{className:a(`text-xs font-medium`,Y(i)),children:J(i)}),o?.checkedAt?(0,O.jsxs)(`span`,{className:`text-[11px] text-muted-foreground`,children:[`Checked `,$(o.checkedAt)]}):null]}),(0,O.jsx)(`p`,{className:`text-sm leading-5 text-muted-foreground`,children:e.fallbackDescription})]}),(0,O.jsxs)(`div`,{className:`grid gap-2`,children:[(0,O.jsx)(`span`,{className:`text-[11px] font-medium uppercase tracking-wider text-muted-foreground`,children:`Install`}),(0,O.jsxs)(`div`,{className:`flex min-w-0 items-center gap-2 rounded-md border border-border bg-secondary px-3 py-2`,children:[(0,O.jsx)(w,{className:`h-3.5 w-3.5 shrink-0 text-muted-foreground`,"aria-hidden":`true`}),(0,O.jsx)(`code`,{className:`min-w-0 flex-1 overflow-x-auto whitespace-nowrap text-[11px] text-foreground`,children:e.installCmd}),(0,O.jsx)(t,{type:`button`,variant:`ghost`,size:`icon-xs`,"aria-label":`Copy install command`,tooltip:`Copy install command`,onClick:()=>{navigator.clipboard?.writeText?.(e.installCmd),r?.(`Install command copied.`)},children:(0,O.jsx)(ee,{})})]})]}),(0,O.jsxs)(`div`,{className:`grid gap-2`,children:[(0,O.jsx)(`span`,{className:`text-[11px] font-medium uppercase tracking-wider text-muted-foreground`,children:`Session source`}),(0,O.jsxs)(`p`,{className:`text-sm leading-5 text-muted-foreground`,children:[`Uses your normal browser session. Supported browsers:`,` `,(e.supportedBrowsers||[]).join(`, `)||`Chrome, Arc, Edge, Firefox, Brave`,`.`]}),o?.message?(0,O.jsx)(`p`,{className:`rounded-md border border-border bg-secondary px-3 py-2 text-xs leading-5 text-muted-foreground`,children:o.message}):null]}),(0,O.jsxs)(`div`,{className:`sticky bottom-0 -mx-4 flex flex-wrap items-center justify-end gap-2 border-t border-border bg-card px-4 py-3 sm:-mx-5 sm:px-5`,children:[(0,O.jsx)(t,{variant:`bordered`,size:`sm`,prefixIcon:c,onClick:()=>{r?.(s?`Re-enabling ${e.displayName} and checking install status...`:`Checking ${e.displayName} install status...`),n?.(`provider.status.check`,{providerId:e.id,mode:`install`,reenable:s})},children:s?`Re-enable & check install`:`Check install`}),(0,O.jsx)(t,{variant:`brand`,size:`sm`,onClick:()=>{r?.(s?`Re-enabling ${e.displayName} and checking session. This may read browser cookies and trigger a Keychain prompt.`:`Checking ${e.displayName} session. This may read browser cookies and trigger a Keychain prompt.`),n?.(`provider.status.check`,{providerId:e.id,mode:`session`,reenable:s})},children:s?`Re-enable & check session`:`Check session`})]})]})}function He({provider:e,send:n,setToast:r}){let i=G(e),o=e.statusDetail;return(0,O.jsxs)(`div`,{className:`grid animate-fade-in-once gap-5 px-4 py-4 sm:px-5`,children:[(0,O.jsxs)(`div`,{className:`grid gap-1.5`,children:[(0,O.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[(0,O.jsx)(q,{status:i}),(0,O.jsx)(`span`,{className:a(`text-xs font-medium`,Y(i)),children:J(i)}),o?.checkedAt?(0,O.jsxs)(`span`,{className:`text-[11px] text-muted-foreground`,children:[`Checked `,$(o.checkedAt)]}):null]}),(0,O.jsx)(`p`,{className:`text-sm leading-5 text-muted-foreground`,children:e.fallbackDescription||`No account or API key is required.`})]}),(0,O.jsxs)(`div`,{className:`grid gap-2`,children:[(0,O.jsx)(`span`,{className:`text-[11px] font-medium uppercase tracking-wider text-muted-foreground`,children:`Probe`}),(0,O.jsx)(`code`,{className:`overflow-x-auto rounded-md border border-border bg-secondary px-3 py-2 text-[11px] text-muted-foreground`,children:e.probeUrl}),o?.message?(0,O.jsx)(`p`,{className:`text-xs leading-5 text-muted-foreground`,children:o.message}):null]}),(0,O.jsx)(`div`,{className:`sticky bottom-0 -mx-4 flex flex-wrap items-center justify-end gap-2 border-t border-border bg-card px-4 py-3 sm:-mx-5 sm:px-5`,children:(0,O.jsx)(t,{variant:`brand`,size:`sm`,prefixIcon:c,onClick:()=>{r?.(`Checking ${e.displayName} reachability...`),n?.(`provider.status.check`,{providerId:e.id})},children:`Check reachability`})})]})}function V({prompt:e,title:t=`Chat prompt`}){return(0,O.jsxs)(`div`,{className:`grid gap-1.5`,children:[(0,O.jsx)(`span`,{className:`text-[11px] font-medium uppercase tracking-wider text-muted-foreground`,children:t}),(0,O.jsx)(`pre`,{className:`overflow-auto whitespace-pre-wrap rounded-md border border-border bg-secondary px-3 py-2 font-mono text-xs leading-5 text-foreground`,children:e||`Fill the required fields to preview the chat prompt.`})]})}function H(e,t){return!e||!t?null:e.kind===`workflow`?t.workflows?.find(t=>t.id===e.id)??null:e.kind===`tool`?t.tools?.find(t=>t.name===e.id)??null:e.kind===`provider`?t.providers?.find(t=>t.id===e.id)??null:null}function Ue(e,t){return t?e.kind===`workflow`?t.name:e.kind===`tool`?t.label||U(t.name):e.kind===`provider`?t.displayName:`Catalog`:`Catalog`}function U(e){return String(e||``).replace(/^get_/,``).replace(/_/g,` `)}function We(e){let t=e.parameters?.properties||{};return Object.entries(t).map(([t,n])=>{let r=String(n.description||``);return{name:t,kind:n.type===`number`?`text`:n.type===`boolean`?`select`:`text`,label:Ge(t),placeholder:n.examples?.[0],helper:r.length>80?`${r.slice(0,80)}…`:r,required:e.parameters?.required?.includes?.(t)??!1}})}function Ge(e){return e.replace(/_/g,` `).replace(/\b\w/g,e=>e.toUpperCase())}function Ke(e){let t={};for(let[n,r]of Object.entries(e))r===void 0||r===``||Array.isArray(r)&&r.length===0||(t[n]=r);return t}function qe(e){let t=Object.entries(e);return t.length===0?``:` with ${t.map(([e,t])=>`${e}=${Je(t)}`).join(`, `)}`}function Je(e){return Array.isArray(e)?e.join(`,`):typeof e==`string`&&e.includes(` `)?JSON.stringify(e):String(e)}function Ye(e,t){try{return e.buildPrompt(t)||``}catch{return``}}function Xe(e,t){if(!t.trim())return e;let n=t.toLowerCase();return e.filter(e=>[e.name,e.label,e.description,e.domain].some(e=>String(e||``).toLowerCase().includes(n)))}function W(e,t){if(!t.trim())return e;let n=t.toLowerCase();return e.filter(e=>[e.id,e.name,e.description].some(e=>String(e||``).toLowerCase().includes(n)))}function Ze(e,t){if(!t.trim())return e;let n=t.toLowerCase();return e.filter(e=>[e.id,e.kind,e.displayName,e.envVar,e.binary,e.installCmd,e.probeUrl,...e.aliases||[],...e.unlocks||[]].some(e=>String(e||``).toLowerCase().includes(n)))}function Qe(e,t){let n=new Map;for(let r of e){let e=t(r);n.has(e)||n.set(e,[]),n.get(e).push(r)}return n}function G(e){return e.statusDetail?.state??e.status??e.source??`absent`}function K(e){return e.kind===`external-tool`?w:e.kind===`public-http`?y:r}function q({status:e}){return(0,O.jsx)(`span`,{"aria-hidden":`true`,className:a(`inline-block h-1.5 w-1.5 rounded-full`,X.has(e)?`bg-success`:Z.has(e)?`bg-info`:Q.has(e)?`bg-destructive`:`bg-warning`)})}function J(e){return e===`configured`||e===`file`?`Configured`:e===`env`?`From environment`:e===`installed`?`Installed`:e===`missing`?`Missing`:e===`session_ok`?`Session ready`:e===`session_missing`?`Login needed`:e===`session_stale`?`Session stale`:e===`skipped`?`Skipped`:e===`reachable`?`Reachable`:e===`unreachable`?`Unreachable`:e===`error`?`Needs attention`:e===`unknown`?`Not checked`:`Not configured`}function Y(e){return X.has(e)?`text-success`:Z.has(e)?`text-info`:Q.has(e)?`text-destructive`:`text-warning`}var X=new Set([`configured`,`file`,`installed`,`session_ok`,`reachable`]),Z=new Set([`env`,`skipped`]),Q=new Set([`error`,`unreachable`]);function $(e){let t=Date.parse(e);if(Number.isNaN(t))return`just now`;let n=Math.max(0,Math.round((Date.now()-t)/1e3));if(n<60)return`just now`;let r=Math.round(n/60);if(r<60)return`${r}m ago`;let i=Math.round(r/60);return i<24?`${i}h ago`:`${Math.round(i/24)}d ago`}export{Oe as CatalogOverlay,B as buildCatalogToolInvokePayload};
|