opencandle 0.11.1 → 0.12.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 (653) hide show
  1. package/README.md +20 -24
  2. package/dist/analysts/contracts.js +0 -1
  3. package/dist/analysts/orchestrator.js +0 -1
  4. package/dist/cli-main.js +13 -7
  5. package/dist/cli-options.d.ts +4 -0
  6. package/dist/cli-options.js +33 -0
  7. package/dist/cli.js +8 -3
  8. package/dist/config.js +0 -1
  9. package/dist/doctor/cli-command.js +2 -1
  10. package/dist/doctor/render.js +0 -1
  11. package/dist/doctor/report.js +40 -11
  12. package/dist/gui/server/ask-user-bridge.d.ts +19 -0
  13. package/dist/gui/server/ask-user-bridge.js +55 -0
  14. package/dist/gui/server/automation-heartbeat.d.ts +25 -0
  15. package/dist/gui/server/automation-heartbeat.js +61 -0
  16. package/dist/gui/server/background-quotes.d.ts +39 -0
  17. package/dist/gui/server/background-quotes.js +71 -0
  18. package/dist/gui/server/chat-event-adapter.d.ts +16 -0
  19. package/dist/gui/server/chat-event-adapter.js +263 -0
  20. package/dist/gui/server/gui-session-manager.d.ts +2 -0
  21. package/dist/gui/server/gui-session-manager.js +4 -0
  22. package/dist/gui/server/http-routes.d.ts +69 -0
  23. package/dist/gui/server/http-routes.js +1008 -0
  24. package/dist/gui/server/invoke-tool.d.ts +47 -0
  25. package/dist/gui/server/invoke-tool.js +373 -0
  26. package/dist/gui/server/live-chat-event-adapter.d.ts +19 -0
  27. package/dist/gui/server/live-chat-event-adapter.js +206 -0
  28. package/dist/gui/server/local-session-coordinator.d.ts +26 -0
  29. package/dist/gui/server/local-session-coordinator.js +53 -0
  30. package/dist/gui/server/market-state-api.d.ts +138 -0
  31. package/dist/gui/server/market-state-api.js +355 -0
  32. package/dist/gui/server/model-setup.d.ts +64 -0
  33. package/dist/gui/server/model-setup.js +150 -0
  34. package/dist/gui/server/private-api-access.d.ts +6 -0
  35. package/dist/gui/server/private-api-access.js +53 -0
  36. package/dist/gui/server/projector.d.ts +49 -0
  37. package/dist/gui/server/projector.js +296 -0
  38. package/dist/gui/server/prompt-observation.d.ts +8 -0
  39. package/dist/gui/server/prompt-observation.js +43 -0
  40. package/dist/gui/server/quote-snapshot-store.d.ts +14 -0
  41. package/dist/gui/server/quote-snapshot-store.js +49 -0
  42. package/dist/gui/server/server.d.ts +1 -0
  43. package/dist/gui/server/server.js +259 -0
  44. package/dist/gui/server/session-actions.d.ts +60 -0
  45. package/dist/gui/server/session-actions.js +218 -0
  46. package/dist/gui/server/session-entry-wait.d.ts +27 -0
  47. package/dist/gui/server/session-entry-wait.js +129 -0
  48. package/dist/gui/server/session-list.d.ts +2 -0
  49. package/dist/gui/server/session-list.js +11 -0
  50. package/dist/gui/server/shutdown.d.ts +10 -0
  51. package/dist/gui/server/shutdown.js +29 -0
  52. package/dist/gui/server/tool-invoke-ack.d.ts +17 -0
  53. package/dist/gui/server/tool-invoke-ack.js +26 -0
  54. package/dist/gui/server/tool-metadata.d.ts +93 -0
  55. package/dist/gui/server/tool-metadata.js +148 -0
  56. package/dist/gui/server/websocket.d.ts +9 -0
  57. package/dist/gui/server/websocket.js +124 -0
  58. package/dist/gui/server/writer-lock.d.ts +1 -0
  59. package/dist/gui/server/writer-lock.js +1 -0
  60. package/dist/gui/server/ws-hub.d.ts +50 -0
  61. package/dist/gui/server/ws-hub.js +284 -0
  62. package/dist/gui/shared/chat-events.d.ts +174 -0
  63. package/dist/gui/shared/chat-events.js +13 -0
  64. package/dist/gui/shared/event-reducer.d.ts +3 -0
  65. package/dist/gui/shared/event-reducer.js +187 -0
  66. package/dist/index.js +0 -1
  67. package/dist/infra/cache.js +0 -1
  68. package/dist/infra/freshness.js +0 -1
  69. package/dist/infra/http-client.js +1 -2
  70. package/dist/infra/index.js +0 -1
  71. package/dist/infra/market-calendar.js +0 -1
  72. package/dist/infra/native-dependencies.js +0 -1
  73. package/dist/infra/node-version.js +0 -1
  74. package/dist/infra/open-url.js +0 -1
  75. package/dist/infra/opencandle-paths.js +0 -1
  76. package/dist/infra/rate-limiter.js +0 -1
  77. package/dist/market-state/alert-conditions.js +0 -1
  78. package/dist/market-state/alert-runner.d.ts +1 -0
  79. package/dist/market-state/alert-runner.js +5 -4
  80. package/dist/market-state/daily-report.js +0 -1
  81. package/dist/market-state/local-automation-service.js +0 -1
  82. package/dist/market-state/notification-delivery.js +0 -1
  83. package/dist/market-state/resolve-for-mutation.js +0 -1
  84. package/dist/market-state/resolve.js +0 -1
  85. package/dist/market-state/service.d.ts +26 -21
  86. package/dist/market-state/service.js +175 -36
  87. package/dist/market-state/summaries.js +1 -13
  88. package/dist/memory/index.js +0 -1
  89. package/dist/memory/manager.js +0 -1
  90. package/dist/memory/preference-extractor.js +0 -1
  91. package/dist/memory/retrieval.js +0 -1
  92. package/dist/memory/sqlite.js +60 -11
  93. package/dist/memory/storage.js +0 -1
  94. package/dist/memory/tool-defaults.js +0 -1
  95. package/dist/memory/types.js +0 -1
  96. package/dist/monitor.js +0 -1
  97. package/dist/onboarding/connect.js +0 -1
  98. package/dist/onboarding/credential-interceptor.js +0 -1
  99. package/dist/onboarding/degradation-accumulator.js +0 -1
  100. package/dist/onboarding/prompt-user.d.ts +1 -1
  101. package/dist/onboarding/prompt-user.js +0 -1
  102. package/dist/onboarding/provider-status.js +0 -1
  103. package/dist/onboarding/providers.js +0 -1
  104. package/dist/onboarding/state.js +0 -1
  105. package/dist/onboarding/tool-helpers.js +0 -1
  106. package/dist/onboarding/tool-tags.js +0 -1
  107. package/dist/onboarding/validate-model-key.d.ts +17 -0
  108. package/dist/onboarding/validate-model-key.js +54 -0
  109. package/dist/onboarding/validation.js +0 -1
  110. package/dist/pi/opencandle-extension.js +2 -2
  111. package/dist/pi/session-action-dedupe.js +0 -1
  112. package/dist/pi/session-storage.js +0 -1
  113. package/dist/pi/session-writer-lock.js +0 -1
  114. package/dist/pi/session.js +0 -1
  115. package/dist/pi/setup.d.ts +2 -0
  116. package/dist/pi/setup.js +10 -3
  117. package/dist/pi/tool-adapter.js +0 -1
  118. package/dist/pi/tui-session-coordinator.js +0 -1
  119. package/dist/prompts/context-builder.js +1 -2
  120. package/dist/prompts/disclaimer.js +0 -1
  121. package/dist/prompts/policy-cards.js +0 -1
  122. package/dist/prompts/sections.js +0 -1
  123. package/dist/prompts/symbol-preflight.js +0 -1
  124. package/dist/prompts/workflow-prompts.js +0 -1
  125. package/dist/providers/alpha-vantage.js +2 -3
  126. package/dist/providers/coingecko.js +0 -1
  127. package/dist/providers/errors.js +0 -1
  128. package/dist/providers/exa-search.js +11 -10
  129. package/dist/providers/external-tool-command.js +0 -1
  130. package/dist/providers/external-tool-error.js +0 -1
  131. package/dist/providers/fear-greed.js +0 -1
  132. package/dist/providers/finnhub.js +0 -1
  133. package/dist/providers/fred.js +0 -1
  134. package/dist/providers/index.js +0 -1
  135. package/dist/providers/polymarket.js +0 -1
  136. package/dist/providers/provider-credential-error.js +0 -1
  137. package/dist/providers/reddit-cli.js +0 -1
  138. package/dist/providers/reddit.js +0 -1
  139. package/dist/providers/sec-edgar.js +0 -1
  140. package/dist/providers/tradingview.js +1 -2
  141. package/dist/providers/twitter-cli.js +0 -1
  142. package/dist/providers/twitter.js +0 -1
  143. package/dist/providers/web-search.js +15 -12
  144. package/dist/providers/with-fallback.js +0 -1
  145. package/dist/providers/wrap-provider.js +0 -1
  146. package/dist/providers/yahoo-finance.js +67 -4
  147. package/dist/routing/classify-intent.js +0 -1
  148. package/dist/routing/defaults.js +0 -1
  149. package/dist/routing/entity-extractor.js +2 -3
  150. package/dist/routing/fund-symbols.js +0 -1
  151. package/dist/routing/horizon.js +0 -1
  152. package/dist/routing/index.js +0 -1
  153. package/dist/routing/legacy-rule-router.js +0 -1
  154. package/dist/routing/planning.js +0 -1
  155. package/dist/routing/route-manifest.js +0 -1
  156. package/dist/routing/router-llm-client.d.ts +2 -2
  157. package/dist/routing/router-llm-client.js +0 -1
  158. package/dist/routing/router-prompt.js +0 -1
  159. package/dist/routing/router-types.js +0 -1
  160. package/dist/routing/router.js +1 -2
  161. package/dist/routing/slot-resolver.js +0 -1
  162. package/dist/routing/symbol-disambiguator.js +0 -1
  163. package/dist/routing/turn-context.js +0 -1
  164. package/dist/routing/types.js +0 -1
  165. package/dist/runtime/answer-contracts.js +0 -1
  166. package/dist/runtime/artifact-contracts.js +0 -1
  167. package/dist/runtime/evidence.js +0 -1
  168. package/dist/runtime/numeric-claims.js +0 -1
  169. package/dist/runtime/planning-evidence.js +0 -1
  170. package/dist/runtime/prompt-step.js +0 -1
  171. package/dist/runtime/provider-tracker.js +0 -1
  172. package/dist/runtime/run-context.js +0 -1
  173. package/dist/runtime/session-coordinator.js +0 -1
  174. package/dist/runtime/session-title.js +0 -1
  175. package/dist/runtime/tool-defaults-wrapper.js +0 -1
  176. package/dist/runtime/validation.js +0 -1
  177. package/dist/runtime/workflow-events.js +0 -1
  178. package/dist/runtime/workflow-runner.d.ts +1 -0
  179. package/dist/runtime/workflow-runner.js +8 -3
  180. package/dist/runtime/workflow-types.js +0 -1
  181. package/dist/sentiment/adapters/finnhub.js +0 -1
  182. package/dist/sentiment/adapters/reddit.js +0 -1
  183. package/dist/sentiment/adapters/twitter.js +0 -1
  184. package/dist/sentiment/adapters/web.js +0 -1
  185. package/dist/sentiment/index.js +4 -2
  186. package/dist/sentiment/insights.js +0 -1
  187. package/dist/sentiment/keywords.js +0 -1
  188. package/dist/sentiment/pipeline.js +0 -1
  189. package/dist/sentiment/scorer.js +0 -1
  190. package/dist/sentiment/store.js +0 -1
  191. package/dist/sentiment/trends.js +0 -1
  192. package/dist/sentiment/types.js +0 -1
  193. package/dist/system-prompt.js +0 -1
  194. package/dist/tool-kit.js +0 -1
  195. package/dist/tools/fundamentals/company-overview.d.ts +1 -1
  196. package/dist/tools/fundamentals/company-overview.js +2 -1
  197. package/dist/tools/fundamentals/comps.js +6 -4
  198. package/dist/tools/fundamentals/dcf.js +0 -1
  199. package/dist/tools/fundamentals/earnings.d.ts +1 -1
  200. package/dist/tools/fundamentals/earnings.js +2 -1
  201. package/dist/tools/fundamentals/financials.js +2 -1
  202. package/dist/tools/fundamentals/sec-filings.js +0 -1
  203. package/dist/tools/index.d.ts +116 -2
  204. package/dist/tools/index.js +0 -1
  205. package/dist/tools/interaction/ask-user.js +11 -1
  206. package/dist/tools/macro/event-probabilities.js +0 -1
  207. package/dist/tools/macro/fear-greed.d.ts +1 -1
  208. package/dist/tools/macro/fear-greed.js +0 -1
  209. package/dist/tools/macro/fred-data.d.ts +1 -1
  210. package/dist/tools/macro/fred-data.js +2 -1
  211. package/dist/tools/market/crypto-history.js +0 -1
  212. package/dist/tools/market/crypto-price.d.ts +2 -2
  213. package/dist/tools/market/crypto-price.js +0 -1
  214. package/dist/tools/market/screen-stocks.js +0 -1
  215. package/dist/tools/market/search-ticker.js +1 -2
  216. package/dist/tools/market/stock-history.js +0 -1
  217. package/dist/tools/market/stock-quote.d.ts +2 -2
  218. package/dist/tools/market/stock-quote.js +0 -1
  219. package/dist/tools/options/greeks.js +0 -1
  220. package/dist/tools/options/option-chain.d.ts +2 -2
  221. package/dist/tools/options/option-chain.js +0 -1
  222. package/dist/tools/portfolio/alerts.d.ts +2 -1
  223. package/dist/tools/portfolio/alerts.js +228 -2
  224. package/dist/tools/portfolio/correlation.js +23 -5
  225. package/dist/tools/portfolio/daily-report.js +0 -1
  226. package/dist/tools/portfolio/holdings-overlap.js +0 -1
  227. package/dist/tools/portfolio/notifications.js +0 -1
  228. package/dist/tools/portfolio/risk-analysis.d.ts +1 -1
  229. package/dist/tools/portfolio/risk-analysis.js +0 -1
  230. package/dist/tools/portfolio/tracker.d.ts +3 -1
  231. package/dist/tools/portfolio/tracker.js +57 -10
  232. package/dist/tools/portfolio/watchlist.d.ts +3 -6
  233. package/dist/tools/portfolio/watchlist.js +101 -110
  234. package/dist/tools/sentiment/insight-format.js +0 -1
  235. package/dist/tools/sentiment/query-match.js +0 -1
  236. package/dist/tools/sentiment/reddit-sentiment.js +0 -1
  237. package/dist/tools/sentiment/sentiment-summary.js +8 -4
  238. package/dist/tools/sentiment/sentiment-trend.d.ts +5 -1
  239. package/dist/tools/sentiment/sentiment-trend.js +6 -2
  240. package/dist/tools/sentiment/twitter-sentiment.js +0 -1
  241. package/dist/tools/sentiment/untrusted-text.js +0 -1
  242. package/dist/tools/sentiment/web-search.d.ts +1 -1
  243. package/dist/tools/sentiment/web-search.js +0 -1
  244. package/dist/tools/sentiment/web-sentiment.js +0 -1
  245. package/dist/tools/technical/backtest.js +0 -1
  246. package/dist/tools/technical/indicators.js +0 -1
  247. package/dist/types/fundamentals.js +0 -1
  248. package/dist/types/index.js +0 -1
  249. package/dist/types/macro.js +0 -1
  250. package/dist/types/market.d.ts +6 -0
  251. package/dist/types/market.js +0 -1
  252. package/dist/types/options.js +0 -1
  253. package/dist/types/portfolio.js +0 -1
  254. package/dist/types/prediction-markets.js +0 -1
  255. package/dist/types/sentiment.js +0 -1
  256. package/dist/workflows/compare-assets.js +0 -1
  257. package/dist/workflows/index.js +0 -1
  258. package/dist/workflows/options-screener.js +0 -1
  259. package/dist/workflows/portfolio-builder.js +0 -1
  260. package/gui/web/dist/assets/CatalogOverlay-CAc7e3Pf.js +1 -0
  261. package/gui/web/dist/assets/index-BOEKd9wT.css +2 -0
  262. package/gui/web/dist/assets/index-C-H05cQ2.js +65 -0
  263. package/gui/web/dist/index.html +2 -2
  264. package/package.json +11 -12
  265. package/dist/analysts/contracts.js.map +0 -1
  266. package/dist/analysts/orchestrator.js.map +0 -1
  267. package/dist/cli-main.js.map +0 -1
  268. package/dist/cli.js.map +0 -1
  269. package/dist/config.js.map +0 -1
  270. package/dist/doctor/cli-command.js.map +0 -1
  271. package/dist/doctor/render.js.map +0 -1
  272. package/dist/doctor/report.js.map +0 -1
  273. package/dist/index.js.map +0 -1
  274. package/dist/infra/cache.js.map +0 -1
  275. package/dist/infra/freshness.js.map +0 -1
  276. package/dist/infra/http-client.js.map +0 -1
  277. package/dist/infra/index.js.map +0 -1
  278. package/dist/infra/market-calendar.js.map +0 -1
  279. package/dist/infra/native-dependencies.js.map +0 -1
  280. package/dist/infra/node-version.js.map +0 -1
  281. package/dist/infra/open-url.js.map +0 -1
  282. package/dist/infra/opencandle-paths.js.map +0 -1
  283. package/dist/infra/rate-limiter.js.map +0 -1
  284. package/dist/market-state/alert-conditions.js.map +0 -1
  285. package/dist/market-state/alert-runner.js.map +0 -1
  286. package/dist/market-state/daily-report.js.map +0 -1
  287. package/dist/market-state/local-automation-service.js.map +0 -1
  288. package/dist/market-state/notification-delivery.js.map +0 -1
  289. package/dist/market-state/resolve-for-mutation.js.map +0 -1
  290. package/dist/market-state/resolve.js.map +0 -1
  291. package/dist/market-state/service.js.map +0 -1
  292. package/dist/market-state/summaries.js.map +0 -1
  293. package/dist/memory/index.js.map +0 -1
  294. package/dist/memory/manager.js.map +0 -1
  295. package/dist/memory/preference-extractor.js.map +0 -1
  296. package/dist/memory/retrieval.js.map +0 -1
  297. package/dist/memory/sqlite.js.map +0 -1
  298. package/dist/memory/storage.js.map +0 -1
  299. package/dist/memory/tool-defaults.js.map +0 -1
  300. package/dist/memory/types.js.map +0 -1
  301. package/dist/monitor.js.map +0 -1
  302. package/dist/onboarding/connect.js.map +0 -1
  303. package/dist/onboarding/credential-interceptor.js.map +0 -1
  304. package/dist/onboarding/degradation-accumulator.js.map +0 -1
  305. package/dist/onboarding/prompt-user.js.map +0 -1
  306. package/dist/onboarding/provider-status.js.map +0 -1
  307. package/dist/onboarding/providers.js.map +0 -1
  308. package/dist/onboarding/state.js.map +0 -1
  309. package/dist/onboarding/tool-helpers.js.map +0 -1
  310. package/dist/onboarding/tool-tags.js.map +0 -1
  311. package/dist/onboarding/validation.js.map +0 -1
  312. package/dist/pi/opencandle-extension.js.map +0 -1
  313. package/dist/pi/session-action-dedupe.js.map +0 -1
  314. package/dist/pi/session-storage.js.map +0 -1
  315. package/dist/pi/session-writer-lock.js.map +0 -1
  316. package/dist/pi/session.js.map +0 -1
  317. package/dist/pi/setup.js.map +0 -1
  318. package/dist/pi/tool-adapter.js.map +0 -1
  319. package/dist/pi/tui-session-coordinator.js.map +0 -1
  320. package/dist/prompts/context-builder.js.map +0 -1
  321. package/dist/prompts/disclaimer.js.map +0 -1
  322. package/dist/prompts/policy-cards.js.map +0 -1
  323. package/dist/prompts/sections.js.map +0 -1
  324. package/dist/prompts/symbol-preflight.js.map +0 -1
  325. package/dist/prompts/workflow-prompts.js.map +0 -1
  326. package/dist/providers/alpha-vantage.js.map +0 -1
  327. package/dist/providers/coingecko.js.map +0 -1
  328. package/dist/providers/errors.js.map +0 -1
  329. package/dist/providers/exa-search.js.map +0 -1
  330. package/dist/providers/external-tool-command.js.map +0 -1
  331. package/dist/providers/external-tool-error.js.map +0 -1
  332. package/dist/providers/fear-greed.js.map +0 -1
  333. package/dist/providers/finnhub.js.map +0 -1
  334. package/dist/providers/fred.js.map +0 -1
  335. package/dist/providers/index.js.map +0 -1
  336. package/dist/providers/polymarket.js.map +0 -1
  337. package/dist/providers/provider-credential-error.js.map +0 -1
  338. package/dist/providers/reddit-cli.js.map +0 -1
  339. package/dist/providers/reddit.js.map +0 -1
  340. package/dist/providers/sec-edgar.js.map +0 -1
  341. package/dist/providers/tradingview.js.map +0 -1
  342. package/dist/providers/twitter-cli.js.map +0 -1
  343. package/dist/providers/twitter.js.map +0 -1
  344. package/dist/providers/web-search.js.map +0 -1
  345. package/dist/providers/with-fallback.js.map +0 -1
  346. package/dist/providers/wrap-provider.js.map +0 -1
  347. package/dist/providers/yahoo-finance.js.map +0 -1
  348. package/dist/routing/classify-intent.js.map +0 -1
  349. package/dist/routing/defaults.js.map +0 -1
  350. package/dist/routing/entity-extractor.js.map +0 -1
  351. package/dist/routing/fund-symbols.js.map +0 -1
  352. package/dist/routing/horizon.js.map +0 -1
  353. package/dist/routing/index.js.map +0 -1
  354. package/dist/routing/legacy-rule-router.js.map +0 -1
  355. package/dist/routing/planning.js.map +0 -1
  356. package/dist/routing/route-manifest.js.map +0 -1
  357. package/dist/routing/router-llm-client.js.map +0 -1
  358. package/dist/routing/router-prompt.js.map +0 -1
  359. package/dist/routing/router-types.js.map +0 -1
  360. package/dist/routing/router.js.map +0 -1
  361. package/dist/routing/slot-resolver.js.map +0 -1
  362. package/dist/routing/symbol-disambiguator.js.map +0 -1
  363. package/dist/routing/turn-context.js.map +0 -1
  364. package/dist/routing/types.js.map +0 -1
  365. package/dist/runtime/answer-contracts.js.map +0 -1
  366. package/dist/runtime/artifact-contracts.js.map +0 -1
  367. package/dist/runtime/evidence.js.map +0 -1
  368. package/dist/runtime/numeric-claims.js.map +0 -1
  369. package/dist/runtime/planning-evidence.js.map +0 -1
  370. package/dist/runtime/prompt-step.js.map +0 -1
  371. package/dist/runtime/provider-tracker.js.map +0 -1
  372. package/dist/runtime/run-context.js.map +0 -1
  373. package/dist/runtime/session-coordinator.js.map +0 -1
  374. package/dist/runtime/session-title.js.map +0 -1
  375. package/dist/runtime/tool-defaults-wrapper.js.map +0 -1
  376. package/dist/runtime/validation.js.map +0 -1
  377. package/dist/runtime/workflow-events.js.map +0 -1
  378. package/dist/runtime/workflow-runner.js.map +0 -1
  379. package/dist/runtime/workflow-types.js.map +0 -1
  380. package/dist/sentiment/adapters/finnhub.js.map +0 -1
  381. package/dist/sentiment/adapters/reddit.js.map +0 -1
  382. package/dist/sentiment/adapters/twitter.js.map +0 -1
  383. package/dist/sentiment/adapters/web.js.map +0 -1
  384. package/dist/sentiment/index.js.map +0 -1
  385. package/dist/sentiment/insights.js.map +0 -1
  386. package/dist/sentiment/keywords.js.map +0 -1
  387. package/dist/sentiment/pipeline.js.map +0 -1
  388. package/dist/sentiment/scorer.js.map +0 -1
  389. package/dist/sentiment/store.js.map +0 -1
  390. package/dist/sentiment/trends.js.map +0 -1
  391. package/dist/sentiment/types.js.map +0 -1
  392. package/dist/system-prompt.js.map +0 -1
  393. package/dist/tool-kit.js.map +0 -1
  394. package/dist/tools/fundamentals/company-overview.js.map +0 -1
  395. package/dist/tools/fundamentals/comps.js.map +0 -1
  396. package/dist/tools/fundamentals/dcf.js.map +0 -1
  397. package/dist/tools/fundamentals/earnings.js.map +0 -1
  398. package/dist/tools/fundamentals/financials.js.map +0 -1
  399. package/dist/tools/fundamentals/sec-filings.js.map +0 -1
  400. package/dist/tools/index.js.map +0 -1
  401. package/dist/tools/interaction/ask-user.js.map +0 -1
  402. package/dist/tools/macro/event-probabilities.js.map +0 -1
  403. package/dist/tools/macro/fear-greed.js.map +0 -1
  404. package/dist/tools/macro/fred-data.js.map +0 -1
  405. package/dist/tools/market/crypto-history.js.map +0 -1
  406. package/dist/tools/market/crypto-price.js.map +0 -1
  407. package/dist/tools/market/screen-stocks.js.map +0 -1
  408. package/dist/tools/market/search-ticker.js.map +0 -1
  409. package/dist/tools/market/stock-history.js.map +0 -1
  410. package/dist/tools/market/stock-quote.js.map +0 -1
  411. package/dist/tools/options/greeks.js.map +0 -1
  412. package/dist/tools/options/option-chain.js.map +0 -1
  413. package/dist/tools/portfolio/alerts.js.map +0 -1
  414. package/dist/tools/portfolio/correlation.js.map +0 -1
  415. package/dist/tools/portfolio/daily-report.js.map +0 -1
  416. package/dist/tools/portfolio/holdings-overlap.js.map +0 -1
  417. package/dist/tools/portfolio/notifications.js.map +0 -1
  418. package/dist/tools/portfolio/risk-analysis.js.map +0 -1
  419. package/dist/tools/portfolio/tracker.js.map +0 -1
  420. package/dist/tools/portfolio/watchlist.js.map +0 -1
  421. package/dist/tools/sentiment/insight-format.js.map +0 -1
  422. package/dist/tools/sentiment/query-match.js.map +0 -1
  423. package/dist/tools/sentiment/reddit-sentiment.js.map +0 -1
  424. package/dist/tools/sentiment/sentiment-summary.js.map +0 -1
  425. package/dist/tools/sentiment/sentiment-trend.js.map +0 -1
  426. package/dist/tools/sentiment/twitter-sentiment.js.map +0 -1
  427. package/dist/tools/sentiment/untrusted-text.js.map +0 -1
  428. package/dist/tools/sentiment/web-search.js.map +0 -1
  429. package/dist/tools/sentiment/web-sentiment.js.map +0 -1
  430. package/dist/tools/technical/backtest.js.map +0 -1
  431. package/dist/tools/technical/indicators.js.map +0 -1
  432. package/dist/types/fundamentals.js.map +0 -1
  433. package/dist/types/index.js.map +0 -1
  434. package/dist/types/macro.js.map +0 -1
  435. package/dist/types/market.js.map +0 -1
  436. package/dist/types/options.js.map +0 -1
  437. package/dist/types/portfolio.js.map +0 -1
  438. package/dist/types/prediction-markets.js.map +0 -1
  439. package/dist/types/sentiment.js.map +0 -1
  440. package/dist/workflows/compare-assets.js.map +0 -1
  441. package/dist/workflows/index.js.map +0 -1
  442. package/dist/workflows/options-screener.js.map +0 -1
  443. package/dist/workflows/portfolio-builder.js.map +0 -1
  444. package/gui/server/ask-user-bridge.ts +0 -89
  445. package/gui/server/automation-heartbeat.ts +0 -97
  446. package/gui/server/background-quotes.ts +0 -127
  447. package/gui/server/chat-event-adapter.ts +0 -294
  448. package/gui/server/gui-session-manager.ts +0 -5
  449. package/gui/server/http-routes.ts +0 -1201
  450. package/gui/server/invoke-tool.ts +0 -490
  451. package/gui/server/live-chat-event-adapter.ts +0 -243
  452. package/gui/server/local-session-coordinator.ts +0 -97
  453. package/gui/server/market-state-api.ts +0 -331
  454. package/gui/server/model-setup.ts +0 -254
  455. package/gui/server/package.json +0 -5
  456. package/gui/server/private-api-access.ts +0 -62
  457. package/gui/server/projector.ts +0 -392
  458. package/gui/server/prompt-observation.ts +0 -58
  459. package/gui/server/quote-snapshot-store.ts +0 -50
  460. package/gui/server/server.ts +0 -289
  461. package/gui/server/session-actions.ts +0 -323
  462. package/gui/server/session-entry-wait.ts +0 -179
  463. package/gui/server/shutdown.ts +0 -47
  464. package/gui/server/tool-invoke-ack.ts +0 -49
  465. package/gui/server/tool-metadata.ts +0 -167
  466. package/gui/server/websocket.ts +0 -138
  467. package/gui/server/writer-lock.ts +0 -1
  468. package/gui/server/ws-hub.ts +0 -403
  469. package/gui/shared/chat-events.ts +0 -165
  470. package/gui/shared/event-reducer.ts +0 -220
  471. package/gui/web/dist/assets/CatalogOverlay-DZ1niyQm.js +0 -1
  472. package/gui/web/dist/assets/index-D4F9AJnn.css +0 -2
  473. package/gui/web/dist/assets/index-DtqMMBTr.js +0 -65
  474. package/src/analysts/contracts.ts +0 -176
  475. package/src/analysts/orchestrator.ts +0 -244
  476. package/src/cli-main.ts +0 -510
  477. package/src/cli.ts +0 -17
  478. package/src/config.ts +0 -272
  479. package/src/doctor/cli-command.ts +0 -83
  480. package/src/doctor/render.ts +0 -37
  481. package/src/doctor/report.ts +0 -638
  482. package/src/index.ts +0 -5
  483. package/src/infra/cache.ts +0 -127
  484. package/src/infra/freshness.ts +0 -165
  485. package/src/infra/http-client.ts +0 -134
  486. package/src/infra/index.ts +0 -14
  487. package/src/infra/market-calendar.ts +0 -193
  488. package/src/infra/native-dependencies.ts +0 -84
  489. package/src/infra/node-version.ts +0 -23
  490. package/src/infra/open-url.ts +0 -28
  491. package/src/infra/opencandle-paths.ts +0 -53
  492. package/src/infra/rate-limiter.ts +0 -77
  493. package/src/market-state/alert-conditions.ts +0 -82
  494. package/src/market-state/alert-runner.ts +0 -863
  495. package/src/market-state/daily-report.ts +0 -237
  496. package/src/market-state/local-automation-service.ts +0 -162
  497. package/src/market-state/notification-delivery.ts +0 -158
  498. package/src/market-state/resolve-for-mutation.ts +0 -24
  499. package/src/market-state/resolve.ts +0 -112
  500. package/src/market-state/service.ts +0 -2208
  501. package/src/market-state/summaries.ts +0 -75
  502. package/src/memory/index.ts +0 -10
  503. package/src/memory/manager.ts +0 -190
  504. package/src/memory/preference-extractor.ts +0 -106
  505. package/src/memory/retrieval.ts +0 -71
  506. package/src/memory/sqlite.ts +0 -577
  507. package/src/memory/storage.ts +0 -195
  508. package/src/memory/tool-defaults.ts +0 -108
  509. package/src/memory/types.ts +0 -71
  510. package/src/monitor.ts +0 -123
  511. package/src/onboarding/connect.ts +0 -177
  512. package/src/onboarding/credential-interceptor.ts +0 -122
  513. package/src/onboarding/degradation-accumulator.ts +0 -77
  514. package/src/onboarding/prompt-user.ts +0 -85
  515. package/src/onboarding/provider-status.ts +0 -382
  516. package/src/onboarding/providers.ts +0 -442
  517. package/src/onboarding/state.ts +0 -216
  518. package/src/onboarding/tool-helpers.ts +0 -104
  519. package/src/onboarding/tool-tags.ts +0 -244
  520. package/src/onboarding/validation.ts +0 -152
  521. package/src/pi/opencandle-extension.ts +0 -1294
  522. package/src/pi/session-action-dedupe.ts +0 -155
  523. package/src/pi/session-storage.ts +0 -5
  524. package/src/pi/session-writer-lock.ts +0 -426
  525. package/src/pi/session.ts +0 -84
  526. package/src/pi/setup.ts +0 -399
  527. package/src/pi/tool-adapter.ts +0 -49
  528. package/src/pi/tui-session-coordinator.ts +0 -351
  529. package/src/prompts/context-builder.ts +0 -326
  530. package/src/prompts/disclaimer.ts +0 -9
  531. package/src/prompts/policy-cards.ts +0 -228
  532. package/src/prompts/sections.ts +0 -46
  533. package/src/prompts/symbol-preflight.ts +0 -80
  534. package/src/prompts/workflow-prompts.ts +0 -504
  535. package/src/providers/alpha-vantage.ts +0 -340
  536. package/src/providers/coingecko.ts +0 -95
  537. package/src/providers/errors.ts +0 -9
  538. package/src/providers/exa-search.ts +0 -375
  539. package/src/providers/external-tool-command.ts +0 -164
  540. package/src/providers/external-tool-error.ts +0 -20
  541. package/src/providers/fear-greed.ts +0 -45
  542. package/src/providers/finnhub.ts +0 -125
  543. package/src/providers/fred.ts +0 -83
  544. package/src/providers/index.ts +0 -17
  545. package/src/providers/polymarket.ts +0 -214
  546. package/src/providers/provider-credential-error.ts +0 -23
  547. package/src/providers/reddit-cli.ts +0 -286
  548. package/src/providers/reddit.ts +0 -106
  549. package/src/providers/sec-edgar.ts +0 -326
  550. package/src/providers/tradingview.ts +0 -399
  551. package/src/providers/twitter-cli.ts +0 -202
  552. package/src/providers/twitter.ts +0 -102
  553. package/src/providers/web-search.ts +0 -303
  554. package/src/providers/with-fallback.ts +0 -42
  555. package/src/providers/wrap-provider.ts +0 -105
  556. package/src/providers/yahoo-finance.ts +0 -984
  557. package/src/routing/classify-intent.ts +0 -380
  558. package/src/routing/defaults.ts +0 -29
  559. package/src/routing/entity-extractor.ts +0 -557
  560. package/src/routing/fund-symbols.ts +0 -58
  561. package/src/routing/horizon.ts +0 -7
  562. package/src/routing/index.ts +0 -70
  563. package/src/routing/legacy-rule-router.ts +0 -13
  564. package/src/routing/planning.ts +0 -829
  565. package/src/routing/route-manifest.ts +0 -308
  566. package/src/routing/router-llm-client.ts +0 -64
  567. package/src/routing/router-prompt.ts +0 -159
  568. package/src/routing/router-types.ts +0 -84
  569. package/src/routing/router.ts +0 -1332
  570. package/src/routing/slot-resolver.ts +0 -213
  571. package/src/routing/symbol-disambiguator.ts +0 -72
  572. package/src/routing/turn-context.ts +0 -108
  573. package/src/routing/types.ts +0 -77
  574. package/src/runtime/answer-contracts.ts +0 -693
  575. package/src/runtime/artifact-contracts.ts +0 -77
  576. package/src/runtime/evidence.ts +0 -78
  577. package/src/runtime/numeric-claims.ts +0 -108
  578. package/src/runtime/planning-evidence.ts +0 -597
  579. package/src/runtime/prompt-step.ts +0 -185
  580. package/src/runtime/provider-tracker.ts +0 -40
  581. package/src/runtime/run-context.ts +0 -32
  582. package/src/runtime/session-coordinator.ts +0 -1037
  583. package/src/runtime/session-title.ts +0 -60
  584. package/src/runtime/tool-defaults-wrapper.ts +0 -43
  585. package/src/runtime/validation.ts +0 -211
  586. package/src/runtime/workflow-events.ts +0 -77
  587. package/src/runtime/workflow-runner.ts +0 -182
  588. package/src/runtime/workflow-types.ts +0 -105
  589. package/src/sentiment/adapters/finnhub.ts +0 -49
  590. package/src/sentiment/adapters/reddit.ts +0 -65
  591. package/src/sentiment/adapters/twitter.ts +0 -36
  592. package/src/sentiment/adapters/web.ts +0 -44
  593. package/src/sentiment/index.ts +0 -49
  594. package/src/sentiment/insights.ts +0 -269
  595. package/src/sentiment/keywords.ts +0 -31
  596. package/src/sentiment/pipeline.ts +0 -91
  597. package/src/sentiment/scorer.ts +0 -89
  598. package/src/sentiment/store.ts +0 -260
  599. package/src/sentiment/trends.ts +0 -96
  600. package/src/sentiment/types.ts +0 -112
  601. package/src/system-prompt.ts +0 -115
  602. package/src/tool-kit.ts +0 -69
  603. package/src/tools/AGENTS.md +0 -36
  604. package/src/tools/fundamentals/company-overview.ts +0 -64
  605. package/src/tools/fundamentals/comps.ts +0 -180
  606. package/src/tools/fundamentals/dcf.ts +0 -447
  607. package/src/tools/fundamentals/earnings.ts +0 -57
  608. package/src/tools/fundamentals/financials.ts +0 -63
  609. package/src/tools/fundamentals/sec-filings.ts +0 -105
  610. package/src/tools/index.ts +0 -104
  611. package/src/tools/interaction/ask-user.ts +0 -93
  612. package/src/tools/macro/event-probabilities.ts +0 -141
  613. package/src/tools/macro/fear-greed.ts +0 -41
  614. package/src/tools/macro/fred-data.ts +0 -92
  615. package/src/tools/market/crypto-history.ts +0 -72
  616. package/src/tools/market/crypto-price.ts +0 -65
  617. package/src/tools/market/screen-stocks.ts +0 -290
  618. package/src/tools/market/search-ticker.ts +0 -254
  619. package/src/tools/market/stock-history.ts +0 -104
  620. package/src/tools/market/stock-quote.ts +0 -73
  621. package/src/tools/options/greeks.ts +0 -81
  622. package/src/tools/options/option-chain.ts +0 -134
  623. package/src/tools/portfolio/alerts.ts +0 -457
  624. package/src/tools/portfolio/correlation.ts +0 -189
  625. package/src/tools/portfolio/daily-report.ts +0 -107
  626. package/src/tools/portfolio/holdings-overlap.ts +0 -139
  627. package/src/tools/portfolio/notifications.ts +0 -45
  628. package/src/tools/portfolio/risk-analysis.ts +0 -173
  629. package/src/tools/portfolio/tracker.ts +0 -308
  630. package/src/tools/portfolio/watchlist.ts +0 -288
  631. package/src/tools/sentiment/insight-format.ts +0 -50
  632. package/src/tools/sentiment/query-match.ts +0 -117
  633. package/src/tools/sentiment/reddit-sentiment.ts +0 -403
  634. package/src/tools/sentiment/sentiment-summary.ts +0 -383
  635. package/src/tools/sentiment/sentiment-trend.ts +0 -75
  636. package/src/tools/sentiment/twitter-sentiment.ts +0 -287
  637. package/src/tools/sentiment/untrusted-text.ts +0 -21
  638. package/src/tools/sentiment/web-search.ts +0 -186
  639. package/src/tools/sentiment/web-sentiment.ts +0 -96
  640. package/src/tools/technical/backtest.ts +0 -336
  641. package/src/tools/technical/indicators.ts +0 -281
  642. package/src/types/fundamentals.ts +0 -47
  643. package/src/types/index.ts +0 -26
  644. package/src/types/macro.ts +0 -27
  645. package/src/types/market.ts +0 -46
  646. package/src/types/options.ts +0 -53
  647. package/src/types/portfolio.ts +0 -83
  648. package/src/types/prediction-markets.ts +0 -13
  649. package/src/types/sentiment.ts +0 -129
  650. package/src/workflows/compare-assets.ts +0 -89
  651. package/src/workflows/index.ts +0 -3
  652. package/src/workflows/options-screener.ts +0 -125
  653. package/src/workflows/portfolio-builder.ts +0 -63
