opencandle 0.5.0 → 0.7.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 (574) hide show
  1. package/README.md +170 -186
  2. package/dist/analysts/contracts.d.ts +1 -3
  3. package/dist/analysts/contracts.js +1 -11
  4. package/dist/analysts/contracts.js.map +1 -1
  5. package/dist/analysts/orchestrator.d.ts +1 -3
  6. package/dist/analysts/orchestrator.js +1 -26
  7. package/dist/analysts/orchestrator.js.map +1 -1
  8. package/dist/cli.js +66 -7
  9. package/dist/cli.js.map +1 -1
  10. package/dist/config.d.ts +13 -3
  11. package/dist/config.js +25 -5
  12. package/dist/config.js.map +1 -1
  13. package/dist/index.d.ts +1 -1
  14. package/dist/index.js +1 -1
  15. package/dist/index.js.map +1 -1
  16. package/dist/infra/cache.d.ts +8 -11
  17. package/dist/infra/cache.js +17 -15
  18. package/dist/infra/cache.js.map +1 -1
  19. package/dist/infra/http-client.d.ts +4 -1
  20. package/dist/infra/http-client.js +59 -6
  21. package/dist/infra/http-client.js.map +1 -1
  22. package/dist/infra/index.d.ts +2 -3
  23. package/dist/infra/index.js +2 -3
  24. package/dist/infra/index.js.map +1 -1
  25. package/dist/infra/native-dependencies.js +2 -2
  26. package/dist/infra/native-dependencies.js.map +1 -1
  27. package/dist/infra/node-version.js.map +1 -1
  28. package/dist/infra/opencandle-paths.d.ts +0 -3
  29. package/dist/infra/opencandle-paths.js +4 -11
  30. package/dist/infra/opencandle-paths.js.map +1 -1
  31. package/dist/infra/rate-limiter.js +12 -9
  32. package/dist/infra/rate-limiter.js.map +1 -1
  33. package/dist/market-state/alert-conditions.d.ts +34 -0
  34. package/dist/market-state/alert-conditions.js +23 -0
  35. package/dist/market-state/alert-conditions.js.map +1 -0
  36. package/dist/market-state/alert-runner.d.ts +55 -0
  37. package/dist/market-state/alert-runner.js +634 -0
  38. package/dist/market-state/alert-runner.js.map +1 -0
  39. package/dist/market-state/daily-report.d.ts +26 -0
  40. package/dist/market-state/daily-report.js +179 -0
  41. package/dist/market-state/daily-report.js.map +1 -0
  42. package/dist/market-state/local-automation-service.d.ts +25 -0
  43. package/dist/market-state/local-automation-service.js +119 -0
  44. package/dist/market-state/local-automation-service.js.map +1 -0
  45. package/dist/market-state/notification-delivery.d.ts +14 -0
  46. package/dist/market-state/notification-delivery.js +139 -0
  47. package/dist/market-state/notification-delivery.js.map +1 -0
  48. package/dist/market-state/resolve-for-mutation.d.ts +10 -0
  49. package/dist/market-state/resolve-for-mutation.js +15 -0
  50. package/dist/market-state/resolve-for-mutation.js.map +1 -0
  51. package/dist/market-state/resolve.d.ts +14 -0
  52. package/dist/market-state/resolve.js +89 -0
  53. package/dist/market-state/resolve.js.map +1 -0
  54. package/dist/market-state/service.d.ts +527 -0
  55. package/dist/market-state/service.js +1099 -0
  56. package/dist/market-state/service.js.map +1 -0
  57. package/dist/memory/index.d.ts +7 -7
  58. package/dist/memory/index.js +6 -6
  59. package/dist/memory/index.js.map +1 -1
  60. package/dist/memory/manager.js +11 -11
  61. package/dist/memory/manager.js.map +1 -1
  62. package/dist/memory/retrieval.js +7 -4
  63. package/dist/memory/retrieval.js.map +1 -1
  64. package/dist/memory/sqlite.js +385 -3
  65. package/dist/memory/sqlite.js.map +1 -1
  66. package/dist/memory/storage.js +1 -2
  67. package/dist/memory/storage.js.map +1 -1
  68. package/dist/memory/tool-defaults.js +64 -28
  69. package/dist/memory/tool-defaults.js.map +1 -1
  70. package/dist/memory/types.js.map +1 -1
  71. package/dist/monitor.d.ts +2 -0
  72. package/dist/monitor.js +104 -0
  73. package/dist/monitor.js.map +1 -0
  74. package/dist/onboarding/connect.d.ts +2 -2
  75. package/dist/onboarding/connect.js +13 -8
  76. package/dist/onboarding/connect.js.map +1 -1
  77. package/dist/onboarding/credential-interceptor.js +1 -1
  78. package/dist/onboarding/credential-interceptor.js.map +1 -1
  79. package/dist/onboarding/degradation-accumulator.js +1 -3
  80. package/dist/onboarding/degradation-accumulator.js.map +1 -1
  81. package/dist/onboarding/provider-status.d.ts +48 -0
  82. package/dist/onboarding/provider-status.js +285 -0
  83. package/dist/onboarding/provider-status.js.map +1 -0
  84. package/dist/onboarding/providers.d.ts +85 -8
  85. package/dist/onboarding/providers.js +83 -18
  86. package/dist/onboarding/providers.js.map +1 -1
  87. package/dist/onboarding/state.d.ts +1 -0
  88. package/dist/onboarding/state.js +5 -0
  89. package/dist/onboarding/state.js.map +1 -1
  90. package/dist/onboarding/tool-helpers.js +1 -1
  91. package/dist/onboarding/tool-helpers.js.map +1 -1
  92. package/dist/onboarding/tool-tags.d.ts +12 -1
  93. package/dist/onboarding/tool-tags.js +37 -5
  94. package/dist/onboarding/tool-tags.js.map +1 -1
  95. package/dist/onboarding/validation.d.ts +2 -2
  96. package/dist/onboarding/validation.js +1 -1
  97. package/dist/onboarding/validation.js.map +1 -1
  98. package/dist/pi/opencandle-extension.d.ts +8 -0
  99. package/dist/pi/opencandle-extension.js +502 -42
  100. package/dist/pi/opencandle-extension.js.map +1 -1
  101. package/dist/pi/session.d.ts +1 -1
  102. package/dist/pi/session.js +3 -1
  103. package/dist/pi/session.js.map +1 -1
  104. package/dist/pi/setup.js +8 -3
  105. package/dist/pi/setup.js.map +1 -1
  106. package/dist/pi/tool-adapter.d.ts +4 -1
  107. package/dist/pi/tool-adapter.js +10 -6
  108. package/dist/pi/tool-adapter.js.map +1 -1
  109. package/dist/prompts/context-builder.d.ts +1 -1
  110. package/dist/prompts/context-builder.js +20 -7
  111. package/dist/prompts/context-builder.js.map +1 -1
  112. package/dist/prompts/policy-cards.d.ts +1 -1
  113. package/dist/prompts/policy-cards.js +2 -2
  114. package/dist/prompts/policy-cards.js.map +1 -1
  115. package/dist/prompts/sections.d.ts +1 -1
  116. package/dist/prompts/symbol-preflight.d.ts +20 -0
  117. package/dist/prompts/symbol-preflight.js +49 -0
  118. package/dist/prompts/symbol-preflight.js.map +1 -0
  119. package/dist/prompts/workflow-prompts.d.ts +1 -1
  120. package/dist/prompts/workflow-prompts.js +54 -16
  121. package/dist/prompts/workflow-prompts.js.map +1 -1
  122. package/dist/providers/alpha-vantage.d.ts +1 -1
  123. package/dist/providers/alpha-vantage.js +26 -7
  124. package/dist/providers/alpha-vantage.js.map +1 -1
  125. package/dist/providers/coingecko.js +1 -1
  126. package/dist/providers/coingecko.js.map +1 -1
  127. package/dist/providers/errors.d.ts +5 -0
  128. package/dist/providers/errors.js +11 -0
  129. package/dist/providers/errors.js.map +1 -0
  130. package/dist/providers/exa-search.d.ts +2 -2
  131. package/dist/providers/exa-search.js +19 -11
  132. package/dist/providers/exa-search.js.map +1 -1
  133. package/dist/providers/external-tool-error.d.ts +10 -0
  134. package/dist/providers/external-tool-error.js +21 -0
  135. package/dist/providers/external-tool-error.js.map +1 -0
  136. package/dist/providers/fear-greed.js +1 -1
  137. package/dist/providers/fear-greed.js.map +1 -1
  138. package/dist/providers/finnhub.js +3 -5
  139. package/dist/providers/finnhub.js.map +1 -1
  140. package/dist/providers/fred.js +2 -2
  141. package/dist/providers/fred.js.map +1 -1
  142. package/dist/providers/index.d.ts +7 -6
  143. package/dist/providers/index.js +6 -5
  144. package/dist/providers/index.js.map +1 -1
  145. package/dist/providers/reddit-cli.d.ts +36 -0
  146. package/dist/providers/reddit-cli.js +201 -0
  147. package/dist/providers/reddit-cli.js.map +1 -0
  148. package/dist/providers/reddit.d.ts +1 -1
  149. package/dist/providers/reddit.js +9 -37
  150. package/dist/providers/reddit.js.map +1 -1
  151. package/dist/providers/sec-edgar.d.ts +1 -0
  152. package/dist/providers/sec-edgar.js +12 -4
  153. package/dist/providers/sec-edgar.js.map +1 -1
  154. package/dist/providers/tradingview.d.ts +47 -0
  155. package/dist/providers/tradingview.js +275 -0
  156. package/dist/providers/tradingview.js.map +1 -0
  157. package/dist/providers/twitter-cli.d.ts +40 -0
  158. package/dist/providers/twitter-cli.js +153 -0
  159. package/dist/providers/twitter-cli.js.map +1 -0
  160. package/dist/providers/twitter.d.ts +0 -8
  161. package/dist/providers/twitter.js +8 -60
  162. package/dist/providers/twitter.js.map +1 -1
  163. package/dist/providers/web-search.js +26 -12
  164. package/dist/providers/web-search.js.map +1 -1
  165. package/dist/providers/with-fallback.js +4 -2
  166. package/dist/providers/with-fallback.js.map +1 -1
  167. package/dist/providers/wrap-provider.d.ts +2 -3
  168. package/dist/providers/wrap-provider.js +44 -8
  169. package/dist/providers/wrap-provider.js.map +1 -1
  170. package/dist/providers/yahoo-finance.d.ts +1 -1
  171. package/dist/providers/yahoo-finance.js +153 -48
  172. package/dist/providers/yahoo-finance.js.map +1 -1
  173. package/dist/routing/classify-intent.d.ts +6 -0
  174. package/dist/routing/classify-intent.js +78 -7
  175. package/dist/routing/classify-intent.js.map +1 -1
  176. package/dist/routing/defaults.d.ts +1 -1
  177. package/dist/routing/entity-extractor.d.ts +1 -0
  178. package/dist/routing/entity-extractor.js +234 -29
  179. package/dist/routing/entity-extractor.js.map +1 -1
  180. package/dist/routing/fund-symbols.d.ts +2 -0
  181. package/dist/routing/fund-symbols.js +55 -0
  182. package/dist/routing/fund-symbols.js.map +1 -0
  183. package/dist/routing/horizon.d.ts +1 -0
  184. package/dist/routing/horizon.js +10 -0
  185. package/dist/routing/horizon.js.map +1 -0
  186. package/dist/routing/index.d.ts +10 -10
  187. package/dist/routing/index.js +6 -6
  188. package/dist/routing/index.js.map +1 -1
  189. package/dist/routing/planning.d.ts +2 -2
  190. package/dist/routing/planning.js +65 -34
  191. package/dist/routing/planning.js.map +1 -1
  192. package/dist/routing/route-manifest.d.ts +2 -2
  193. package/dist/routing/route-manifest.js +25 -4
  194. package/dist/routing/route-manifest.js.map +1 -1
  195. package/dist/routing/router-llm-client.js.map +1 -1
  196. package/dist/routing/router-prompt.js +7 -9
  197. package/dist/routing/router-prompt.js.map +1 -1
  198. package/dist/routing/router-types.d.ts +1 -0
  199. package/dist/routing/router.js +137 -22
  200. package/dist/routing/router.js.map +1 -1
  201. package/dist/routing/slot-resolver.d.ts +1 -1
  202. package/dist/routing/slot-resolver.js +2 -4
  203. package/dist/routing/slot-resolver.js.map +1 -1
  204. package/dist/routing/symbol-disambiguator.d.ts +11 -0
  205. package/dist/routing/symbol-disambiguator.js +52 -0
  206. package/dist/routing/symbol-disambiguator.js.map +1 -0
  207. package/dist/routing/turn-context.d.ts +1 -1
  208. package/dist/routing/turn-context.js +1 -1
  209. package/dist/routing/turn-context.js.map +1 -1
  210. package/dist/routing/types.d.ts +2 -0
  211. package/dist/runtime/answer-contracts.d.ts +1 -1
  212. package/dist/runtime/answer-contracts.js +48 -9
  213. package/dist/runtime/answer-contracts.js.map +1 -1
  214. package/dist/runtime/artifact-contracts.js.map +1 -1
  215. package/dist/runtime/planning-evidence.js +47 -26
  216. package/dist/runtime/planning-evidence.js.map +1 -1
  217. package/dist/runtime/prompt-step.d.ts +1 -9
  218. package/dist/runtime/prompt-step.js +0 -10
  219. package/dist/runtime/prompt-step.js.map +1 -1
  220. package/dist/runtime/run-context.d.ts +5 -2
  221. package/dist/runtime/run-context.js +8 -1
  222. package/dist/runtime/run-context.js.map +1 -1
  223. package/dist/runtime/session-coordinator.d.ts +13 -5
  224. package/dist/runtime/session-coordinator.js +160 -20
  225. package/dist/runtime/session-coordinator.js.map +1 -1
  226. package/dist/runtime/session-title.d.ts +14 -0
  227. package/dist/runtime/session-title.js +50 -0
  228. package/dist/runtime/session-title.js.map +1 -0
  229. package/dist/runtime/tool-defaults-wrapper.js +7 -5
  230. package/dist/runtime/tool-defaults-wrapper.js.map +1 -1
  231. package/dist/runtime/validation.js.map +1 -1
  232. package/dist/runtime/workflow-events.js.map +1 -1
  233. package/dist/runtime/workflow-runner.d.ts +3 -3
  234. package/dist/runtime/workflow-runner.js +1 -1
  235. package/dist/runtime/workflow-runner.js.map +1 -1
  236. package/dist/sentiment/adapters/finnhub.d.ts +1 -1
  237. package/dist/sentiment/adapters/finnhub.js +6 -1
  238. package/dist/sentiment/adapters/finnhub.js.map +1 -1
  239. package/dist/sentiment/adapters/reddit.d.ts +2 -2
  240. package/dist/sentiment/adapters/twitter.d.ts +1 -1
  241. package/dist/sentiment/adapters/web.d.ts +1 -1
  242. package/dist/sentiment/index.d.ts +10 -11
  243. package/dist/sentiment/index.js +10 -20
  244. package/dist/sentiment/index.js.map +1 -1
  245. package/dist/sentiment/insights.d.ts +17 -0
  246. package/dist/sentiment/insights.js +206 -0
  247. package/dist/sentiment/insights.js.map +1 -0
  248. package/dist/sentiment/keywords.js +26 -4
  249. package/dist/sentiment/keywords.js.map +1 -1
  250. package/dist/sentiment/pipeline.d.ts +2 -2
  251. package/dist/sentiment/pipeline.js +14 -2
  252. package/dist/sentiment/pipeline.js.map +1 -1
  253. package/dist/sentiment/scorer.d.ts +2 -0
  254. package/dist/sentiment/scorer.js +11 -2
  255. package/dist/sentiment/scorer.js.map +1 -1
  256. package/dist/sentiment/store.d.ts +1 -1
  257. package/dist/sentiment/store.js +1 -1
  258. package/dist/sentiment/store.js.map +1 -1
  259. package/dist/sentiment/trends.d.ts +1 -1
  260. package/dist/sentiment/trends.js.map +1 -1
  261. package/dist/sentiment/types.d.ts +2 -0
  262. package/dist/sentiment/types.js.map +1 -1
  263. package/dist/system-prompt.js +6 -9
  264. package/dist/system-prompt.js.map +1 -1
  265. package/dist/tool-kit.d.ts +7 -7
  266. package/dist/tool-kit.js +4 -4
  267. package/dist/tool-kit.js.map +1 -1
  268. package/dist/tools/fundamentals/company-overview.js +11 -6
  269. package/dist/tools/fundamentals/company-overview.js.map +1 -1
  270. package/dist/tools/fundamentals/comps.js +18 -9
  271. package/dist/tools/fundamentals/comps.js.map +1 -1
  272. package/dist/tools/fundamentals/dcf.js +23 -11
  273. package/dist/tools/fundamentals/dcf.js.map +1 -1
  274. package/dist/tools/fundamentals/earnings.js +8 -3
  275. package/dist/tools/fundamentals/earnings.js.map +1 -1
  276. package/dist/tools/fundamentals/financials.js +8 -3
  277. package/dist/tools/fundamentals/financials.js.map +1 -1
  278. package/dist/tools/fundamentals/sec-filings.js +21 -6
  279. package/dist/tools/fundamentals/sec-filings.js.map +1 -1
  280. package/dist/tools/index.d.ts +27 -20
  281. package/dist/tools/index.js +55 -43
  282. package/dist/tools/index.js.map +1 -1
  283. package/dist/tools/interaction/ask-user.js +15 -3
  284. package/dist/tools/interaction/ask-user.js.map +1 -1
  285. package/dist/tools/macro/fear-greed.js.map +1 -1
  286. package/dist/tools/macro/fred-data.d.ts +1 -1
  287. package/dist/tools/macro/fred-data.js +17 -6
  288. package/dist/tools/macro/fred-data.js.map +1 -1
  289. package/dist/tools/market/crypto-history.js +3 -1
  290. package/dist/tools/market/crypto-history.js.map +1 -1
  291. package/dist/tools/market/crypto-price.js +3 -1
  292. package/dist/tools/market/crypto-price.js.map +1 -1
  293. package/dist/tools/market/screen-stocks.d.ts +18 -0
  294. package/dist/tools/market/screen-stocks.js +252 -0
  295. package/dist/tools/market/screen-stocks.js.map +1 -0
  296. package/dist/tools/market/search-ticker.js +160 -8
  297. package/dist/tools/market/search-ticker.js.map +1 -1
  298. package/dist/tools/market/stock-history.d.ts +2 -2
  299. package/dist/tools/market/stock-history.js +26 -7
  300. package/dist/tools/market/stock-history.js.map +1 -1
  301. package/dist/tools/market/stock-quote.js +5 -3
  302. package/dist/tools/market/stock-quote.js.map +1 -1
  303. package/dist/tools/options/greeks.js +1 -1
  304. package/dist/tools/options/greeks.js.map +1 -1
  305. package/dist/tools/options/option-chain.js +19 -6
  306. package/dist/tools/options/option-chain.js.map +1 -1
  307. package/dist/tools/portfolio/alerts.d.ts +15 -0
  308. package/dist/tools/portfolio/alerts.js +357 -0
  309. package/dist/tools/portfolio/alerts.js.map +1 -0
  310. package/dist/tools/portfolio/correlation.d.ts +1 -1
  311. package/dist/tools/portfolio/correlation.js +33 -13
  312. package/dist/tools/portfolio/correlation.js.map +1 -1
  313. package/dist/tools/portfolio/daily-report.d.ts +8 -0
  314. package/dist/tools/portfolio/daily-report.js +83 -0
  315. package/dist/tools/portfolio/daily-report.js.map +1 -0
  316. package/dist/tools/portfolio/holdings-overlap.js +10 -3
  317. package/dist/tools/portfolio/holdings-overlap.js.map +1 -1
  318. package/dist/tools/portfolio/notifications.d.ts +7 -0
  319. package/dist/tools/portfolio/notifications.js +43 -0
  320. package/dist/tools/portfolio/notifications.js.map +1 -0
  321. package/dist/tools/portfolio/predictions.d.ts +12 -6
  322. package/dist/tools/portfolio/predictions.js +337 -87
  323. package/dist/tools/portfolio/predictions.js.map +1 -1
  324. package/dist/tools/portfolio/risk-analysis.d.ts +1 -1
  325. package/dist/tools/portfolio/risk-analysis.js +45 -6
  326. package/dist/tools/portfolio/risk-analysis.js.map +1 -1
  327. package/dist/tools/portfolio/tracker.d.ts +4 -3
  328. package/dist/tools/portfolio/tracker.js +246 -101
  329. package/dist/tools/portfolio/tracker.js.map +1 -1
  330. package/dist/tools/portfolio/watchlist.d.ts +6 -4
  331. package/dist/tools/portfolio/watchlist.js +208 -108
  332. package/dist/tools/portfolio/watchlist.js.map +1 -1
  333. package/dist/tools/sentiment/insight-format.d.ts +2 -0
  334. package/dist/tools/sentiment/insight-format.js +36 -0
  335. package/dist/tools/sentiment/insight-format.js.map +1 -0
  336. package/dist/tools/sentiment/query-match.d.ts +3 -0
  337. package/dist/tools/sentiment/query-match.js +113 -0
  338. package/dist/tools/sentiment/query-match.js.map +1 -0
  339. package/dist/tools/sentiment/reddit-sentiment.d.ts +12 -1
  340. package/dist/tools/sentiment/reddit-sentiment.js +266 -107
  341. package/dist/tools/sentiment/reddit-sentiment.js.map +1 -1
  342. package/dist/tools/sentiment/sentiment-summary.d.ts +9 -1
  343. package/dist/tools/sentiment/sentiment-summary.js +223 -205
  344. package/dist/tools/sentiment/sentiment-summary.js.map +1 -1
  345. package/dist/tools/sentiment/sentiment-trend.d.ts +1 -1
  346. package/dist/tools/sentiment/sentiment-trend.js +12 -2
  347. package/dist/tools/sentiment/sentiment-trend.js.map +1 -1
  348. package/dist/tools/sentiment/twitter-sentiment.d.ts +11 -1
  349. package/dist/tools/sentiment/twitter-sentiment.js +188 -58
  350. package/dist/tools/sentiment/twitter-sentiment.js.map +1 -1
  351. package/dist/tools/sentiment/untrusted-text.d.ts +2 -0
  352. package/dist/tools/sentiment/untrusted-text.js +17 -0
  353. package/dist/tools/sentiment/untrusted-text.js.map +1 -0
  354. package/dist/tools/sentiment/web-search.js +9 -13
  355. package/dist/tools/sentiment/web-search.js.map +1 -1
  356. package/dist/tools/sentiment/web-sentiment.js +19 -3
  357. package/dist/tools/sentiment/web-sentiment.js.map +1 -1
  358. package/dist/tools/technical/backtest.d.ts +1 -1
  359. package/dist/tools/technical/backtest.js +27 -20
  360. package/dist/tools/technical/backtest.js.map +1 -1
  361. package/dist/tools/technical/indicators.js +23 -5
  362. package/dist/tools/technical/indicators.js.map +1 -1
  363. package/dist/types/index.d.ts +3 -3
  364. package/dist/types/index.js.map +1 -1
  365. package/dist/types/market.d.ts +1 -0
  366. package/dist/types/portfolio.d.ts +14 -4
  367. package/dist/types/sentiment.d.ts +52 -0
  368. package/dist/workflows/compare-assets.d.ts +0 -3
  369. package/dist/workflows/compare-assets.js +20 -11
  370. package/dist/workflows/compare-assets.js.map +1 -1
  371. package/dist/workflows/index.d.ts +3 -4
  372. package/dist/workflows/index.js +3 -3
  373. package/dist/workflows/index.js.map +1 -1
  374. package/dist/workflows/options-screener.d.ts +0 -3
  375. package/dist/workflows/options-screener.js +4 -11
  376. package/dist/workflows/options-screener.js.map +1 -1
  377. package/dist/workflows/portfolio-builder.d.ts +0 -3
  378. package/dist/workflows/portfolio-builder.js +0 -8
  379. package/dist/workflows/portfolio-builder.js.map +1 -1
  380. package/gui/server/ask-user-bridge.ts +1 -1
  381. package/gui/server/automation-heartbeat.ts +97 -0
  382. package/gui/server/background-quotes.ts +97 -1
  383. package/gui/server/chat-event-adapter.ts +32 -10
  384. package/gui/server/chat-run-session.ts +16 -0
  385. package/gui/server/invoke-tool.ts +160 -3
  386. package/gui/server/live-chat-event-adapter.ts +21 -6
  387. package/gui/server/market-state-api.ts +315 -0
  388. package/gui/server/model-setup.ts +156 -2
  389. package/gui/server/private-api-access.ts +62 -0
  390. package/gui/server/projector.ts +18 -9
  391. package/gui/server/prompt-observation.ts +4 -7
  392. package/gui/server/quote-snapshot-store.ts +50 -0
  393. package/gui/server/server.ts +218 -451
  394. package/gui/server/session-actions.ts +186 -1
  395. package/gui/server/shutdown.ts +47 -0
  396. package/gui/server/tool-invoke-ack.ts +49 -0
  397. package/gui/server/tool-metadata.ts +101 -24
  398. package/gui/server/websocket.ts +13 -3
  399. package/gui/server/writer-lock.ts +6 -2
  400. package/gui/server/ws-hub.ts +311 -0
  401. package/gui/shared/chat-events.ts +16 -1
  402. package/gui/shared/event-reducer.ts +24 -6
  403. package/gui/web/dist/assets/CatalogOverlay-CgeY5Pkp.js +1 -0
  404. package/gui/web/dist/assets/index-C6W_2eAn.js +69 -0
  405. package/gui/web/dist/assets/index-hwbx24a5.css +1 -0
  406. package/gui/web/dist/index.html +2 -2
  407. package/package.json +9 -6
  408. package/src/analysts/contracts.ts +10 -23
  409. package/src/analysts/orchestrator.ts +8 -43
  410. package/src/cli.ts +76 -12
  411. package/src/config.ts +44 -9
  412. package/src/index.ts +1 -1
  413. package/src/infra/cache.ts +41 -30
  414. package/src/infra/http-client.ts +72 -6
  415. package/src/infra/index.ts +6 -10
  416. package/src/infra/native-dependencies.ts +8 -3
  417. package/src/infra/node-version.ts +3 -1
  418. package/src/infra/opencandle-paths.ts +3 -14
  419. package/src/infra/rate-limiter.ts +22 -19
  420. package/src/market-state/alert-conditions.ts +82 -0
  421. package/src/market-state/alert-runner.ts +863 -0
  422. package/src/market-state/daily-report.ts +247 -0
  423. package/src/market-state/local-automation-service.ts +162 -0
  424. package/src/market-state/notification-delivery.ts +158 -0
  425. package/src/market-state/resolve-for-mutation.ts +24 -0
  426. package/src/market-state/resolve.ts +112 -0
  427. package/src/market-state/service.ts +2344 -0
  428. package/src/memory/index.ts +7 -7
  429. package/src/memory/manager.ts +14 -16
  430. package/src/memory/retrieval.ts +8 -7
  431. package/src/memory/sqlite.ts +407 -6
  432. package/src/memory/storage.ts +5 -15
  433. package/src/memory/tool-defaults.ts +60 -39
  434. package/src/memory/types.ts +3 -3
  435. package/src/monitor.ts +121 -0
  436. package/src/onboarding/connect.ts +24 -31
  437. package/src/onboarding/credential-interceptor.ts +3 -15
  438. package/src/onboarding/degradation-accumulator.ts +1 -3
  439. package/src/onboarding/provider-status.ts +410 -0
  440. package/src/onboarding/providers.ts +144 -45
  441. package/src/onboarding/state.ts +13 -15
  442. package/src/onboarding/tool-helpers.ts +2 -9
  443. package/src/onboarding/tool-tags.ts +51 -8
  444. package/src/onboarding/validation.ts +16 -22
  445. package/src/pi/opencandle-extension.ts +643 -101
  446. package/src/pi/session.ts +7 -5
  447. package/src/pi/setup.ts +61 -43
  448. package/src/pi/tool-adapter.ts +19 -6
  449. package/src/prompts/context-builder.ts +24 -13
  450. package/src/prompts/policy-cards.ts +3 -3
  451. package/src/prompts/sections.ts +1 -1
  452. package/src/prompts/symbol-preflight.ts +80 -0
  453. package/src/prompts/workflow-prompts.ts +77 -28
  454. package/src/providers/alpha-vantage.ts +58 -39
  455. package/src/providers/coingecko.ts +2 -5
  456. package/src/providers/errors.ts +9 -0
  457. package/src/providers/exa-search.ts +24 -22
  458. package/src/providers/external-tool-error.ts +20 -0
  459. package/src/providers/fear-greed.ts +1 -1
  460. package/src/providers/finnhub.ts +7 -6
  461. package/src/providers/fred.ts +3 -3
  462. package/src/providers/index.ts +14 -6
  463. package/src/providers/reddit-cli.ts +317 -0
  464. package/src/providers/reddit.ts +14 -59
  465. package/src/providers/sec-edgar.ts +20 -6
  466. package/src/providers/tradingview.ts +399 -0
  467. package/src/providers/twitter-cli.ts +233 -0
  468. package/src/providers/twitter.ts +8 -79
  469. package/src/providers/web-search.ts +30 -20
  470. package/src/providers/with-fallback.ts +8 -7
  471. package/src/providers/wrap-provider.ts +49 -10
  472. package/src/providers/yahoo-finance.ts +204 -66
  473. package/src/routing/classify-intent.ts +101 -10
  474. package/src/routing/defaults.ts +1 -1
  475. package/src/routing/entity-extractor.ts +287 -38
  476. package/src/routing/fund-symbols.ts +58 -0
  477. package/src/routing/horizon.ts +7 -0
  478. package/src/routing/index.ts +48 -48
  479. package/src/routing/planning.ts +145 -53
  480. package/src/routing/route-manifest.ts +37 -15
  481. package/src/routing/router-llm-client.ts +4 -4
  482. package/src/routing/router-prompt.ts +15 -19
  483. package/src/routing/router-types.ts +2 -5
  484. package/src/routing/router.ts +251 -53
  485. package/src/routing/slot-resolver.ts +34 -11
  486. package/src/routing/symbol-disambiguator.ts +72 -0
  487. package/src/routing/turn-context.ts +6 -9
  488. package/src/routing/types.ts +2 -0
  489. package/src/runtime/answer-contracts.ts +105 -45
  490. package/src/runtime/artifact-contracts.ts +2 -1
  491. package/src/runtime/planning-evidence.ts +157 -66
  492. package/src/runtime/prompt-step.ts +1 -16
  493. package/src/runtime/run-context.ts +12 -2
  494. package/src/runtime/session-coordinator.ts +238 -63
  495. package/src/runtime/session-title.ts +60 -0
  496. package/src/runtime/tool-defaults-wrapper.ts +13 -5
  497. package/src/runtime/validation.ts +1 -4
  498. package/src/runtime/workflow-events.ts +7 -7
  499. package/src/runtime/workflow-runner.ts +5 -11
  500. package/src/sentiment/adapters/finnhub.ts +7 -2
  501. package/src/sentiment/adapters/reddit.ts +2 -2
  502. package/src/sentiment/adapters/twitter.ts +1 -1
  503. package/src/sentiment/adapters/web.ts +1 -1
  504. package/src/sentiment/index.ts +17 -26
  505. package/src/sentiment/insights.ts +269 -0
  506. package/src/sentiment/keywords.ts +26 -4
  507. package/src/sentiment/pipeline.ts +28 -5
  508. package/src/sentiment/scorer.ts +13 -2
  509. package/src/sentiment/store.ts +2 -2
  510. package/src/sentiment/trends.ts +9 -3
  511. package/src/sentiment/types.ts +8 -4
  512. package/src/system-prompt.ts +6 -9
  513. package/src/tool-kit.ts +10 -9
  514. package/src/tools/fundamentals/company-overview.ts +19 -9
  515. package/src/tools/fundamentals/comps.ts +68 -55
  516. package/src/tools/fundamentals/dcf.ts +145 -95
  517. package/src/tools/fundamentals/earnings.ts +16 -6
  518. package/src/tools/fundamentals/financials.ts +16 -7
  519. package/src/tools/fundamentals/sec-filings.ts +37 -16
  520. package/src/tools/index.ts +56 -43
  521. package/src/tools/interaction/ask-user.ts +22 -10
  522. package/src/tools/macro/fear-greed.ts +1 -1
  523. package/src/tools/macro/fred-data.ts +58 -46
  524. package/src/tools/market/crypto-history.ts +8 -3
  525. package/src/tools/market/crypto-price.ts +6 -6
  526. package/src/tools/market/screen-stocks.ts +279 -0
  527. package/src/tools/market/search-ticker.ts +218 -17
  528. package/src/tools/market/stock-history.ts +37 -12
  529. package/src/tools/market/stock-quote.ts +10 -7
  530. package/src/tools/options/greeks.ts +5 -5
  531. package/src/tools/options/option-chain.ts +41 -17
  532. package/src/tools/portfolio/alerts.ts +457 -0
  533. package/src/tools/portfolio/correlation.ts +47 -20
  534. package/src/tools/portfolio/daily-report.ts +101 -0
  535. package/src/tools/portfolio/holdings-overlap.ts +31 -15
  536. package/src/tools/portfolio/notifications.ts +45 -0
  537. package/src/tools/portfolio/predictions.ts +406 -106
  538. package/src/tools/portfolio/risk-analysis.ts +46 -7
  539. package/src/tools/portfolio/tracker.ts +270 -109
  540. package/src/tools/portfolio/watchlist.ts +250 -121
  541. package/src/tools/sentiment/insight-format.ts +50 -0
  542. package/src/tools/sentiment/query-match.ts +117 -0
  543. package/src/tools/sentiment/reddit-sentiment.ts +360 -121
  544. package/src/tools/sentiment/sentiment-summary.ts +302 -235
  545. package/src/tools/sentiment/sentiment-trend.ts +24 -7
  546. package/src/tools/sentiment/twitter-sentiment.ts +264 -73
  547. package/src/tools/sentiment/untrusted-text.ts +21 -0
  548. package/src/tools/sentiment/web-search.ts +21 -18
  549. package/src/tools/sentiment/web-sentiment.ts +30 -10
  550. package/src/tools/technical/backtest.ts +32 -22
  551. package/src/tools/technical/indicators.ts +39 -14
  552. package/src/types/index.ts +8 -3
  553. package/src/types/market.ts +1 -0
  554. package/src/types/portfolio.ts +14 -4
  555. package/src/types/sentiment.ts +61 -2
  556. package/src/workflows/compare-assets.ts +33 -21
  557. package/src/workflows/index.ts +3 -4
  558. package/src/workflows/options-screener.ts +27 -29
  559. package/src/workflows/portfolio-builder.ts +34 -27
  560. package/dist/infra/browser.d.ts +0 -35
  561. package/dist/infra/browser.js +0 -103
  562. package/dist/infra/browser.js.map +0 -1
  563. package/dist/tools/interaction/twitter-login.d.ts +0 -8
  564. package/dist/tools/interaction/twitter-login.js +0 -77
  565. package/dist/tools/interaction/twitter-login.js.map +0 -1
  566. package/dist/workflows/types.d.ts +0 -4
  567. package/dist/workflows/types.js +0 -2
  568. package/dist/workflows/types.js.map +0 -1
  569. package/gui/web/dist/assets/CatalogOverlay-Bmp6Knu7.js +0 -1
  570. package/gui/web/dist/assets/index-Bxt9QpLX.css +0 -1
  571. package/gui/web/dist/assets/index-CZ9DHZYy.js +0 -67
  572. package/src/infra/browser.ts +0 -111
  573. package/src/tools/interaction/twitter-login.ts +0 -93
  574. package/src/workflows/types.ts +0 -4
