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.
Files changed (46) hide show
  1. package/dist/cli-main.js +48 -24
  2. package/dist/cli-main.js.map +1 -1
  3. package/dist/pi/session-writer-lock.d.ts +30 -0
  4. package/dist/pi/session-writer-lock.js +111 -0
  5. package/dist/pi/session-writer-lock.js.map +1 -0
  6. package/dist/prompts/workflow-prompts.js +15 -0
  7. package/dist/prompts/workflow-prompts.js.map +1 -1
  8. package/dist/routing/classify-intent.js +8 -9
  9. package/dist/routing/classify-intent.js.map +1 -1
  10. package/dist/routing/entity-extractor.js +1 -1
  11. package/dist/routing/entity-extractor.js.map +1 -1
  12. package/dist/routing/router-llm-client.d.ts +1 -1
  13. package/dist/routing/router-llm-client.js +1 -1
  14. package/dist/routing/router-llm-client.js.map +1 -1
  15. package/dist/routing/router.js +37 -0
  16. package/dist/routing/router.js.map +1 -1
  17. package/dist/workflows/compare-assets.js +4 -1
  18. package/dist/workflows/compare-assets.js.map +1 -1
  19. package/gui/server/ask-user-bridge.ts +26 -19
  20. package/gui/server/chat-event-adapter.ts +49 -3
  21. package/gui/server/http-routes.ts +173 -15
  22. package/gui/server/invoke-tool.ts +102 -7
  23. package/gui/server/live-chat-event-adapter.ts +16 -4
  24. package/gui/server/server.ts +42 -5
  25. package/gui/server/session-actions.ts +7 -1
  26. package/gui/server/session-entry-wait.ts +79 -0
  27. package/gui/server/writer-lock.ts +1 -122
  28. package/gui/server/ws-hub.ts +25 -0
  29. package/gui/shared/chat-events.ts +42 -19
  30. package/gui/shared/event-reducer.ts +41 -26
  31. package/gui/web/dist/assets/CatalogOverlay-CYptsda-.js +1 -0
  32. package/gui/web/dist/assets/index-B7QAjY5g.js +65 -0
  33. package/gui/web/dist/assets/index-D5dbWPfM.css +2 -0
  34. package/gui/web/dist/index.html +2 -2
  35. package/package.json +16 -16
  36. package/src/cli-main.ts +64 -27
  37. package/src/pi/session-writer-lock.ts +156 -0
  38. package/src/prompts/workflow-prompts.ts +15 -0
  39. package/src/routing/classify-intent.ts +11 -11
  40. package/src/routing/entity-extractor.ts +1 -1
  41. package/src/routing/router-llm-client.ts +2 -1
  42. package/src/routing/router.ts +46 -0
  43. package/src/workflows/compare-assets.ts +4 -2
  44. package/gui/web/dist/assets/CatalogOverlay-CCVKwBUB.js +0 -1
  45. package/gui/web/dist/assets/index-Dm4Aom2_.js +0 -69
  46. 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"; runId: string; sessionId: string; seq: number }
49
- | { type: "thinking.delta"; runId: string; text: string; seq: number }
50
- | { type: "thinking.completed"; runId: string; text?: string; seq: number }
51
- | { type: "message.created"; messageId: string; role: ChatRole; seq: number }
52
- | { type: "message.delta"; messageId: string; text: string; seq: number }
53
- | { type: "message.completed"; messageId: string; content: MessageContent[]; seq: number }
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
- seq: number;
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
- seq: number;
68
- }
69
- | { type: "tool.delta"; toolCallId: string; chunk: unknown; seq: number }
70
- | { type: "tool.completed"; toolCallId: string; output: ToolOutput; seq: number }
71
- | { type: "tool.failed"; toolCallId: string; error: ToolError; seq: number }
72
- | { type: "run.completed"; runId: string; usage?: Usage; seq: number }
73
- | { type: "run.failed"; runId: string; error: RunError; seq: number }
74
- | { type: "session.updated"; sessionId: string; title?: string; updatedAt: string; seq: number };
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<number>;
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
- if (state.seenSeq.has(event.seq)) return state;
16
+ const eventKey = `${event.sessionId}:${event.seq}`;
17
+ if (state.seenSeq.has(eventKey)) return state;
17
18
 
18
19
  const next = cloneState(state);
19
- if (event.seq > next.lastSeq + 1 && next.lastSeq !== 0) {
20
- next.gaps.push({ expected: next.lastSeq + 1, received: event.seq });
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(event.seq);
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 existing = state.messageById.get(id);
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(id, message);
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(messages.map((message) => [message.id, message]));
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 existing = state.thinking.get(runId);
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(runId, thinking);
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};