@@ -1,104 +0,0 @@
1
- // Tool-boundary helpers for credentialed providers.
2
- //
3
- // `withCredentialCheck` is the single-entry helper that OpenCandle tools use
4
- // to wrap their provider calls. It centralizes:
5
- // 1. The upfront "credential missing" check via the registry.
6
- // 2. The catch-and-convert logic for `ProviderCredentialError` thrown from
7
- // providers on 401/403 (stale credential after HTTP call).
8
- // 3. The tagged `[OPENCANDLE_CREDENTIAL_REQUIRED ...]` content emission that
9
- // the Pi `tool_result` extension hook intercepts.
10
- //
11
- // Non-credential errors (network timeouts, parse errors, etc.) are re-thrown
12
- // unchanged so existing error handling in `wrapProvider` continues to work.
13
-
14
- import type { AgentToolResult } from "@earendil-works/pi-agent-core";
15
- import { ProviderCredentialError } from "../providers/provider-credential-error.js";
16
- import { getProvider, hasCredential, type ProviderId } from "./providers.js";
17
- import { buildCredentialRequiredTag, type CredentialRequiredReason } from "./tool-tags.js";
18
-
19
- // Metadata carried on `details` for UI / test assertion. This is NOT the
20
- // LLM-facing contract — that lives in `content` as the tagged line. Pi
21
- // provider adapters serialize `content`, not `details`, into the model's
22
- // conversation.
23
- export interface CredentialRequiredDetails {
24
- credentialRequired: {
25
- provider: ProviderId;
26
- reason: CredentialRequiredReason;
27
- httpStatus?: number;
28
- };
29
- }
30
-
31
- function buildCredentialRequiredResult(
32
- provider: ProviderId,
33
- reason: CredentialRequiredReason,
34
- httpStatus?: number,
35
- ): AgentToolResult<CredentialRequiredDetails> {
36
- const descriptor = getProvider(provider);
37
- const tag = buildCredentialRequiredTag({
38
- provider,
39
- reason,
40
- unlocks: descriptor.unlocks,
41
- fallback: descriptor.fallbackDescription,
42
- httpStatus,
43
- });
44
- // The second line is natural language describing what's missing. Users won't
45
- // see it directly — the model sees it and uses the information to synthesize
46
- // a gap note in its final answer. The tagged first line is the machine-
47
- // readable signal the `tool_result` interception handler keys off of.
48
- const narrative =
49
- reason === "missing"
50
- ? `${descriptor.displayName} was not fetched for this request because no API key is configured. It unlocks ${descriptor.unlocks.join(", ")}.`
51
- : `${descriptor.displayName} rejected the configured API key (HTTP ${httpStatus ?? "auth error"}). It may be expired or revoked.`;
52
-
53
- return {
54
- content: [{ type: "text", text: `${tag}\n\n${narrative}` }],
55
- details: {
56
- credentialRequired: {
57
- provider,
58
- reason,
59
- ...(httpStatus !== undefined ? { httpStatus } : {}),
60
- },
61
- },
62
- };
63
- }
64
-
65
- /**
66
- * Wrap a tool's provider-calling logic with a credential-check layer.
67
- *
68
- * Usage:
69
- * ```
70
- * async execute(_, args) {
71
- * return withCredentialCheck("alpha_vantage", async () => {
72
- * const apiKey = getConfig().alphaVantageApiKey!;
73
- * const result = await wrapProvider("alphavantage", () => getFinancials(args.symbol, apiKey));
74
- * // ... format success result ...
75
- * return { content: [...], details: [...] };
76
- * });
77
- * }
78
- * ```
79
- *
80
- * On missing credential (upfront): `fn` is NOT called. A tagged tool result
81
- * is returned directly.
82
- *
83
- * On `ProviderCredentialError` thrown during `fn`: the error is caught and a
84
- * tagged tool result is returned.
85
- *
86
- * Any other thrown value (plain Error, string, etc.) is re-thrown unchanged.
87
- */
88
- export async function withCredentialCheck<T>(
89
- providerId: ProviderId,
90
- fn: () => Promise<AgentToolResult<T>>,
91
- ): Promise<AgentToolResult<T> | AgentToolResult<CredentialRequiredDetails>> {
92
- if (!hasCredential(providerId)) {
93
- return buildCredentialRequiredResult(providerId, "missing");
94
- }
95
-
96
- try {
97
- return await fn();
98
- } catch (error) {
99
- if (error instanceof ProviderCredentialError) {
100
- return buildCredentialRequiredResult(error.provider, error.reason, error.httpStatus);
101
- }
102
- throw error;
103
- }
104
- }
@@ -1,244 +0,0 @@
1
- // Tool-result text tags used by OpenCandle's conversational-provider-setup
2
- // flow. These tagged lines are the LLM-facing contract — Pi provider adapters
3
- // serialize the `content` field of tool results into the model's conversation,
4
- // so any signal we want the model to reason over must live in text, not
5
- // `details`.
6
- //
7
- // Tag format (single line, parseable):
8
- // [OPENCANDLE_<KIND> field=value field2=value ... ]
9
- //
10
- // Values may be:
11
- // - bare: provider=alpha_vantage reason=missing silenced=true httpStatus=401
12
- // - quoted (for spaces or commas): remediation="run /connect economy"
13
- // - lists (comma-separated inside quotes): unlocks="fundamentals, DCF"
14
- // - null/absent: fallback=none
15
- //
16
- // Parser is tolerant of unknown fields and extra whitespace.
17
-
18
- import type { ProviderId } from "./providers.js";
19
-
20
- // -----------------------------------------------------------------------------
21
- // Public types
22
- // -----------------------------------------------------------------------------
23
-
24
- export type CredentialRequiredReason = "missing" | "stale";
25
- export type ExternalToolRequiredReason = "not_installed" | "session_missing" | "session_stale";
26
-
27
- export interface CredentialRequiredTagFields {
28
- provider: ProviderId;
29
- reason: CredentialRequiredReason;
30
- unlocks: readonly string[];
31
- fallback: string | null;
32
- httpStatus?: number;
33
- }
34
-
35
- export interface SoftDegradedTagFields {
36
- provider: ProviderId;
37
- fallback: string;
38
- remediation: string;
39
- }
40
-
41
- export interface SkippedTagFields {
42
- provider: ProviderId;
43
- reason: "credential_not_provided";
44
- remediation: string;
45
- silenced?: boolean;
46
- }
47
-
48
- export interface ConnectedTagFields {
49
- provider: ProviderId;
50
- }
51
-
52
- export interface ExternalToolRequiredTagFields {
53
- provider: ProviderId;
54
- reason: ExternalToolRequiredReason;
55
- installCmd: string;
56
- loginCmd?: string;
57
- fallback: string | null;
58
- }
59
-
60
- export type ParsedTag =
61
- | ({ kind: "credential_required" } & CredentialRequiredTagFields)
62
- | ({ kind: "soft_degraded" } & SoftDegradedTagFields)
63
- | ({ kind: "skipped" } & SkippedTagFields)
64
- | ({ kind: "connected" } & ConnectedTagFields)
65
- | ({ kind: "external_tool_required" } & ExternalToolRequiredTagFields);
66
-
67
- // -----------------------------------------------------------------------------
68
- // Builders
69
- // -----------------------------------------------------------------------------
70
-
71
- function quote(value: string): string {
72
- return `"${value.replace(/"/g, '\\"')}"`;
73
- }
74
-
75
- function formatField(key: string, value: string | number | boolean): string {
76
- return `${key}=${value}`;
77
- }
78
-
79
- export function buildCredentialRequiredTag(fields: CredentialRequiredTagFields): string {
80
- const parts: string[] = [
81
- "[OPENCANDLE_CREDENTIAL_REQUIRED",
82
- formatField("provider", fields.provider),
83
- formatField("reason", fields.reason),
84
- `unlocks=${quote(fields.unlocks.join(", "))}`,
85
- formatField("fallback", fields.fallback ?? "none"),
86
- ];
87
- if (fields.httpStatus !== undefined) {
88
- parts.push(formatField("httpStatus", fields.httpStatus));
89
- }
90
- return `${parts.join(" ")}]`;
91
- }
92
-
93
- export function buildSoftDegradedTag(fields: SoftDegradedTagFields): string {
94
- return `${[
95
- "[OPENCANDLE_SOFT_DEGRADED",
96
- formatField("provider", fields.provider),
97
- formatField("fallback", fields.fallback),
98
- `remediation=${quote(fields.remediation)}`,
99
- ].join(" ")}]`;
100
- }
101
-
102
- export function buildSkippedTag(fields: SkippedTagFields): string {
103
- const parts: string[] = [
104
- "[OPENCANDLE_SKIPPED",
105
- formatField("provider", fields.provider),
106
- formatField("reason", fields.reason),
107
- `remediation=${quote(fields.remediation)}`,
108
- ];
109
- if (fields.silenced) {
110
- parts.push(formatField("silenced", "true"));
111
- }
112
- return `${parts.join(" ")}]`;
113
- }
114
-
115
- export function buildConnectedTag(fields: ConnectedTagFields): string {
116
- return `[OPENCANDLE_CONNECTED provider=${fields.provider}]`;
117
- }
118
-
119
- export function buildExternalToolRequiredTag(fields: ExternalToolRequiredTagFields): string {
120
- const parts: string[] = [
121
- "[OPENCANDLE_EXTERNAL_TOOL_REQUIRED",
122
- formatField("provider", fields.provider),
123
- formatField("reason", fields.reason),
124
- `installCmd=${quote(fields.installCmd)}`,
125
- formatField("fallback", fields.fallback ?? "none"),
126
- ];
127
- if (fields.loginCmd) parts.push(`loginCmd=${quote(fields.loginCmd)}`);
128
- return `${parts.join(" ")}]`;
129
- }
130
-
131
- // -----------------------------------------------------------------------------
132
- // Parser
133
- // -----------------------------------------------------------------------------
134
-
135
- const TAG_LINE_REGEX =
136
- /\[OPENCANDLE_(CREDENTIAL_REQUIRED|SOFT_DEGRADED|SKIPPED|CONNECTED|EXTERNAL_TOOL_REQUIRED)([^\]]*)\]/;
137
-
138
- function parseFields(raw: string): Record<string, string> {
139
- // Split on `key=value` pairs, respecting quoted values.
140
- const fields: Record<string, string> = {};
141
- const pattern = /(\w+)=("((?:[^"\\]|\\.)*)"|([^\s\]]+))/g;
142
- while (true) {
143
- const match = pattern.exec(raw);
144
- if (!match) break;
145
- const key = match[1];
146
- const value = match[3] !== undefined ? match[3].replace(/\\"/g, '"') : match[4];
147
- fields[key] = value;
148
- }
149
- return fields;
150
- }
151
-
152
- export function parseToolTag(text: string): ParsedTag | undefined {
153
- const match = TAG_LINE_REGEX.exec(text);
154
- if (!match) return undefined;
155
-
156
- const kind = match[1];
157
- const rest = match[2];
158
- const fields = parseFields(rest);
159
-
160
- switch (kind) {
161
- case "CREDENTIAL_REQUIRED": {
162
- const provider = fields.provider;
163
- const reason = fields.reason;
164
- const unlocksRaw = fields.unlocks ?? "";
165
- const fallbackRaw = fields.fallback;
166
- if (!provider || (reason !== "missing" && reason !== "stale")) {
167
- return undefined;
168
- }
169
- const unlocks = unlocksRaw
170
- .split(",")
171
- .map((s) => s.trim())
172
- .filter((s) => s.length > 0);
173
- const fallback = fallbackRaw === undefined || fallbackRaw === "none" ? null : fallbackRaw;
174
- const parsed: ParsedTag = {
175
- kind: "credential_required",
176
- provider: provider as ProviderId,
177
- reason: reason as CredentialRequiredReason,
178
- unlocks,
179
- fallback,
180
- };
181
- if (fields.httpStatus !== undefined) {
182
- const n = Number(fields.httpStatus);
183
- if (!Number.isNaN(n)) parsed.httpStatus = n;
184
- }
185
- return parsed;
186
- }
187
-
188
- case "SOFT_DEGRADED": {
189
- const { provider, fallback, remediation } = fields;
190
- if (!provider || !fallback || !remediation) return undefined;
191
- return {
192
- kind: "soft_degraded",
193
- provider: provider as ProviderId,
194
- fallback,
195
- remediation,
196
- };
197
- }
198
-
199
- case "SKIPPED": {
200
- const { provider, reason, remediation } = fields;
201
- if (!provider || reason !== "credential_not_provided" || !remediation) {
202
- return undefined;
203
- }
204
- const parsed: ParsedTag = {
205
- kind: "skipped",
206
- provider: provider as ProviderId,
207
- reason: "credential_not_provided",
208
- remediation,
209
- };
210
- if (fields.silenced === "true") parsed.silenced = true;
211
- return parsed;
212
- }
213
-
214
- case "CONNECTED": {
215
- const { provider } = fields;
216
- if (!provider) return undefined;
217
- return { kind: "connected", provider: provider as ProviderId };
218
- }
219
-
220
- case "EXTERNAL_TOOL_REQUIRED": {
221
- const { provider, reason, installCmd, loginCmd, fallback } = fields;
222
- if (
223
- !provider ||
224
- (reason !== "not_installed" &&
225
- reason !== "session_missing" &&
226
- reason !== "session_stale") ||
227
- !installCmd
228
- ) {
229
- return undefined;
230
- }
231
- return {
232
- kind: "external_tool_required",
233
- provider: provider as ProviderId,
234
- reason,
235
- installCmd,
236
- loginCmd,
237
- fallback: fallback === undefined || fallback === "none" ? null : fallback,
238
- };
239
- }
240
-
241
- default:
242
- return undefined;
243
- }
244
- }
@@ -1,152 +0,0 @@
1
- // Pre-persist credential validation for OpenCandle data providers.
2
- //
3
- // Each `validateCredential` call makes a single cheap request to the
4
- // provider's canonical API with the pasted key and classifies the response
5
- // into one of three states:
6
- //
7
- // - `valid` — provider accepted the credential (persist it)
8
- // - `invalid` — provider rejected the credential (do NOT persist;
9
- // re-prompt or return a classified failure)
10
- // - `transient` — network/timeout/server error (persist anyway; the next
11
- // tool call will surface any real issue and re-open the
12
- // prompt via the credential-required tag)
13
- //
14
- // The endpoint chosen for each provider is the cheapest one available that
15
- // also exercises the auth header/query param — we don't pay for meaningful
16
- // data, just "did the server like the key". Alpha Vantage is a special case:
17
- // it returns HTTP 200 even for bad keys, with an `Error Message` or
18
- // `Information` field in the JSON body, so the body must be inspected.
19
- //
20
- // All validators share a 5-second timeout via `AbortSignal.timeout` so the
21
- // connect flow cannot hang if a provider is unreachable.
22
-
23
- import type { ApiKeyProviderId } from "./providers.js";
24
-
25
- const VALIDATION_TIMEOUT_MS = 5_000;
26
-
27
- export type ValidationResult =
28
- | { status: "valid" }
29
- | { status: "invalid"; httpStatus?: number; message?: string }
30
- | { status: "transient"; reason: string };
31
-
32
- type BodyClassifier = (body: string) => ValidationResult | undefined;
33
-
34
- async function validateWithFetch(
35
- url: string,
36
- init: RequestInit,
37
- classifyBody?: BodyClassifier,
38
- ): Promise<ValidationResult> {
39
- try {
40
- const response = await fetch(url, {
41
- ...init,
42
- signal: AbortSignal.timeout(VALIDATION_TIMEOUT_MS),
43
- });
44
-
45
- // Hard auth failures — the key is definitively bad.
46
- if (response.status === 401 || response.status === 403) {
47
- return { status: "invalid", httpStatus: response.status };
48
- }
49
-
50
- // FRED returns 400 with an `error_message` for bad keys.
51
- if (response.status === 400) {
52
- return { status: "invalid", httpStatus: 400 };
53
- }
54
-
55
- // 5xx and other non-2xx — treat as transient. Don't block the user on a
56
- // provider outage; the next real tool call will surface a fresh error.
57
- if (!response.ok) {
58
- return { status: "transient", reason: `HTTP ${response.status}` };
59
- }
60
-
61
- // Body-level classification for providers that return 200 with an error
62
- // shape (Alpha Vantage).
63
- if (classifyBody) {
64
- const body = await response.text();
65
- const classified = classifyBody(body);
66
- if (classified) return classified;
67
- }
68
-
69
- return { status: "valid" };
70
- } catch (err) {
71
- const reason = err instanceof Error ? err.message : String(err);
72
- return { status: "transient", reason };
73
- }
74
- }
75
-
76
- /**
77
- * Alpha Vantage returns HTTP 200 with an error shape in the JSON body when
78
- * the key is bad. Two fields to watch for:
79
- * - `Error Message`: indicates a malformed query OR an invalid key
80
- * - `Information`: used for rate-limit messages AND for "Invalid API key"
81
- *
82
- * The rate-limit form of `Information` is NOT an invalid-key signal, so we
83
- * only match when the string mentions "invalid api".
84
- */
85
- function classifyAlphaVantageBody(body: string): ValidationResult | undefined {
86
- try {
87
- const parsed = JSON.parse(body) as Record<string, unknown>;
88
- const errorMessage = parsed["Error Message"];
89
- if (typeof errorMessage === "string" && errorMessage.length > 0) {
90
- return { status: "invalid", message: errorMessage };
91
- }
92
- const information = parsed.Information;
93
- if (typeof information === "string" && /invalid api/i.test(information)) {
94
- return { status: "invalid", message: information };
95
- }
96
- } catch {
97
- // Non-JSON body — fall through and trust the HTTP status.
98
- }
99
- return undefined;
100
- }
101
-
102
- /**
103
- * Validate a pasted credential against the provider's API. Returns a
104
- * ValidationResult describing whether the key should be persisted.
105
- *
106
- * This function is side-effect-free beyond the network call: it does not
107
- * touch the config file, onboarding state, or any in-memory cache.
108
- */
109
- export async function validateCredential(
110
- providerId: ApiKeyProviderId,
111
- key: string,
112
- ): Promise<ValidationResult> {
113
- switch (providerId) {
114
- case "alpha_vantage":
115
- return validateWithFetch(
116
- `https://www.alphavantage.co/query?function=GLOBAL_QUOTE&symbol=IBM&apikey=${encodeURIComponent(key)}`,
117
- { method: "GET" },
118
- classifyAlphaVantageBody,
119
- );
120
-
121
- case "fred":
122
- return validateWithFetch(
123
- `https://api.stlouisfed.org/fred/series?series_id=GDP&api_key=${encodeURIComponent(key)}&file_type=json`,
124
- { method: "GET" },
125
- );
126
-
127
- case "finnhub":
128
- return validateWithFetch(
129
- `https://finnhub.io/api/v1/quote?symbol=AAPL&token=${encodeURIComponent(key)}`,
130
- { method: "GET" },
131
- );
132
-
133
- case "brave":
134
- return validateWithFetch("https://api.search.brave.com/res/v1/web/search?q=test&count=1", {
135
- method: "GET",
136
- headers: {
137
- "X-Subscription-Token": key,
138
- Accept: "application/json",
139
- },
140
- });
141
-
142
- case "exa":
143
- return validateWithFetch("https://api.exa.ai/search", {
144
- method: "POST",
145
- headers: {
146
- "Content-Type": "application/json",
147
- "x-api-key": key,
148
- },
149
- body: JSON.stringify({ query: "test", numResults: 1 }),
150
- });
151
- }
152
- }