@@ -0,0 +1,311 @@
1
+ import type { IncomingMessage } from "node:http";
2
+ import type { Duplex } from "node:stream";
3
+ import {
4
+ type AgentSession,
5
+ type SessionEntry,
6
+ SessionManager,
7
+ } from "@earendil-works/pi-coding-agent";
8
+ import { probeProviderStatus } from "../../src/onboarding/provider-status.js";
9
+ import { getProvider, type ProviderId } from "../../src/onboarding/providers.js";
10
+ import {
11
+ clearProviderOnboardingEntry,
12
+ loadOnboardingState,
13
+ saveOnboardingState,
14
+ } from "../../src/onboarding/state.js";
15
+ import type { ChatEvent } from "../shared/chat-events.js";
16
+ import type { BackgroundQuoteRefreshes } from "./background-quotes.js";
17
+ import { sessionEntriesToChatEvents } from "./chat-event-adapter.js";
18
+ import type { ToolInvokeController } from "./invoke-tool.js";
19
+ import type { ModelSetupController } from "./model-setup.js";
20
+ import { projectDashboard } from "./projector.js";
21
+ import type { SessionActionsController } from "./session-actions.js";
22
+ import { buildCatalog, setToolEnabled } from "./tool-metadata.js";
23
+ import { acceptWebSocket, type WsClient } from "./websocket.js";
24
+
25
+ interface AskUserBridge {
26
+ getPrompts(): unknown[];
27
+ }
28
+
29
+ export interface WsHub {
30
+ handleUpgrade(req: IncomingMessage, socket: Duplex): void;
31
+ getClientCount(): number;
32
+ closeClients(): void;
33
+ sendBoot(client: WsClient): void;
34
+ buildBootstrapPayload(): Promise<Record<string, unknown>>;
35
+ broadcast(message: unknown): void;
36
+ broadcastModelSetup(): void;
37
+ broadcastState(): void;
38
+ broadcastSessions(): void;
39
+ buildStateSnapshot(): {
40
+ sessionId: string;
41
+ state: unknown;
42
+ entries: SessionEntry[];
43
+ events: ChatEvent[];
44
+ };
45
+ currentChatEvents(entries?: SessionEntry[]): ChatEvent[];
46
+ subscribeToSessionEvents(): () => void;
47
+ }
48
+
49
+ export interface WsHubOptions {
50
+ role: string;
51
+ lock: unknown;
52
+ cwd: string;
53
+ sessionDir: string;
54
+ getSession: () => AgentSession;
55
+ getSessionManager: () => SessionManager;
56
+ backgroundQuoteRefreshes: BackgroundQuoteRefreshes;
57
+ askUserBridge: AskUserBridge;
58
+ modelSetupController: ModelSetupController;
59
+ toolInvokeController: ToolInvokeController;
60
+ sessionActionsController: SessionActionsController;
61
+ onClientCountChanged: () => void;
62
+ isTrustedRequest?: (req: IncomingMessage) => boolean;
63
+ acceptWebSocketFn?: typeof acceptWebSocket;
64
+ }
65
+
66
+ export function createWsHub({
67
+ role,
68
+ lock,
69
+ cwd,
70
+ sessionDir,
71
+ getSession,
72
+ getSessionManager,
73
+ backgroundQuoteRefreshes,
74
+ askUserBridge,
75
+ modelSetupController,
76
+ toolInvokeController,
77
+ sessionActionsController,
78
+ onClientCountChanged,
79
+ isTrustedRequest = () => true,
80
+ acceptWebSocketFn = acceptWebSocket,
81
+ }: WsHubOptions): WsHub {
82
+ const clients = new Set<WsClient>();
83
+
84
+ function handleUpgrade(req: IncomingMessage, socket: Duplex): void {
85
+ if (req.url !== "/ws") {
86
+ socket.destroy();
87
+ return;
88
+ }
89
+ if (!isTrustedRequest(req)) {
90
+ socket.destroy();
91
+ return;
92
+ }
93
+
94
+ const client = acceptWebSocketFn(req, socket);
95
+ clients.add(client);
96
+ client.onClose(() => {
97
+ clients.delete(client);
98
+ onClientCountChanged();
99
+ });
100
+ client.onMessage((message) => void handleClientMessage(client, message));
101
+ sendBoot(client);
102
+ onClientCountChanged();
103
+ }
104
+
105
+ async function handleClientMessage(client: WsClient, message: unknown): Promise<void> {
106
+ const data = asRecord(message);
107
+ try {
108
+ switch (data.type) {
109
+ case "chat.prompt":
110
+ await sessionActionsController.handlePrompt(String(data.prompt ?? ""));
111
+ break;
112
+ case "ask_user.answer":
113
+ await sessionActionsController.handleAskUserAnswer(String(data.id ?? ""), data.answer);
114
+ break;
115
+ case "ask_user.cancel":
116
+ await sessionActionsController.handleAskUserCancel(String(data.id ?? ""));
117
+ break;
118
+ case "tool.invoke":
119
+ await toolInvokeController.handleToolInvokeMessage(client, data);
120
+ break;
121
+ case "tool.enabled":
122
+ if (role !== "writer") throw new Error("Read-only follower mode");
123
+ setToolEnabled(String(data.toolName), Boolean(data.enabled));
124
+ broadcast({ type: "catalog", catalog: buildCatalog(), restartRequired: true });
125
+ break;
126
+ case "catalog.refresh":
127
+ client.send({ type: "catalog", catalog: buildCatalog() });
128
+ break;
129
+ case "model.setup.refresh":
130
+ getSession().modelRegistry.refresh();
131
+ broadcastModelSetup();
132
+ break;
133
+ case "model.setup.save_api_key":
134
+ await modelSetupController.handleSaveModelApiKey(
135
+ String(data.provider ?? ""),
136
+ String(data.apiKey ?? ""),
137
+ );
138
+ broadcastModelSetup();
139
+ break;
140
+ case "model.setup.select_model":
141
+ await modelSetupController.handleSelectModel(
142
+ String(data.provider ?? ""),
143
+ String(data.modelId ?? ""),
144
+ );
145
+ broadcastModelSetup();
146
+ break;
147
+ case "provider.save_api_key":
148
+ await modelSetupController.handleSaveProviderApiKey(
149
+ String(data.providerId ?? ""),
150
+ String(data.apiKey ?? ""),
151
+ );
152
+ broadcast({ type: "catalog", catalog: buildCatalog() });
153
+ break;
154
+ case "provider.status.check": {
155
+ const providerId = String(data.providerId ?? "") as ProviderId;
156
+ getProvider(providerId);
157
+ const mode = data.mode === "session" ? "session" : "install";
158
+ if (data.reenable === true) {
159
+ saveOnboardingState(clearProviderOnboardingEntry(loadOnboardingState(), providerId));
160
+ broadcast({ type: "catalog", catalog: buildCatalog() });
161
+ }
162
+ const status = await probeProviderStatus(providerId, { mode, force: true });
163
+ client.send({ type: "provider.status", providerId, status });
164
+ break;
165
+ }
166
+ case "session.new":
167
+ await sessionActionsController.handleNewSession();
168
+ sendBoot(client);
169
+ broadcastState();
170
+ broadcastSessions();
171
+ break;
172
+ case "session.open":
173
+ await sessionActionsController.handleOpenSession(String(data.path ?? ""));
174
+ sendBoot(client);
175
+ broadcastState();
176
+ broadcastSessions();
177
+ break;
178
+ case "session.rename":
179
+ await sessionActionsController.handleRenameSession(
180
+ String(data.path ?? ""),
181
+ String(data.name ?? ""),
182
+ );
183
+ broadcastState();
184
+ broadcastSessions();
185
+ break;
186
+ case "session.delete":
187
+ await sessionActionsController.handleDeleteSession(client, String(data.path ?? ""));
188
+ break;
189
+ }
190
+ } catch (error) {
191
+ const errorMessage = error instanceof Error ? error.message : String(error);
192
+ client.send({
193
+ type: "error",
194
+ message: errorMessage,
195
+ });
196
+ }
197
+ }
198
+
199
+ function getClientCount(): number {
200
+ return clients.size;
201
+ }
202
+
203
+ function closeClients(): void {
204
+ for (const client of clients) client.close();
205
+ clients.clear();
206
+ }
207
+
208
+ function sendBoot(client: WsClient): void {
209
+ const snapshot = buildStateSnapshot();
210
+ client.send({
211
+ type: "boot",
212
+ role,
213
+ lock,
214
+ sessionId: getSessionManager().getSessionId(),
215
+ catalog: buildCatalog(),
216
+ modelSetup: modelSetupController.buildCurrentModelSetupState(),
217
+ askUserPrompts: askUserBridge.getPrompts(),
218
+ });
219
+ client.send({
220
+ type: "state.snapshot",
221
+ ...snapshot,
222
+ });
223
+ void SessionManager.list(cwd, sessionDir).then((sessions) =>
224
+ client.send({ type: "sessions", sessions }),
225
+ );
226
+ }
227
+
228
+ async function buildBootstrapPayload(): Promise<Record<string, unknown>> {
229
+ return {
230
+ role,
231
+ sessionId: getSessionManager().getSessionId(),
232
+ catalog: buildCatalog(),
233
+ modelSetup: modelSetupController.buildCurrentModelSetupState(),
234
+ askUserPrompts: askUserBridge.getPrompts(),
235
+ sessions: await SessionManager.list(cwd, sessionDir),
236
+ snapshot: buildStateSnapshot(),
237
+ };
238
+ }
239
+
240
+ function broadcastModelSetup(): void {
241
+ broadcast({
242
+ type: "model.setup",
243
+ modelSetup: modelSetupController.buildCurrentModelSetupState(),
244
+ });
245
+ }
246
+
247
+ function broadcastState(): void {
248
+ broadcast({
249
+ type: "state.snapshot",
250
+ ...buildStateSnapshot(),
251
+ });
252
+ }
253
+
254
+ function buildStateSnapshot() {
255
+ const sessionManager = getSessionManager();
256
+ const sessionId = sessionManager.getSessionId();
257
+ const entries = sessionManager.getEntries();
258
+ return {
259
+ sessionId,
260
+ state: projectDashboard(backgroundQuoteRefreshes.withEntries(entries), sessionId),
261
+ entries,
262
+ events: currentChatEvents(entries),
263
+ };
264
+ }
265
+
266
+ function currentChatEvents(entries = getSessionManager().getEntries()): ChatEvent[] {
267
+ const sessionManager = getSessionManager();
268
+ return sessionEntriesToChatEvents(entries, {
269
+ sessionId: sessionManager.getSessionId(),
270
+ title: sessionManager.getSessionName(),
271
+ });
272
+ }
273
+
274
+ function broadcastSessions(): void {
275
+ void SessionManager.list(cwd, sessionDir).then((sessions) =>
276
+ broadcast({ type: "sessions", sessions }),
277
+ );
278
+ }
279
+
280
+ function broadcast(message: unknown): void {
281
+ for (const client of clients) client.send(message);
282
+ }
283
+
284
+ function subscribeToSessionEvents(): () => void {
285
+ return getSession().subscribe((event) => {
286
+ broadcast({ type: "session.event", event });
287
+ broadcastState();
288
+ });
289
+ }
290
+
291
+ return {
292
+ handleUpgrade,
293
+ getClientCount,
294
+ closeClients,
295
+ sendBoot,
296
+ buildBootstrapPayload,
297
+ broadcast,
298
+ broadcastModelSetup,
299
+ broadcastState,
300
+ broadcastSessions,
301
+ buildStateSnapshot,
302
+ currentChatEvents,
303
+ subscribeToSessionEvents,
304
+ };
305
+ }
306
+
307
+ function asRecord(value: unknown): Record<string, unknown> {
308
+ return typeof value === "object" && value !== null && !Array.isArray(value)
309
+ ? (value as Record<string, unknown>)
310
+ : {};
311
+ }
@@ -51,7 +51,21 @@ export type ChatEvent =
51
51
  | { type: "message.created"; messageId: string; role: ChatRole; seq: number }
52
52
  | { type: "message.delta"; messageId: string; text: string; seq: number }
53
53
  | { type: "message.completed"; messageId: string; content: MessageContent[]; seq: number }
54
- | { type: "tool.started"; toolCallId: string; messageId: string; name: string; input: unknown; seq: number }
54
+ | {
55
+ type: "custom.message";
56
+ messageId: string;
57
+ customType: string;
58
+ content: MessageContent[];
59
+ seq: number;
60
+ }
61
+ | {
62
+ type: "tool.started";
63
+ toolCallId: string;
64
+ messageId: string;
65
+ name: string;
66
+ input: unknown;
67
+ seq: number;
68
+ }
55
69
  | { type: "tool.delta"; toolCallId: string; chunk: unknown; seq: number }
56
70
  | { type: "tool.completed"; toolCallId: string; output: ToolOutput; seq: number }
57
71
  | { type: "tool.failed"; toolCallId: string; error: ToolError; seq: number }
@@ -65,6 +79,7 @@ export interface RenderMessage {
65
79
  status: "streaming" | "completed";
66
80
  content: MessageContent[];
67
81
  text: string;
82
+ customType?: string;
68
83
  }
69
84
 
70
85
  export interface RenderToolCall {
@@ -1,7 +1,7 @@
1
1
  import {
2
- createChatRenderState,
3
2
  type ChatEvent,
4
3
  type ChatRenderState,
4
+ createChatRenderState,
5
5
  type MessageContent,
6
6
  type RenderMessage,
7
7
  } from "./chat-events.js";
@@ -66,6 +66,15 @@ export function applyChatEvent(state: ChatRenderState, event: ChatEvent): ChatRe
66
66
  break;
67
67
  }
68
68
 
69
+ case "custom.message": {
70
+ const message = ensureMessage(next, event.messageId, "assistant");
71
+ message.status = "completed";
72
+ message.content = event.content;
73
+ message.text = contentText(event.content);
74
+ message.customType = event.customType;
75
+ break;
76
+ }
77
+
69
78
  case "tool.started":
70
79
  ensureMessage(next, event.messageId, "assistant");
71
80
  next.tools.set(event.toolCallId, {
@@ -132,7 +141,11 @@ export function applyChatEvent(state: ChatRenderState, event: ChatEvent): ChatRe
132
141
  return next;
133
142
  }
134
143
 
135
- function ensureMessage(state: ChatRenderState, id: string, role: RenderMessage["role"]): RenderMessage {
144
+ function ensureMessage(
145
+ state: ChatRenderState,
146
+ id: string,
147
+ role: RenderMessage["role"],
148
+ ): RenderMessage {
136
149
  const existing = state.messageById.get(id);
137
150
  if (existing) return existing;
138
151
 
@@ -159,10 +172,15 @@ function cloneState(state: ChatRenderState): ChatRenderState {
159
172
  seenSeq: new Set(state.seenSeq),
160
173
  messages,
161
174
  messageById,
162
- tools: new Map([...state.tools].map(([id, tool]) => [id, {
163
- ...tool,
164
- chunks: [...tool.chunks],
165
- }])),
175
+ tools: new Map(
176
+ [...state.tools].map(([id, tool]) => [
177
+ id,
178
+ {
179
+ ...tool,
180
+ chunks: [...tool.chunks],
181
+ },
182
+ ]),
183
+ ),
166
184
  runs: new Map([...state.runs].map(([id, run]) => [id, { ...run }])),
167
185
  thinking: new Map([...state.thinking].map(([id, thinking]) => [id, { ...thinking }])),
168
186
  session: state.session ? { ...state.session } : undefined,
@@ -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 _}from"./index-C6W_2eAn.js";var v=l(`arrow-right`,[[`path`,{d:`M5 12h14`,key:`1ays0h`}],[`path`,{d:`m12 5 7 7-7 7`,key:`xquz4c`}]]),y=l(`chevron-left`,[[`path`,{d:`m15 18-6-6 6-6`,key:`1wnfg3`}]]),b=l(`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`}]]),x=l(`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`}]]),ee=l(`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`}]]),S=l(`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=l(`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=l(`refresh-cw`,[[`path`,{d:`M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8`,key:`v9h5vc`}],[`path`,{d:`M21 3v5h-5`,key:`1q7to0`}],[`path`,{d:`M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16`,key:`3uifl3`}],[`path`,{d:`M8 16H3v5`,key:`1cv678`}]]),T=l(`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`}]]),E=l(`terminal`,[[`path`,{d:`M12 19h8`,key:`baeox8`}],[`path`,{d:`m4 17 6-6-6-6`,key:`1yngyt`}]]),D=_(e(),1),te=[{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`}],ne=[{value:`6mo`,label:`6M`},{value:`1y`,label:`1Y`},{value:`2y`,label:`2Y`}],re=[{value:`hours`,label:`Hours`},{value:`day`,label:`Day`},{value:`week`,label:`Week`},{value:`month`,label:`Month`}],ie=[{value:6,label:`6h`},{value:24,label:`24h`},{value:72,label:`3d`},{value:168,label:`7d`}],O=[{value:7,label:`7d`},{value:30,label:`30d`},{value:90,label:`90d`},{value:180,label:`6M`},{value:365,label:`1Y`}],k=a();function A({label:e,hint:t,required:n=!1,children:r,className:i}){return(0,k.jsxs)(`label`,{className:o(`grid gap-1.5`,i),children:[(0,k.jsxs)(`span`,{className:`flex items-baseline justify-between gap-3 text-xs font-medium text-foreground`,children:[(0,k.jsxs)(`span`,{children:[e,n?(0,k.jsxs)(`span`,{className:`text-foreground/40`,"aria-hidden":`true`,children:[` `,`*`]}):null]}),t?(0,k.jsx)(`span`,{className:`text-[11px] font-normal text-muted-foreground`,children:t}):null]}),r]})}function ae({value:e,onChange:t,options:n,ariaLabel:r}){return(0,k.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,k.jsx)(`button`,{type:`button`,role:`radio`,"aria-checked":r,onClick:()=>t(n.value),className:o(`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 oe({value:e,onChange:t,options:n,placeholder:r,ariaLabel:a}){return(0,k.jsxs)(`div`,{className:`relative`,children:[(0,k.jsxs)(`select`,{"aria-label":a,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,k.jsx)(`option`,{value:``,disabled:!0,hidden:!0,children:r}):null,n.map(e=>(0,k.jsx)(`option`,{value:e.value,children:e.label},e.value))]}),(0,k.jsx)(i,{"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 se({value:e,onChange:t,presets:n,suffix:r,min:i,max:a,step:s=1,placeholder:c}){let l=n.some(t=>t.value===e);return(0,k.jsxs)(`div`,{className:`grid gap-2`,children:[(0,k.jsx)(`div`,{className:`flex flex-wrap items-center gap-1.5`,children:n.map(n=>(0,k.jsx)(`button`,{type:`button`,onClick:()=>t(n.value),className:o(`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,k.jsxs)(`div`,{className:`relative w-32`,children:[(0,k.jsx)(p,{type:`number`,inputMode:`numeric`,value:l?``:e??``,min:i,max:a,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,k.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 ce({value:e,onChange:t,lookup:n,placeholder:r=`AAPL`,ariaLabel:i}){let[a,o]=(0,D.useState)(!1),[s,c]=(0,D.useState)({query:``,items:[]}),[l,u]=(0,D.useState)(``),d=(0,D.useRef)(null),f=String(e||``).trim(),m=s.query===f?s.items:[],h=l===f&&f.length>0;return(0,D.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,k.jsxs)(`div`,{className:`relative`,children:[(0,k.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,k.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,k.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,k.jsx)(`span`,{className:`font-medium tabular-nums text-foreground`,children:e.symbol}),(0,k.jsx)(`span`,{className:`truncate text-xs text-muted-foreground`,children:e.name})]},e.symbol))}):null,h?(0,k.jsx)(`span`,{className:`absolute right-3 top-1/2 -translate-y-1/2 text-[10px] uppercase tracking-wider text-muted-foreground`,children:`…`}):null]})}function le({value:e=[],onChange:n,placeholder:r=`Add ticker`,min:i,max:a,ariaLabel:o=`Ticker symbols`}){let[s,l]=(0,D.useState)(``),u=a!=null&&e.length>=a,f=()=>{let t=s.trim().toUpperCase();if(t){if(e.includes(t)){l(``);return}u||(n([...e,t]),l(``))}},p=t=>n(e.filter(e=>e!==t));return(0,k.jsxs)(`div`,{children:[(0,k.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,k.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,k.jsx)(`button`,{type:`button`,"aria-label":`Remove ${e}`,onClick:()=>p(e),className:`text-muted-foreground hover:text-foreground`,children:(0,k.jsx)(d,{className:`h-3 w-3`})})]},e)),(0,k.jsx)(`input`,{"aria-label":o,value:s,onChange:e=>l(e.target.value.toUpperCase()),onKeyDown:t=>{t.key===`Enter`||t.key===`,`?(t.preventDefault(),f()):t.key===`Backspace`&&!s&&e.length>0&&(t.preventDefault(),n(e.slice(0,-1)))},placeholder:e.length===0?r:``,disabled:u,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,k.jsx)(t,{type:`button`,variant:`ghost`,size:`icon-xs`,"aria-label":`Add ticker`,onClick:f,children:(0,k.jsx)(c,{})}):null]}),i!=null&&e.length<i?(0,k.jsxs)(`p`,{className:`mt-1 text-[11px] text-muted-foreground`,children:[`Add at least `,i,` symbol`,i===1?``:`s`,`.`]}):null,a==null?null:(0,k.jsxs)(`p`,{className:`mt-1 text-[11px] text-muted-foreground tabular-nums`,children:[e.length,`/`,a]})]})}function ue({value:e=[],onChange:t,options:n}){let r=n=>{e.includes(n)?t(e.filter(e=>e!==n)):t([...e,n])};return(0,k.jsx)(`div`,{className:`flex flex-wrap gap-1.5`,children:n.map(t=>{let n=e.includes(t.value);return(0,k.jsxs)(`button`,{type:`button`,onClick:()=>r(t.value),className:o(`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,k.jsx)(f,{className:`h-3 w-3`,"aria-hidden":`true`}):null,t.label]},t.value)})})}function de({value:e,onChange:t,min:n,max:r,placeholder:i=`YYYY-MM-DD`}){return(0,k.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 fe({value:e,onChange:t,placeholder:n,rows:r=3,maxLength:i,ariaLabel:a=`Text input`}){return(0,k.jsxs)(`div`,{children:[(0,k.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,k.jsxs)(`div`,{className:`mt-1 text-right text-[11px] tabular-nums text-muted-foreground`,children:[(e||``).length,`/`,i]}):null]})}function pe({value:e,onChange:t,currency:n=`USD`,min:r=0,placeholder:i=`0`}){let[a,o]=(0,D.useState)(!1),[s,c]=(0,D.useState)(j(e,!1));(0,D.useEffect)(()=>{a||c(j(e,!1))},[e,a]);let l=me(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(j(n,!1)))};return(0,k.jsxs)(`div`,{className:`relative`,children:[(0,k.jsx)(`span`,{className:`pointer-events-none absolute left-3 top-1/2 -translate-y-1/2 text-sm text-muted-foreground`,children:l}),(0,k.jsx)(p,{value:a?s:j(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 j(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 me(e){return!e||e===`USD`||e===`CAD`||e===`AUD`?`$`:e===`EUR`?`€`:e===`GBP`?`£`:e===`JPY`?`¥`:e}function he({value:e,onChange:t,min:n,max:r,step:i=.5,placeholder:a}){return(0,k.jsxs)(`div`,{className:`relative`,children:[(0,k.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,k.jsx)(`span`,{className:`pointer-events-none absolute right-3 top-1/2 -translate-y-1/2 text-sm text-muted-foreground`,children:`%`})]})}function ge({suggestions:e,onPick:t,label:n=`Suggestions`}){return e?.length?(0,k.jsxs)(`div`,{className:`grid gap-1.5`,children:[(0,k.jsx)(`span`,{className:`text-[11px] font-medium uppercase tracking-wider text-muted-foreground`,children:n}),(0,k.jsx)(`div`,{className:`flex flex-wrap gap-1.5`,children:e.map(e=>(0,k.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 _e={DAYS_PRESETS:O,HOURS_PRESETS:ie,RANGE_OPTIONS:te,PERIOD_OPTIONS:ne,FRESHNESS_OPTIONS:re};function M(e){return typeof e==`string`?_e[e]??[]:e??[]}function N({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,k.jsx)(A,{label:e.label,hint:e.helper,required:e.required,children:(0,k.jsx)(ce,{value:t,onChange:i,lookup:r,placeholder:e.placeholder,ariaLabel:e.label})});case`symbols`:return(0,k.jsx)(A,{label:e.label,hint:e.helper,required:e.required,children:(0,k.jsx)(le,{value:t||[],onChange:i,min:e.min,max:e.max,placeholder:e.placeholder,ariaLabel:e.label})});case`segmented`:return(0,k.jsx)(A,{label:e.label,hint:e.helper,required:e.required,children:(0,k.jsx)(ae,{value:t,onChange:i,options:M(e.options),ariaLabel:e.label})});case`select`:return(0,k.jsx)(A,{label:e.label,hint:e.helper,required:e.required,children:(0,k.jsx)(oe,{value:t,onChange:i,options:M(e.options),placeholder:e.placeholder,ariaLabel:e.label})});case`number-chips`:return(0,k.jsx)(A,{label:e.label,hint:e.helper,required:e.required,children:(0,k.jsx)(se,{value:t,onChange:i,presets:M(e.presets),suffix:e.suffix,min:e.min,max:e.max,step:e.step,placeholder:e.placeholder})});case`multi-chips`:return(0,k.jsx)(A,{label:e.label,hint:e.helper,required:e.required,children:(0,k.jsx)(ue,{value:t||[],onChange:i,options:M(e.options)})});case`date`:return(0,k.jsx)(A,{label:e.label,hint:e.helper,required:e.required,children:(0,k.jsx)(de,{value:t,onChange:i,min:e.min,max:e.max})});case`freetext`:return(0,k.jsx)(A,{label:e.label,hint:e.helper,required:e.required,children:(0,k.jsx)(fe,{value:t,onChange:i,placeholder:e.placeholder,maxLength:e.maxLength,rows:e.rows,ariaLabel:e.label})});case`money`:return(0,k.jsx)(A,{label:e.label,hint:e.helper,required:e.required,children:(0,k.jsx)(pe,{value:t,onChange:i,currency:e.currency,placeholder:e.placeholder})});case`percent`:return(0,k.jsx)(A,{label:e.label,hint:e.helper,required:e.required,children:(0,k.jsx)(he,{value:t,onChange:i,min:e.min,max:e.max,step:e.step,placeholder:e.placeholder})});default:return(0,k.jsxs)(A,{label:e.label,hint:e.helper,required:e.required,children:[(0,k.jsx)(p,{value:t??``,placeholder:e.placeholder,onChange:e=>i(e.target.value),className:`h-9`}),e.suggestions?.length?(0,k.jsx)(`div`,{className:`mt-2`,children:(0,k.jsx)(ge,{suggestions:e.suggestions,onPick:i,label:`Try`})}):null]})}}function P(e){let t={};for(let n of e)n.default!==void 0&&(t[n.name]=n.default);return t}function F(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 I=(e={})=>({name:`symbol`,kind:`symbol`,label:`Symbol`,required:!0,default:`NVDA`,placeholder:`AAPL`,...e}),L=(e={})=>({name:`query`,kind:`text`,label:`Ticker or topic`,required:!0,placeholder:`AAPL or AI infrastructure`,...e}),ve={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:[I()],get_stock_history:[I(),{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:[I()],get_financials:[I(),{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:[I()],calculate_dcf:[I(),{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:[I(),{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:[I(),{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:[I(),{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`}]},I({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`}]},I({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:[I(),{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:[I(),{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:[L(),{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:[L({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:[L(),{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:[L(),{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:[L(),{name:`hours`,kind:`number-chips`,label:`Lookback`,default:24,presets:`HOURS_PRESETS`,suffix:`hr`}]},R={market:`Market`,fundamentals:`Fundamentals`,options:`Options`,portfolio:`Portfolio`,technical:`Technical`,sentiment:`Sentiment`,macro:`Macro`,interaction:`Interaction`};function ye(e){return ve[e]??null}var be={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=[`${z(e.budget)} budget`,e.riskProfile&&`${e.riskProfile} risk`,e.timeHorizon&&`${e.timeHorizon} horizon`,e.assetScope&&xe(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&&Se(e.liquidityMinimum),e.objective&&Ce(e.objective),e.maxPremium!=null&&`max premium ${z(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 xe(e){return e===`stocks_etfs`?`stocks and ETFs`:e===`stocks_crypto`?`stocks and crypto`:`stocks only`}function Se(e){return e===`tight_spreads`?`tight bid-ask spreads`:e===`high_oi`?`high open interest`:`any liquidity`}function Ce(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 z(e){if(e==null)return``;let t=Number(e);return Number.isFinite(t)?`$${t.toLocaleString(`en-US`)}`:String(e)}function we(e){return be[e]??null}var Te=[{id:`workflows`,label:`Workflows`,icon:T},{id:`tools`,label:`Tools`,icon:m},{id:`providers`,label:`Providers`,icon:g}],Ee=`workflows`;function De({open:e,initialTab:t,catalog:n,onClose:r,send:i,setToast:a,startChatRun:o,fillComposer:s}){let c=t??Ee,l=e?`open:${c}`:`closed`,[d,f]=(0,D.useState)(l),[p,m]=(0,D.useState)(c),[g,_]=(0,D.useState)(``),[v,y]=(0,D.useState)(null),b=(0,D.useRef)(null);d!==l&&(f(l),e&&(m(c),_(``),y(null))),(0,D.useEffect)(()=>{b.current&&(b.current.scrollTop=0)},[v,p]);let x=(0,D.useCallback)(()=>{y(null),_(``),r()},[r]);return(0,k.jsx)(h,{open:e,onOpenChange:e=>{e||x()},children:(0,k.jsx)(u,{width:`xl`,handleLabel:`Catalog`,className:`bg-card p-0`,children:(0,k.jsxs)(`div`,{className:`grid min-h-0 flex-1 grid-rows-[auto_minmax(0,1fr)]`,children:[v?(0,k.jsx)(Pe,{selection:v,catalog:n,onBack:()=>y(null)}):(0,k.jsx)(Oe,{tab:p,setTab:m,query:g,setQuery:_,counts:{workflows:n?.workflows?.length??0,tools:n?.tools?.length??0,providers:n?.providers?.length??0}}),(0,k.jsx)(`div`,{ref:b,className:`min-h-0 overflow-y-auto overscroll-contain`,children:v?(0,k.jsx)(Fe,{selection:v,catalog:n,send:i,setToast:a,startChatRun:o,fillComposer:s,onClose:x,lookupSymbol:void 0}):(0,k.jsx)(Ae,{tab:p,query:g,catalog:n,onSelect:e=>y(e)})})]})})})}function Oe({tab:e,setTab:r,query:i,setQuery:a,counts:s}){return(0,k.jsxs)(`div`,{className:`border-b border-border`,children:[(0,k.jsx)(`div`,{className:`px-3 pt-2 sm:px-4`,children:(0,k.jsx)(`div`,{className:`flex w-full items-center gap-0.5 rounded-md bg-secondary p-0.5`,children:Te.map(t=>{let n=t.icon,i=e===t.id;return(0,k.jsxs)(`button`,{type:`button`,onClick:()=>r(t.id),"aria-pressed":i,className:o(`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,k.jsx)(n,{className:`hidden h-3.5 w-3.5 sm:inline`,"aria-hidden":`true`}),(0,k.jsx)(`span`,{className:`truncate`,children:t.label}),(0,k.jsx)(`span`,{className:o(`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,k.jsxs)(`div`,{className:`flex items-center gap-2 px-3 py-2 sm:px-4`,children:[(0,k.jsx)(n,{"aria-hidden":`true`,className:`h-4 w-4 shrink-0 text-muted-foreground`}),(0,k.jsx)(p,{variant:`ghost`,value:i,onChange:e=>a(e.target.value),placeholder:ke(e),autoFocus:!0,className:`h-8 px-0 text-sm shadow-none`}),i?(0,k.jsx)(t,{variant:`ghost`,size:`icon-xs`,"aria-label":`Clear search`,onClick:()=>a(``),children:(0,k.jsx)(d,{})}):null]})]})}function ke(e){return e===`workflows`?`Search workflows`:e===`providers`?`Search providers`:`Search tools by name, label, or domain`}function Ae({tab:e,query:t,catalog:n,onSelect:r}){if(e===`workflows`){let e=Xe(n?.workflows??[],t);return e.length===0?(0,k.jsx)(B,{query:t,kind:`workflows`}):(0,k.jsx)(`ul`,{className:`grid divide-y divide-border`,children:e.map(e=>(0,k.jsx)(je,{workflow:e,onSelect:r},e.id))})}if(e===`providers`){let e=W(n?.providers??[],t);return e.length===0?(0,k.jsx)(B,{query:t,kind:`providers`}):(0,k.jsx)(`ul`,{className:`grid divide-y divide-border`,children:e.map(e=>(0,k.jsx)(Ne,{provider:e,onSelect:r},e.id))})}let i=Ye(n?.tools??[],t);if(i.length===0)return(0,k.jsx)(B,{query:t,kind:`tools`});let a=Ze(i,e=>e.domain??`tool`),s=[`market`,`fundamentals`,`options`,`portfolio`,`technical`,`sentiment`,`macro`,`interaction`];return(0,k.jsx)(`div`,{className:`grid`,children:[...a.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,k.jsxs)(`section`,{className:o(t===0?``:`mt-2`),children:[(0,k.jsx)(`h4`,{className:`px-4 pb-1 pt-3 text-[11px] font-medium uppercase tracking-[0.08em] text-muted-foreground`,children:R[e]??e}),(0,k.jsx)(`ul`,{className:`grid divide-y divide-border border-y border-border`,children:a.get(e).map(e=>(0,k.jsx)(Me,{tool:e,onSelect:r},e.name))})]},e))})}function je({workflow:e,onSelect:t}){return(0,k.jsx)(`li`,{children:(0,k.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,k.jsx)(T,{"aria-hidden":`true`,className:`mt-0.5 h-4 w-4 shrink-0 text-foreground`}),(0,k.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,k.jsx)(`div`,{className:`flex items-center gap-2`,children:(0,k.jsx)(`span`,{className:`text-sm font-semibold text-foreground`,children:e.name})}),(0,k.jsx)(`p`,{className:`mt-0.5 line-clamp-2 text-xs text-muted-foreground`,children:e.description})]}),(0,k.jsx)(v,{"aria-hidden":`true`,className:`mt-1 h-4 w-4 shrink-0 text-muted-foreground opacity-0 transition-opacity group-hover:opacity-100`})]})})}function Me({tool:e,onSelect:t}){let n=e.enabled===!1;return(0,k.jsx)(`li`,{children:(0,k.jsxs)(`button`,{type:`button`,onClick:()=>t({kind:`tool`,id:e.name}),className:o(`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,k.jsx)(m,{"aria-hidden":`true`,className:`mt-0.5 h-3.5 w-3.5 shrink-0 text-muted-foreground`}),(0,k.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,k.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,k.jsx)(`span`,{className:`text-sm font-medium text-foreground`,children:e.label||U(e.name)}),(0,k.jsx)(`code`,{className:`hidden truncate text-[11px] tabular-nums text-muted-foreground/70 sm:inline`,children:e.name}),n?(0,k.jsx)(s,{variant:`outline`,className:`h-5 px-1.5 text-[10px]`,children:`disabled`}):null]}),(0,k.jsx)(`p`,{className:`mt-0.5 line-clamp-1 text-xs text-muted-foreground`,children:e.description})]}),(0,k.jsx)(v,{"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({provider:e,onSelect:t}){let n=G(e);return(0,k.jsx)(`li`,{children:(0,k.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,k.jsx)(K(e),{"aria-hidden":`true`,className:`mt-0.5 h-4 w-4 shrink-0 text-muted-foreground`}),(0,k.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,k.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,k.jsx)(`span`,{className:`text-sm font-medium text-foreground`,children:e.displayName}),(0,k.jsx)(q,{status:n}),(0,k.jsx)(`span`,{className:o(`text-[11px]`,Y(n)),children:J(n)})]}),(0,k.jsx)(`p`,{className:`mt-0.5 line-clamp-2 text-xs text-muted-foreground`,children:(e.unlocks||[]).join(` · `)})]}),(0,k.jsx)(v,{"aria-hidden":`true`,className:`mt-1 h-4 w-4 shrink-0 text-muted-foreground opacity-0 transition-opacity group-hover:opacity-100`})]})})}function B({query:e,kind:t}){return(0,k.jsxs)(`div`,{className:`grid gap-2 p-12 text-center`,children:[(0,k.jsx)(n,{className:`mx-auto h-5 w-5 text-muted-foreground`,"aria-hidden":`true`}),(0,k.jsx)(`p`,{className:`text-sm font-medium text-foreground`,children:e?`No ${t} match "${e}"`:`No ${t} available`}),(0,k.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 Pe({selection:e,catalog:n,onBack:r}){let i=H(e,n),a=e.kind===`provider`&&i?K(i):g;return(0,k.jsxs)(`div`,{className:`flex items-center gap-2 border-b border-border px-3 py-2 sm:px-4`,children:[(0,k.jsx)(t,{variant:`ghost`,size:`icon-sm`,"aria-label":`Back to catalog`,onClick:r,children:(0,k.jsx)(y,{})}),(0,k.jsxs)(`div`,{className:`flex min-w-0 flex-1 items-center gap-2`,children:[e.kind===`workflow`?(0,k.jsx)(T,{className:`h-4 w-4 text-foreground`,"aria-hidden":`true`}):null,e.kind===`tool`?(0,k.jsx)(m,{className:`h-4 w-4 text-muted-foreground`,"aria-hidden":`true`}):null,e.kind===`provider`?(0,k.jsx)(a,{className:`h-4 w-4 text-muted-foreground`,"aria-hidden":`true`}):null,(0,k.jsx)(`h2`,{className:`truncate text-sm font-semibold text-foreground`,children:He(e,i)}),e.kind===`tool`&&i?.domain?(0,k.jsx)(s,{variant:`outline`,className:`hidden h-5 px-1.5 text-[10px] sm:inline-flex`,children:R[i.domain]??i.domain}):null]})]})}function Fe({selection:e,catalog:t,send:n,setToast:r,startChatRun:i,fillComposer:a,onClose:o,lookupSymbol:s}){let c=H(e,t);return c?e.kind===`workflow`?(0,k.jsx)(Ie,{workflow:c,startChatRun:i,fillComposer:a,onClose:o,setToast:r,lookupSymbol:s}):e.kind===`tool`?(0,k.jsx)(Le,{tool:c,send:n,startChatRun:i,fillComposer:a,onClose:o,setToast:r,lookupSymbol:s}):(0,k.jsx)(Re,{provider:c,send:n,setToast:r}):(0,k.jsxs)(`div`,{className:`grid gap-2 p-12 text-center`,children:[(0,k.jsx)(`p`,{className:`text-sm font-medium text-foreground`,children:`Selection no longer available`}),(0,k.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`The catalog refreshed while you were viewing this entry.`})]})}function Ie({workflow:e,startChatRun:n,fillComposer:r,onClose:i,setToast:a,lookupSymbol:s}){let c=we(e.id),l=c?.fields??[],[u,d]=(0,D.useState)(()=>P(l)),[f,p]=(0,D.useState)(!1),m=(0,D.useCallback)((e,t)=>d(n=>({...n,[e]:t})),[]),h=F(l,u),g=(0,D.useMemo)(()=>c?Je(c,u):e.prompt||e.name,[c,u,e]),_=l.filter(e=>!e.advanced),y=l.filter(e=>e.advanced);if(!c)return(0,k.jsxs)(`div`,{className:`p-6`,children:[(0,k.jsxs)(`p`,{className:`text-sm text-muted-foreground`,children:[`No builder defined for "`,e.name,`". The agent will use its default planner.`]}),(0,k.jsx)(`div`,{className:`mt-4 flex gap-2`,children:(0,k.jsx)(t,{variant:`brand`,onClick:()=>{n(e.prompt||e.name),i()},children:`Run with defaults`})})]});let b=e=>{if(h.length>0){a?.(h[0]);return}if(e===`send`){n(g),i();return}r?.(g),a?.(`Draft loaded — edit and send when ready.`),i()};return(0,k.jsxs)(`div`,{className:`grid animate-fade-in-once gap-5 px-4 py-4 sm:px-5`,children:[(0,k.jsx)(`p`,{className:`text-sm leading-5 text-muted-foreground`,children:c.description}),(0,k.jsx)(`div`,{className:`grid gap-3.5`,children:_.map(e=>(0,k.jsx)(N,{field:e,value:u[e.name],onChange:m,lookupSymbol:s},e.name))}),y.length>0?(0,k.jsxs)(`div`,{className:`grid gap-3.5 border-t border-border pt-4`,children:[(0,k.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,k.jsxs)(`span`,{children:[f?`Hide`:`Show`,` advanced`]}),(0,k.jsx)(v,{"aria-hidden":`true`,className:o(`h-3 w-3 transition-transform`,f&&`rotate-90`)})]}),f?y.map(e=>(0,k.jsx)(N,{field:e,value:u[e.name],onChange:m,lookupSymbol:s},e.name)):null]}):null,(0,k.jsx)(V,{prompt:g}),(0,k.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,k.jsx)(t,{variant:`bordered`,onClick:()=>b(`draft`),disabled:!g,children:`Edit in chat`}),(0,k.jsx)(t,{variant:`brand`,onClick:()=>b(`send`),disabled:!g,prefixIcon:C,children:`Run workflow`})]})]})}function Le({tool:e,send:n,startChatRun:r,fillComposer:i,onClose:a,setToast:o,lookupSymbol:s}){let c=(0,D.useMemo)(()=>ye(e.name)??Ue(e),[e]),[l,u]=(0,D.useState)(()=>P(c)),d=(0,D.useCallback)((e,t)=>u(n=>({...n,[e]:t})),[]),f=F(c,l),p=(0,D.useMemo)(()=>Ge(l),[l]),m=(0,D.useMemo)(()=>`Use ${e.name}${Ke(p)}`,[e,p]),h=t=>{if(f.length>0){o?.(f[0]);return}if(t===`send`){r(m),a();return}if(t===`draft`){i?.(m),o?.(`Draft loaded — edit and send when ready.`),a();return}t===`run`&&n?.(`tool.invoke`,{toolName:e.name,args:p})&&(o?.(`Running ${e.label||e.name}…`),a())};return(0,k.jsxs)(`div`,{className:`grid animate-fade-in-once gap-5 px-4 py-4 sm:px-5`,children:[(0,k.jsx)(`p`,{className:`text-sm leading-5 text-muted-foreground`,children:e.description}),c.length===0?(0,k.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,k.jsx)(`div`,{className:`grid gap-3.5`,children:c.map(e=>(0,k.jsx)(N,{field:e,value:l[e.name],onChange:d,lookupSymbol:s},e.name))}),(0,k.jsx)(V,{prompt:m,title:`Chat preview`}),(0,k.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,k.jsx)(t,{variant:`bordered`,size:`sm`,onClick:()=>h(`draft`),children:`Edit in chat`}),(0,k.jsx)(t,{variant:`brand`,size:`sm`,prefixIcon:C,onClick:()=>h(`run`),children:`Run now`})]})]})}function Re({provider:e,send:t,setToast:n}){return e.kind===`external-tool`?(0,k.jsx)(Be,{provider:e,send:t,setToast:n}):e.kind===`public-http`?(0,k.jsx)(Ve,{provider:e,send:t,setToast:n}):(0,k.jsx)(ze,{provider:e,send:t,setToast:n})}function ze({provider:e,send:n,setToast:i}){let a=`${e.id}:${e.apiKey||``}`,[s,c]=(0,D.useState)(a),[l,u]=(0,D.useState)(e.apiKey||``),[d,f]=(0,D.useState)(!1),m=G(e),h=m===`env`,g=l.trim(),_=!h&&g.length>0;s!==a&&(c(a),u(e.apiKey||``),f(!1));let v=()=>{if(h){i?.(`${e.displayName} is set via ${e.envVar}. Unset it to override here.`);return}g&&(i?.(`Verifying ${e.displayName} key…`),n?.(`provider.save_api_key`,{providerId:e.id,apiKey:g})&&u(``))};return(0,k.jsxs)(`div`,{className:`grid animate-fade-in-once gap-5 px-4 py-4 sm:px-5`,children:[(0,k.jsxs)(`div`,{className:`grid gap-1.5`,children:[(0,k.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,k.jsx)(q,{status:m}),(0,k.jsx)(`span`,{className:o(`text-xs font-medium`,Y(m)),children:J(m)}),h?(0,k.jsxs)(`code`,{className:`text-[11px] text-muted-foreground`,children:[`env: `,e.envVar]}):null]}),(0,k.jsx)(`p`,{className:`text-sm leading-5 text-muted-foreground`,children:e.fallbackDescription?(0,k.jsxs)(k.Fragment,{children:[`If absent: `,e.fallbackDescription,`.`]}):(0,k.jsxs)(k.Fragment,{children:[`Required for: `,(e.unlocks||[]).join(`, `)||`this provider's tools`,`.`]})})]}),(0,k.jsxs)(`div`,{className:`grid gap-2`,children:[(0,k.jsx)(`span`,{className:`text-[11px] font-medium uppercase tracking-wider text-muted-foreground`,children:`Unlocks`}),(0,k.jsx)(`ul`,{className:`grid gap-1`,children:(e.unlocks||[]).map(e=>(0,k.jsxs)(`li`,{className:`flex items-baseline gap-2 text-sm text-foreground`,children:[(0,k.jsx)(`span`,{"aria-hidden":`true`,className:`mt-1 h-1 w-1 rounded-full bg-foreground/40`}),(0,k.jsx)(`span`,{children:e})]},e))})]}),(0,k.jsxs)(`div`,{className:`grid gap-2`,children:[(0,k.jsx)(`label`,{htmlFor:`provider-api-key-${e.id}`,className:`text-xs font-medium text-foreground`,children:`API key`}),(0,k.jsxs)(`div`,{className:`relative`,children:[(0,k.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,k.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,k.jsx)(ee,{}):(0,k.jsx)(S,{})})]}),(0,k.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,k.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,k.jsx)(t,{variant:`ghost`,size:`sm`,suffixIcon:r,onClick:()=>window.open(e.signupUrl,`_blank`,`noreferrer`),children:`Get a key`}):null,(0,k.jsx)(t,{variant:`brand`,size:`sm`,onClick:v,disabled:!_,children:m===`file`?`Replace key`:`Save key`})]})]})}function Be({provider:e,send:n,setToast:r}){let i=G(e),a=e.statusDetail,s=i===`skipped`;return(0,k.jsxs)(`div`,{className:`grid animate-fade-in-once gap-5 px-4 py-4 sm:px-5`,children:[(0,k.jsxs)(`div`,{className:`grid gap-1.5`,children:[(0,k.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[(0,k.jsx)(q,{status:i}),(0,k.jsx)(`span`,{className:o(`text-xs font-medium`,Y(i)),children:J(i)}),a?.checkedAt?(0,k.jsxs)(`span`,{className:`text-[11px] text-muted-foreground`,children:[`Checked `,$(a.checkedAt)]}):null]}),(0,k.jsx)(`p`,{className:`text-sm leading-5 text-muted-foreground`,children:e.fallbackDescription})]}),(0,k.jsxs)(`div`,{className:`grid gap-2`,children:[(0,k.jsx)(`span`,{className:`text-[11px] font-medium uppercase tracking-wider text-muted-foreground`,children:`Install`}),(0,k.jsxs)(`div`,{className:`flex min-w-0 items-center gap-2 rounded-md border border-border bg-secondary px-3 py-2`,children:[(0,k.jsx)(E,{className:`h-3.5 w-3.5 shrink-0 text-muted-foreground`,"aria-hidden":`true`}),(0,k.jsx)(`code`,{className:`min-w-0 flex-1 overflow-x-auto whitespace-nowrap text-[11px] text-foreground`,children:e.installCmd}),(0,k.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,k.jsx)(b,{})})]})]}),(0,k.jsxs)(`div`,{className:`grid gap-2`,children:[(0,k.jsx)(`span`,{className:`text-[11px] font-medium uppercase tracking-wider text-muted-foreground`,children:`Session source`}),(0,k.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`,`.`]}),a?.message?(0,k.jsx)(`p`,{className:`rounded-md border border-border bg-secondary px-3 py-2 text-xs leading-5 text-muted-foreground`,children:a.message}):null]}),(0,k.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,k.jsx)(t,{variant:`bordered`,size:`sm`,prefixIcon:w,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,k.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 Ve({provider:e,send:n,setToast:r}){let i=G(e),a=e.statusDetail;return(0,k.jsxs)(`div`,{className:`grid animate-fade-in-once gap-5 px-4 py-4 sm:px-5`,children:[(0,k.jsxs)(`div`,{className:`grid gap-1.5`,children:[(0,k.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[(0,k.jsx)(q,{status:i}),(0,k.jsx)(`span`,{className:o(`text-xs font-medium`,Y(i)),children:J(i)}),a?.checkedAt?(0,k.jsxs)(`span`,{className:`text-[11px] text-muted-foreground`,children:[`Checked `,$(a.checkedAt)]}):null]}),(0,k.jsx)(`p`,{className:`text-sm leading-5 text-muted-foreground`,children:e.fallbackDescription||`No account or API key is required.`})]}),(0,k.jsxs)(`div`,{className:`grid gap-2`,children:[(0,k.jsx)(`span`,{className:`text-[11px] font-medium uppercase tracking-wider text-muted-foreground`,children:`Probe`}),(0,k.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}),a?.message?(0,k.jsx)(`p`,{className:`text-xs leading-5 text-muted-foreground`,children:a.message}):null]}),(0,k.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,k.jsx)(t,{variant:`brand`,size:`sm`,prefixIcon:w,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,k.jsxs)(`div`,{className:`grid gap-1.5`,children:[(0,k.jsx)(`span`,{className:`text-[11px] font-medium uppercase tracking-wider text-muted-foreground`,children:t}),(0,k.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 He(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 Ue(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:We(t),placeholder:n.examples?.[0],helper:r.length>80?`${r.slice(0,80)}…`:r,required:e.parameters?.required?.includes?.(t)??!1}})}function We(e){return e.replace(/_/g,` `).replace(/\b\w/g,e=>e.toUpperCase())}function Ge(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 Ke(e){let t=Object.entries(e);return t.length===0?``:` with ${t.map(([e,t])=>`${e}=${qe(t)}`).join(`, `)}`}function qe(e){return Array.isArray(e)?e.join(`,`):typeof e==`string`&&e.includes(` `)?JSON.stringify(e):String(e)}function Je(e,t){try{return e.buildPrompt(t)||``}catch{return``}}function Ye(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 Xe(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 W(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 Ze(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`?E:e.kind===`public-http`?x:g}function q({status:e}){return(0,k.jsx)(`span`,{"aria-hidden":`true`,className:o(`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{De as CatalogOverlay};