opencandle 0.5.0 → 0.6.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 (527) hide show
  1. package/README.md +164 -187
  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 +30 -7
  9. package/dist/cli.js.map +1 -1
  10. package/dist/config.d.ts +3 -3
  11. package/dist/config.js +12 -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/browser.js +3 -1
  17. package/dist/infra/browser.js.map +1 -1
  18. package/dist/infra/cache.d.ts +8 -11
  19. package/dist/infra/cache.js +17 -15
  20. package/dist/infra/cache.js.map +1 -1
  21. package/dist/infra/http-client.d.ts +4 -1
  22. package/dist/infra/http-client.js +59 -6
  23. package/dist/infra/http-client.js.map +1 -1
  24. package/dist/infra/index.d.ts +3 -3
  25. package/dist/infra/index.js +3 -3
  26. package/dist/infra/index.js.map +1 -1
  27. package/dist/infra/native-dependencies.js +2 -2
  28. package/dist/infra/native-dependencies.js.map +1 -1
  29. package/dist/infra/node-version.js.map +1 -1
  30. package/dist/infra/opencandle-paths.d.ts +0 -3
  31. package/dist/infra/opencandle-paths.js +4 -11
  32. package/dist/infra/opencandle-paths.js.map +1 -1
  33. package/dist/infra/rate-limiter.js +12 -9
  34. package/dist/infra/rate-limiter.js.map +1 -1
  35. package/dist/market-state/alert-conditions.d.ts +34 -0
  36. package/dist/market-state/alert-conditions.js +23 -0
  37. package/dist/market-state/alert-conditions.js.map +1 -0
  38. package/dist/market-state/alert-runner.d.ts +55 -0
  39. package/dist/market-state/alert-runner.js +634 -0
  40. package/dist/market-state/alert-runner.js.map +1 -0
  41. package/dist/market-state/daily-report.d.ts +26 -0
  42. package/dist/market-state/daily-report.js +179 -0
  43. package/dist/market-state/daily-report.js.map +1 -0
  44. package/dist/market-state/local-automation-service.d.ts +25 -0
  45. package/dist/market-state/local-automation-service.js +119 -0
  46. package/dist/market-state/local-automation-service.js.map +1 -0
  47. package/dist/market-state/notification-delivery.d.ts +14 -0
  48. package/dist/market-state/notification-delivery.js +139 -0
  49. package/dist/market-state/notification-delivery.js.map +1 -0
  50. package/dist/market-state/resolve-for-mutation.d.ts +10 -0
  51. package/dist/market-state/resolve-for-mutation.js +15 -0
  52. package/dist/market-state/resolve-for-mutation.js.map +1 -0
  53. package/dist/market-state/resolve.d.ts +14 -0
  54. package/dist/market-state/resolve.js +89 -0
  55. package/dist/market-state/resolve.js.map +1 -0
  56. package/dist/market-state/service.d.ts +527 -0
  57. package/dist/market-state/service.js +1099 -0
  58. package/dist/market-state/service.js.map +1 -0
  59. package/dist/memory/index.d.ts +7 -7
  60. package/dist/memory/index.js +6 -6
  61. package/dist/memory/index.js.map +1 -1
  62. package/dist/memory/manager.js +11 -11
  63. package/dist/memory/manager.js.map +1 -1
  64. package/dist/memory/retrieval.js +7 -4
  65. package/dist/memory/retrieval.js.map +1 -1
  66. package/dist/memory/sqlite.js +385 -3
  67. package/dist/memory/sqlite.js.map +1 -1
  68. package/dist/memory/storage.js +1 -2
  69. package/dist/memory/storage.js.map +1 -1
  70. package/dist/memory/tool-defaults.js +64 -28
  71. package/dist/memory/tool-defaults.js.map +1 -1
  72. package/dist/memory/types.js.map +1 -1
  73. package/dist/monitor.d.ts +2 -0
  74. package/dist/monitor.js +104 -0
  75. package/dist/monitor.js.map +1 -0
  76. package/dist/onboarding/connect.js +4 -6
  77. package/dist/onboarding/connect.js.map +1 -1
  78. package/dist/onboarding/credential-interceptor.js +1 -1
  79. package/dist/onboarding/credential-interceptor.js.map +1 -1
  80. package/dist/onboarding/degradation-accumulator.js +1 -3
  81. package/dist/onboarding/degradation-accumulator.js.map +1 -1
  82. package/dist/onboarding/providers.js +3 -16
  83. package/dist/onboarding/providers.js.map +1 -1
  84. package/dist/onboarding/state.js.map +1 -1
  85. package/dist/onboarding/tool-helpers.js +1 -1
  86. package/dist/onboarding/tool-helpers.js.map +1 -1
  87. package/dist/onboarding/tool-tags.js +6 -4
  88. package/dist/onboarding/tool-tags.js.map +1 -1
  89. package/dist/onboarding/validation.js +1 -1
  90. package/dist/onboarding/validation.js.map +1 -1
  91. package/dist/pi/opencandle-extension.d.ts +8 -0
  92. package/dist/pi/opencandle-extension.js +412 -28
  93. package/dist/pi/opencandle-extension.js.map +1 -1
  94. package/dist/pi/session.d.ts +1 -1
  95. package/dist/pi/session.js +3 -1
  96. package/dist/pi/session.js.map +1 -1
  97. package/dist/pi/setup.js +8 -3
  98. package/dist/pi/setup.js.map +1 -1
  99. package/dist/pi/tool-adapter.js +5 -2
  100. package/dist/pi/tool-adapter.js.map +1 -1
  101. package/dist/prompts/context-builder.d.ts +1 -1
  102. package/dist/prompts/context-builder.js +19 -6
  103. package/dist/prompts/context-builder.js.map +1 -1
  104. package/dist/prompts/policy-cards.d.ts +1 -1
  105. package/dist/prompts/policy-cards.js +1 -1
  106. package/dist/prompts/policy-cards.js.map +1 -1
  107. package/dist/prompts/sections.d.ts +1 -1
  108. package/dist/prompts/symbol-preflight.d.ts +20 -0
  109. package/dist/prompts/symbol-preflight.js +49 -0
  110. package/dist/prompts/symbol-preflight.js.map +1 -0
  111. package/dist/prompts/workflow-prompts.d.ts +1 -1
  112. package/dist/prompts/workflow-prompts.js +54 -16
  113. package/dist/prompts/workflow-prompts.js.map +1 -1
  114. package/dist/providers/alpha-vantage.d.ts +1 -1
  115. package/dist/providers/alpha-vantage.js +26 -7
  116. package/dist/providers/alpha-vantage.js.map +1 -1
  117. package/dist/providers/coingecko.js +1 -1
  118. package/dist/providers/coingecko.js.map +1 -1
  119. package/dist/providers/errors.d.ts +5 -0
  120. package/dist/providers/errors.js +11 -0
  121. package/dist/providers/errors.js.map +1 -0
  122. package/dist/providers/exa-search.d.ts +2 -2
  123. package/dist/providers/exa-search.js +19 -11
  124. package/dist/providers/exa-search.js.map +1 -1
  125. package/dist/providers/fear-greed.js +1 -1
  126. package/dist/providers/fear-greed.js.map +1 -1
  127. package/dist/providers/finnhub.js +3 -5
  128. package/dist/providers/finnhub.js.map +1 -1
  129. package/dist/providers/fred.js +2 -2
  130. package/dist/providers/fred.js.map +1 -1
  131. package/dist/providers/index.d.ts +7 -6
  132. package/dist/providers/index.js +6 -5
  133. package/dist/providers/index.js.map +1 -1
  134. package/dist/providers/reddit.js +2 -2
  135. package/dist/providers/reddit.js.map +1 -1
  136. package/dist/providers/sec-edgar.d.ts +1 -0
  137. package/dist/providers/sec-edgar.js +12 -4
  138. package/dist/providers/sec-edgar.js.map +1 -1
  139. package/dist/providers/tradingview.d.ts +47 -0
  140. package/dist/providers/tradingview.js +275 -0
  141. package/dist/providers/tradingview.js.map +1 -0
  142. package/dist/providers/twitter.js +6 -8
  143. package/dist/providers/twitter.js.map +1 -1
  144. package/dist/providers/web-search.js +26 -12
  145. package/dist/providers/web-search.js.map +1 -1
  146. package/dist/providers/with-fallback.js +4 -2
  147. package/dist/providers/with-fallback.js.map +1 -1
  148. package/dist/providers/wrap-provider.d.ts +2 -3
  149. package/dist/providers/wrap-provider.js +14 -8
  150. package/dist/providers/wrap-provider.js.map +1 -1
  151. package/dist/providers/yahoo-finance.d.ts +1 -1
  152. package/dist/providers/yahoo-finance.js +101 -17
  153. package/dist/providers/yahoo-finance.js.map +1 -1
  154. package/dist/routing/classify-intent.d.ts +6 -0
  155. package/dist/routing/classify-intent.js +78 -7
  156. package/dist/routing/classify-intent.js.map +1 -1
  157. package/dist/routing/defaults.d.ts +1 -1
  158. package/dist/routing/entity-extractor.d.ts +1 -0
  159. package/dist/routing/entity-extractor.js +234 -29
  160. package/dist/routing/entity-extractor.js.map +1 -1
  161. package/dist/routing/fund-symbols.d.ts +2 -0
  162. package/dist/routing/fund-symbols.js +55 -0
  163. package/dist/routing/fund-symbols.js.map +1 -0
  164. package/dist/routing/horizon.d.ts +1 -0
  165. package/dist/routing/horizon.js +10 -0
  166. package/dist/routing/horizon.js.map +1 -0
  167. package/dist/routing/index.d.ts +10 -10
  168. package/dist/routing/index.js +6 -6
  169. package/dist/routing/index.js.map +1 -1
  170. package/dist/routing/planning.d.ts +1 -1
  171. package/dist/routing/planning.js +65 -34
  172. package/dist/routing/planning.js.map +1 -1
  173. package/dist/routing/route-manifest.d.ts +2 -2
  174. package/dist/routing/route-manifest.js +25 -4
  175. package/dist/routing/route-manifest.js.map +1 -1
  176. package/dist/routing/router-llm-client.js.map +1 -1
  177. package/dist/routing/router-prompt.js +7 -9
  178. package/dist/routing/router-prompt.js.map +1 -1
  179. package/dist/routing/router-types.d.ts +1 -0
  180. package/dist/routing/router.js +137 -22
  181. package/dist/routing/router.js.map +1 -1
  182. package/dist/routing/slot-resolver.d.ts +1 -1
  183. package/dist/routing/slot-resolver.js +2 -4
  184. package/dist/routing/slot-resolver.js.map +1 -1
  185. package/dist/routing/symbol-disambiguator.d.ts +11 -0
  186. package/dist/routing/symbol-disambiguator.js +52 -0
  187. package/dist/routing/symbol-disambiguator.js.map +1 -0
  188. package/dist/routing/turn-context.d.ts +1 -1
  189. package/dist/routing/turn-context.js +1 -1
  190. package/dist/routing/turn-context.js.map +1 -1
  191. package/dist/routing/types.d.ts +2 -0
  192. package/dist/runtime/answer-contracts.js +36 -8
  193. package/dist/runtime/answer-contracts.js.map +1 -1
  194. package/dist/runtime/artifact-contracts.js.map +1 -1
  195. package/dist/runtime/planning-evidence.js +47 -26
  196. package/dist/runtime/planning-evidence.js.map +1 -1
  197. package/dist/runtime/prompt-step.d.ts +1 -9
  198. package/dist/runtime/prompt-step.js +0 -10
  199. package/dist/runtime/prompt-step.js.map +1 -1
  200. package/dist/runtime/run-context.d.ts +5 -2
  201. package/dist/runtime/run-context.js +8 -1
  202. package/dist/runtime/run-context.js.map +1 -1
  203. package/dist/runtime/session-coordinator.d.ts +13 -5
  204. package/dist/runtime/session-coordinator.js +160 -20
  205. package/dist/runtime/session-coordinator.js.map +1 -1
  206. package/dist/runtime/session-title.d.ts +14 -0
  207. package/dist/runtime/session-title.js +50 -0
  208. package/dist/runtime/session-title.js.map +1 -0
  209. package/dist/runtime/tool-defaults-wrapper.js +1 -3
  210. package/dist/runtime/tool-defaults-wrapper.js.map +1 -1
  211. package/dist/runtime/validation.js.map +1 -1
  212. package/dist/runtime/workflow-events.js.map +1 -1
  213. package/dist/runtime/workflow-runner.d.ts +3 -3
  214. package/dist/runtime/workflow-runner.js +1 -1
  215. package/dist/runtime/workflow-runner.js.map +1 -1
  216. package/dist/sentiment/adapters/finnhub.d.ts +1 -1
  217. package/dist/sentiment/adapters/finnhub.js +6 -1
  218. package/dist/sentiment/adapters/finnhub.js.map +1 -1
  219. package/dist/sentiment/adapters/reddit.d.ts +2 -2
  220. package/dist/sentiment/adapters/twitter.d.ts +1 -1
  221. package/dist/sentiment/adapters/web.d.ts +1 -1
  222. package/dist/sentiment/index.d.ts +9 -11
  223. package/dist/sentiment/index.js +9 -20
  224. package/dist/sentiment/index.js.map +1 -1
  225. package/dist/sentiment/keywords.js +26 -4
  226. package/dist/sentiment/keywords.js.map +1 -1
  227. package/dist/sentiment/pipeline.d.ts +2 -2
  228. package/dist/sentiment/pipeline.js +1 -1
  229. package/dist/sentiment/pipeline.js.map +1 -1
  230. package/dist/sentiment/scorer.js +1 -1
  231. package/dist/sentiment/store.d.ts +1 -1
  232. package/dist/sentiment/store.js +1 -1
  233. package/dist/sentiment/store.js.map +1 -1
  234. package/dist/sentiment/trends.d.ts +1 -1
  235. package/dist/sentiment/trends.js.map +1 -1
  236. package/dist/sentiment/types.js.map +1 -1
  237. package/dist/system-prompt.js +3 -2
  238. package/dist/system-prompt.js.map +1 -1
  239. package/dist/tool-kit.d.ts +7 -7
  240. package/dist/tool-kit.js +4 -4
  241. package/dist/tool-kit.js.map +1 -1
  242. package/dist/tools/fundamentals/company-overview.js +11 -6
  243. package/dist/tools/fundamentals/company-overview.js.map +1 -1
  244. package/dist/tools/fundamentals/comps.js +18 -9
  245. package/dist/tools/fundamentals/comps.js.map +1 -1
  246. package/dist/tools/fundamentals/dcf.js +23 -11
  247. package/dist/tools/fundamentals/dcf.js.map +1 -1
  248. package/dist/tools/fundamentals/earnings.js +8 -3
  249. package/dist/tools/fundamentals/earnings.js.map +1 -1
  250. package/dist/tools/fundamentals/financials.js +8 -3
  251. package/dist/tools/fundamentals/financials.js.map +1 -1
  252. package/dist/tools/fundamentals/sec-filings.js +21 -6
  253. package/dist/tools/fundamentals/sec-filings.js.map +1 -1
  254. package/dist/tools/index.d.ts +23 -19
  255. package/dist/tools/index.js +51 -39
  256. package/dist/tools/index.js.map +1 -1
  257. package/dist/tools/interaction/ask-user.js +15 -3
  258. package/dist/tools/interaction/ask-user.js.map +1 -1
  259. package/dist/tools/interaction/twitter-login.js +13 -3
  260. package/dist/tools/interaction/twitter-login.js.map +1 -1
  261. package/dist/tools/macro/fear-greed.js.map +1 -1
  262. package/dist/tools/macro/fred-data.d.ts +1 -1
  263. package/dist/tools/macro/fred-data.js +17 -6
  264. package/dist/tools/macro/fred-data.js.map +1 -1
  265. package/dist/tools/market/crypto-history.js +3 -1
  266. package/dist/tools/market/crypto-history.js.map +1 -1
  267. package/dist/tools/market/crypto-price.js +3 -1
  268. package/dist/tools/market/crypto-price.js.map +1 -1
  269. package/dist/tools/market/screen-stocks.d.ts +18 -0
  270. package/dist/tools/market/screen-stocks.js +252 -0
  271. package/dist/tools/market/screen-stocks.js.map +1 -0
  272. package/dist/tools/market/search-ticker.js +160 -8
  273. package/dist/tools/market/search-ticker.js.map +1 -1
  274. package/dist/tools/market/stock-history.d.ts +2 -2
  275. package/dist/tools/market/stock-history.js +26 -7
  276. package/dist/tools/market/stock-history.js.map +1 -1
  277. package/dist/tools/market/stock-quote.js +5 -3
  278. package/dist/tools/market/stock-quote.js.map +1 -1
  279. package/dist/tools/options/greeks.js +1 -1
  280. package/dist/tools/options/greeks.js.map +1 -1
  281. package/dist/tools/options/option-chain.js +19 -6
  282. package/dist/tools/options/option-chain.js.map +1 -1
  283. package/dist/tools/portfolio/alerts.d.ts +15 -0
  284. package/dist/tools/portfolio/alerts.js +357 -0
  285. package/dist/tools/portfolio/alerts.js.map +1 -0
  286. package/dist/tools/portfolio/correlation.d.ts +1 -1
  287. package/dist/tools/portfolio/correlation.js +33 -13
  288. package/dist/tools/portfolio/correlation.js.map +1 -1
  289. package/dist/tools/portfolio/daily-report.d.ts +8 -0
  290. package/dist/tools/portfolio/daily-report.js +83 -0
  291. package/dist/tools/portfolio/daily-report.js.map +1 -0
  292. package/dist/tools/portfolio/holdings-overlap.js +10 -3
  293. package/dist/tools/portfolio/holdings-overlap.js.map +1 -1
  294. package/dist/tools/portfolio/notifications.d.ts +7 -0
  295. package/dist/tools/portfolio/notifications.js +43 -0
  296. package/dist/tools/portfolio/notifications.js.map +1 -0
  297. package/dist/tools/portfolio/predictions.d.ts +12 -6
  298. package/dist/tools/portfolio/predictions.js +337 -87
  299. package/dist/tools/portfolio/predictions.js.map +1 -1
  300. package/dist/tools/portfolio/risk-analysis.d.ts +1 -1
  301. package/dist/tools/portfolio/risk-analysis.js +45 -6
  302. package/dist/tools/portfolio/risk-analysis.js.map +1 -1
  303. package/dist/tools/portfolio/tracker.d.ts +4 -3
  304. package/dist/tools/portfolio/tracker.js +246 -101
  305. package/dist/tools/portfolio/tracker.js.map +1 -1
  306. package/dist/tools/portfolio/watchlist.d.ts +6 -4
  307. package/dist/tools/portfolio/watchlist.js +208 -108
  308. package/dist/tools/portfolio/watchlist.js.map +1 -1
  309. package/dist/tools/sentiment/reddit-sentiment.js +23 -10
  310. package/dist/tools/sentiment/reddit-sentiment.js.map +1 -1
  311. package/dist/tools/sentiment/sentiment-summary.js +15 -13
  312. package/dist/tools/sentiment/sentiment-summary.js.map +1 -1
  313. package/dist/tools/sentiment/sentiment-trend.d.ts +1 -1
  314. package/dist/tools/sentiment/sentiment-trend.js +12 -2
  315. package/dist/tools/sentiment/sentiment-trend.js.map +1 -1
  316. package/dist/tools/sentiment/twitter-sentiment.js +12 -5
  317. package/dist/tools/sentiment/twitter-sentiment.js.map +1 -1
  318. package/dist/tools/sentiment/untrusted-text.d.ts +2 -0
  319. package/dist/tools/sentiment/untrusted-text.js +17 -0
  320. package/dist/tools/sentiment/untrusted-text.js.map +1 -0
  321. package/dist/tools/sentiment/web-search.js +9 -13
  322. package/dist/tools/sentiment/web-search.js.map +1 -1
  323. package/dist/tools/sentiment/web-sentiment.js +15 -3
  324. package/dist/tools/sentiment/web-sentiment.js.map +1 -1
  325. package/dist/tools/technical/backtest.d.ts +1 -1
  326. package/dist/tools/technical/backtest.js +27 -20
  327. package/dist/tools/technical/backtest.js.map +1 -1
  328. package/dist/tools/technical/indicators.js +23 -5
  329. package/dist/tools/technical/indicators.js.map +1 -1
  330. package/dist/types/index.d.ts +3 -3
  331. package/dist/types/index.js.map +1 -1
  332. package/dist/types/market.d.ts +1 -0
  333. package/dist/types/portfolio.d.ts +14 -4
  334. package/dist/workflows/compare-assets.d.ts +0 -3
  335. package/dist/workflows/compare-assets.js +20 -11
  336. package/dist/workflows/compare-assets.js.map +1 -1
  337. package/dist/workflows/index.d.ts +3 -4
  338. package/dist/workflows/index.js +3 -3
  339. package/dist/workflows/index.js.map +1 -1
  340. package/dist/workflows/options-screener.d.ts +0 -3
  341. package/dist/workflows/options-screener.js +4 -11
  342. package/dist/workflows/options-screener.js.map +1 -1
  343. package/dist/workflows/portfolio-builder.d.ts +0 -3
  344. package/dist/workflows/portfolio-builder.js +0 -8
  345. package/dist/workflows/portfolio-builder.js.map +1 -1
  346. package/gui/server/ask-user-bridge.ts +1 -1
  347. package/gui/server/automation-heartbeat.ts +97 -0
  348. package/gui/server/background-quotes.ts +97 -1
  349. package/gui/server/chat-event-adapter.ts +32 -10
  350. package/gui/server/chat-run-session.ts +16 -0
  351. package/gui/server/invoke-tool.ts +144 -1
  352. package/gui/server/live-chat-event-adapter.ts +21 -6
  353. package/gui/server/market-state-api.ts +315 -0
  354. package/gui/server/model-setup.ts +149 -2
  355. package/gui/server/private-api-access.ts +62 -0
  356. package/gui/server/projector.ts +12 -7
  357. package/gui/server/prompt-observation.ts +4 -7
  358. package/gui/server/quote-snapshot-store.ts +50 -0
  359. package/gui/server/server.ts +200 -451
  360. package/gui/server/session-actions.ts +186 -1
  361. package/gui/server/shutdown.ts +47 -0
  362. package/gui/server/tool-invoke-ack.ts +49 -0
  363. package/gui/server/tool-metadata.ts +23 -10
  364. package/gui/server/websocket.ts +13 -3
  365. package/gui/server/writer-lock.ts +6 -2
  366. package/gui/server/ws-hub.ts +292 -0
  367. package/gui/shared/chat-events.ts +16 -1
  368. package/gui/shared/event-reducer.ts +24 -6
  369. package/gui/web/dist/assets/CatalogOverlay-eJ2cBk33.js +1 -0
  370. package/gui/web/dist/assets/index-2KZtKBmu.css +1 -0
  371. package/gui/web/dist/assets/index-CveNgtDg.js +69 -0
  372. package/gui/web/dist/index.html +2 -2
  373. package/package.json +5 -1
  374. package/src/analysts/contracts.ts +10 -23
  375. package/src/analysts/orchestrator.ts +8 -43
  376. package/src/cli.ts +35 -12
  377. package/src/config.ts +17 -9
  378. package/src/index.ts +1 -1
  379. package/src/infra/browser.ts +3 -1
  380. package/src/infra/cache.ts +41 -30
  381. package/src/infra/http-client.ts +72 -6
  382. package/src/infra/index.ts +7 -10
  383. package/src/infra/native-dependencies.ts +8 -3
  384. package/src/infra/node-version.ts +3 -1
  385. package/src/infra/opencandle-paths.ts +3 -14
  386. package/src/infra/rate-limiter.ts +22 -19
  387. package/src/market-state/alert-conditions.ts +82 -0
  388. package/src/market-state/alert-runner.ts +863 -0
  389. package/src/market-state/daily-report.ts +247 -0
  390. package/src/market-state/local-automation-service.ts +162 -0
  391. package/src/market-state/notification-delivery.ts +158 -0
  392. package/src/market-state/resolve-for-mutation.ts +24 -0
  393. package/src/market-state/resolve.ts +112 -0
  394. package/src/market-state/service.ts +2344 -0
  395. package/src/memory/index.ts +7 -7
  396. package/src/memory/manager.ts +14 -16
  397. package/src/memory/retrieval.ts +8 -7
  398. package/src/memory/sqlite.ts +407 -6
  399. package/src/memory/storage.ts +5 -15
  400. package/src/memory/tool-defaults.ts +60 -39
  401. package/src/memory/types.ts +3 -3
  402. package/src/monitor.ts +121 -0
  403. package/src/onboarding/connect.ts +10 -33
  404. package/src/onboarding/credential-interceptor.ts +3 -15
  405. package/src/onboarding/degradation-accumulator.ts +1 -3
  406. package/src/onboarding/providers.ts +9 -40
  407. package/src/onboarding/state.ts +4 -15
  408. package/src/onboarding/tool-helpers.ts +2 -9
  409. package/src/onboarding/tool-tags.ts +6 -6
  410. package/src/onboarding/validation.ts +14 -20
  411. package/src/pi/opencandle-extension.ts +529 -85
  412. package/src/pi/session.ts +7 -5
  413. package/src/pi/setup.ts +61 -43
  414. package/src/pi/tool-adapter.ts +5 -2
  415. package/src/prompts/context-builder.ts +23 -12
  416. package/src/prompts/policy-cards.ts +2 -2
  417. package/src/prompts/sections.ts +1 -1
  418. package/src/prompts/symbol-preflight.ts +80 -0
  419. package/src/prompts/workflow-prompts.ts +77 -28
  420. package/src/providers/alpha-vantage.ts +58 -39
  421. package/src/providers/coingecko.ts +2 -5
  422. package/src/providers/errors.ts +9 -0
  423. package/src/providers/exa-search.ts +24 -22
  424. package/src/providers/fear-greed.ts +1 -1
  425. package/src/providers/finnhub.ts +7 -6
  426. package/src/providers/fred.ts +3 -3
  427. package/src/providers/index.ts +14 -6
  428. package/src/providers/reddit.ts +17 -6
  429. package/src/providers/sec-edgar.ts +20 -6
  430. package/src/providers/tradingview.ts +399 -0
  431. package/src/providers/twitter.ts +6 -8
  432. package/src/providers/web-search.ts +30 -20
  433. package/src/providers/with-fallback.ts +8 -7
  434. package/src/providers/wrap-provider.ts +15 -10
  435. package/src/providers/yahoo-finance.ts +140 -35
  436. package/src/routing/classify-intent.ts +101 -10
  437. package/src/routing/defaults.ts +1 -1
  438. package/src/routing/entity-extractor.ts +287 -38
  439. package/src/routing/fund-symbols.ts +58 -0
  440. package/src/routing/horizon.ts +7 -0
  441. package/src/routing/index.ts +48 -48
  442. package/src/routing/planning.ts +144 -53
  443. package/src/routing/route-manifest.ts +37 -15
  444. package/src/routing/router-llm-client.ts +4 -4
  445. package/src/routing/router-prompt.ts +15 -19
  446. package/src/routing/router-types.ts +2 -5
  447. package/src/routing/router.ts +251 -53
  448. package/src/routing/slot-resolver.ts +34 -11
  449. package/src/routing/symbol-disambiguator.ts +72 -0
  450. package/src/routing/turn-context.ts +6 -9
  451. package/src/routing/types.ts +2 -0
  452. package/src/runtime/answer-contracts.ts +82 -43
  453. package/src/runtime/artifact-contracts.ts +2 -1
  454. package/src/runtime/planning-evidence.ts +157 -66
  455. package/src/runtime/prompt-step.ts +1 -16
  456. package/src/runtime/run-context.ts +12 -2
  457. package/src/runtime/session-coordinator.ts +238 -63
  458. package/src/runtime/session-title.ts +60 -0
  459. package/src/runtime/tool-defaults-wrapper.ts +1 -3
  460. package/src/runtime/validation.ts +1 -4
  461. package/src/runtime/workflow-events.ts +7 -7
  462. package/src/runtime/workflow-runner.ts +5 -11
  463. package/src/sentiment/adapters/finnhub.ts +7 -2
  464. package/src/sentiment/adapters/reddit.ts +2 -2
  465. package/src/sentiment/adapters/twitter.ts +1 -1
  466. package/src/sentiment/adapters/web.ts +1 -1
  467. package/src/sentiment/index.ts +16 -26
  468. package/src/sentiment/keywords.ts +26 -4
  469. package/src/sentiment/pipeline.ts +15 -4
  470. package/src/sentiment/scorer.ts +1 -1
  471. package/src/sentiment/store.ts +2 -2
  472. package/src/sentiment/trends.ts +9 -3
  473. package/src/sentiment/types.ts +5 -4
  474. package/src/system-prompt.ts +3 -2
  475. package/src/tool-kit.ts +10 -9
  476. package/src/tools/fundamentals/company-overview.ts +19 -9
  477. package/src/tools/fundamentals/comps.ts +68 -55
  478. package/src/tools/fundamentals/dcf.ts +145 -95
  479. package/src/tools/fundamentals/earnings.ts +16 -6
  480. package/src/tools/fundamentals/financials.ts +16 -7
  481. package/src/tools/fundamentals/sec-filings.ts +37 -16
  482. package/src/tools/index.ts +51 -39
  483. package/src/tools/interaction/ask-user.ts +22 -10
  484. package/src/tools/interaction/twitter-login.ts +17 -5
  485. package/src/tools/macro/fear-greed.ts +1 -1
  486. package/src/tools/macro/fred-data.ts +58 -46
  487. package/src/tools/market/crypto-history.ts +8 -3
  488. package/src/tools/market/crypto-price.ts +6 -6
  489. package/src/tools/market/screen-stocks.ts +279 -0
  490. package/src/tools/market/search-ticker.ts +218 -17
  491. package/src/tools/market/stock-history.ts +37 -12
  492. package/src/tools/market/stock-quote.ts +10 -7
  493. package/src/tools/options/greeks.ts +5 -5
  494. package/src/tools/options/option-chain.ts +41 -17
  495. package/src/tools/portfolio/alerts.ts +457 -0
  496. package/src/tools/portfolio/correlation.ts +47 -20
  497. package/src/tools/portfolio/daily-report.ts +101 -0
  498. package/src/tools/portfolio/holdings-overlap.ts +31 -15
  499. package/src/tools/portfolio/notifications.ts +45 -0
  500. package/src/tools/portfolio/predictions.ts +406 -106
  501. package/src/tools/portfolio/risk-analysis.ts +46 -7
  502. package/src/tools/portfolio/tracker.ts +270 -109
  503. package/src/tools/portfolio/watchlist.ts +250 -121
  504. package/src/tools/sentiment/reddit-sentiment.ts +50 -24
  505. package/src/tools/sentiment/sentiment-summary.ts +62 -41
  506. package/src/tools/sentiment/sentiment-trend.ts +24 -7
  507. package/src/tools/sentiment/twitter-sentiment.ts +22 -15
  508. package/src/tools/sentiment/untrusted-text.ts +21 -0
  509. package/src/tools/sentiment/web-search.ts +21 -18
  510. package/src/tools/sentiment/web-sentiment.ts +26 -10
  511. package/src/tools/technical/backtest.ts +32 -22
  512. package/src/tools/technical/indicators.ts +39 -14
  513. package/src/types/index.ts +8 -3
  514. package/src/types/market.ts +1 -0
  515. package/src/types/portfolio.ts +14 -4
  516. package/src/types/sentiment.ts +2 -2
  517. package/src/workflows/compare-assets.ts +33 -21
  518. package/src/workflows/index.ts +3 -4
  519. package/src/workflows/options-screener.ts +27 -29
  520. package/src/workflows/portfolio-builder.ts +34 -27
  521. package/dist/workflows/types.d.ts +0 -4
  522. package/dist/workflows/types.js +0 -2
  523. package/dist/workflows/types.js.map +0 -1
  524. package/gui/web/dist/assets/CatalogOverlay-Bmp6Knu7.js +0 -1
  525. package/gui/web/dist/assets/index-Bxt9QpLX.css +0 -1
  526. package/gui/web/dist/assets/index-CZ9DHZYy.js +0 -67
  527. package/src/workflows/types.ts +0 -4
@@ -1,22 +1,19 @@
1
1
  import type { MemoryCategory, MemoryEntry } from "../memory/types.js";
2
2
  import {
3
- activeToolsForBundles,
4
- memoryScopesForRoute,
5
- } from "./route-manifest.js";
3
+ buildPlanningEnvelope,
4
+ type PlanningBuildOptions,
5
+ type PlanningEnvelope,
6
+ } from "./planning.js";
7
+ import { activeToolsForBundles, memoryScopesForRoute } from "./route-manifest.js";
6
8
  import type {
9
+ RouterDiagnostic,
7
10
  RouterInputContext,
8
11
  RouterOutput,
9
12
  RouterRoute,
10
13
  RouterRouteKind,
11
14
  RouterSlot,
12
15
  ToolBundleName,
13
- RouterDiagnostic,
14
16
  } from "./router-types.js";
15
- import {
16
- buildPlanningEnvelope,
17
- type PlanningBuildOptions,
18
- type PlanningEnvelope,
19
- } from "./planning.js";
20
17
  import type { ExtractedEntities, WorkflowType } from "./types.js";
21
18
 
22
19
  export interface MemoryQueryPlan {
@@ -63,6 +63,8 @@ export interface CompareAssetsSlots {
63
63
  symbols: string[];
64
64
  timeHorizon?: string;
65
65
  metrics?: string[];
66
+ budget?: number;
67
+ assetScope?: string;
66
68
  }
67
69
 
68
70
  export type SlotSource = "user" | "preference" | "default" | "prior_context" | "memory";
@@ -160,7 +160,12 @@ export const ANSWER_CONTRACT_REGISTRY: Record<AnswerContractId, AnswerContractDe
160
160
  commitmentMode: "decision",
161
161
  implemented: true,
162
162
  requiredEvidenceTypes: [],
163
- requiredFinalFields: ["clear_commitment", "risk_downside", "freshness_disclosure", "data_gap_disclosure"],
163
+ requiredFinalFields: [
164
+ "clear_commitment",
165
+ "risk_downside",
166
+ "freshness_disclosure",
167
+ "data_gap_disclosure",
168
+ ],
164
169
  requiresFreshness: true,
165
170
  requiresDataGapDisclosure: true,
166
171
  requiresRiskDownside: true,
@@ -175,7 +180,12 @@ export const ANSWER_CONTRACT_REGISTRY: Record<AnswerContractId, AnswerContractDe
175
180
  commitmentMode: "compare_tradeoffs",
176
181
  implemented: true,
177
182
  requiredEvidenceTypes: [],
178
- requiredFinalFields: ["comparison_tradeoffs", "risk_downside", "data_gap_disclosure", "source_coverage"],
183
+ requiredFinalFields: [
184
+ "comparison_tradeoffs",
185
+ "risk_downside",
186
+ "data_gap_disclosure",
187
+ "source_coverage",
188
+ ],
179
189
  requiresFreshness: false,
180
190
  requiresDataGapDisclosure: true,
181
191
  requiresRiskDownside: true,
@@ -184,7 +194,9 @@ export const ANSWER_CONTRACT_REGISTRY: Record<AnswerContractId, AnswerContractDe
184
194
  capabilityGapIds: ["etf_holdings_overlap"],
185
195
  frameworkFallback: "not_allowed",
186
196
  },
187
- portfolio_build: placeholderContract("portfolio_build", "portfolio_build", "construct", ["constructed_output"]),
197
+ portfolio_build: placeholderContract("portfolio_build", "portfolio_build", "construct", [
198
+ "constructed_output",
199
+ ]),
188
200
  portfolio_review: {
189
201
  id: "portfolio_review",
190
202
  taskFamily: "portfolio_review",
@@ -255,7 +267,12 @@ export const ANSWER_CONTRACT_REGISTRY: Record<AnswerContractId, AnswerContractDe
255
267
  commitmentMode: "framework",
256
268
  implemented: true,
257
269
  requiredEvidenceTypes: [],
258
- requiredFinalFields: ["framework_or_checklist", "risk_downside", "data_gap_disclosure", "source_coverage"],
270
+ requiredFinalFields: [
271
+ "framework_or_checklist",
272
+ "risk_downside",
273
+ "data_gap_disclosure",
274
+ "source_coverage",
275
+ ],
259
276
  requiresFreshness: false,
260
277
  requiresDataGapDisclosure: true,
261
278
  requiresRiskDownside: true,
@@ -285,7 +302,12 @@ export const ANSWER_CONTRACT_REGISTRY: Record<AnswerContractId, AnswerContractDe
285
302
  commitmentMode: "framework",
286
303
  implemented: true,
287
304
  requiredEvidenceTypes: ["market_status"],
288
- requiredFinalFields: ["framework_or_checklist", "freshness_disclosure", "source_coverage", "data_gap_disclosure"],
305
+ requiredFinalFields: [
306
+ "framework_or_checklist",
307
+ "freshness_disclosure",
308
+ "source_coverage",
309
+ "data_gap_disclosure",
310
+ ],
289
311
  requiresFreshness: true,
290
312
  requiresDataGapDisclosure: true,
291
313
  requiresRiskDownside: false,
@@ -374,7 +396,9 @@ export const ANSWER_CONTRACT_REGISTRY: Record<AnswerContractId, AnswerContractDe
374
396
  capabilityGapIds: [],
375
397
  frameworkFallback: "not_allowed",
376
398
  },
377
- general_fallback: placeholderContract("general_fallback", "general_fallback", "framework", ["data_gap_disclosure"]),
399
+ general_fallback: placeholderContract("general_fallback", "general_fallback", "framework", [
400
+ "data_gap_disclosure",
401
+ ]),
378
402
  };
379
403
 
380
404
  export function runStructuredChecks(input: StructuredCheckInput): StructuredCheckTrace {
@@ -389,7 +413,9 @@ export function runStructuredChecks(input: StructuredCheckInput): StructuredChec
389
413
  ...semanticChecks(requestedChecks, input.answerText),
390
414
  ];
391
415
  const failures = results.filter((result) => !result.passed);
392
- const retryReasons = failures.map((failure) => `${failure.checkId}: ${failure.failureReason ?? "failed"}`);
416
+ const retryReasons = failures.map(
417
+ (failure) => `${failure.checkId}: ${failure.failureReason ?? "failed"}`,
418
+ );
393
419
 
394
420
  return {
395
421
  mode: "observe_only",
@@ -411,36 +437,44 @@ function semanticChecks(
411
437
  ): StructuredCheckResult[] {
412
438
  const checks: StructuredCheckResult[] = [];
413
439
  if (requestedChecks.has("assumption_disclosed")) {
414
- checks.push(checkAnswerText(
415
- "assumption_disclosed",
416
- answerText,
417
- /\b(?:assuming|assumption|assuming that|if your|based on your stated|given your stated)\b/i,
418
- "Explicit assumption disclosure is missing.",
419
- ));
440
+ checks.push(
441
+ checkAnswerText(
442
+ "assumption_disclosed",
443
+ answerText,
444
+ /\b(?:assuming|assumption|assuming that|if your|based on your stated|given your stated)\b/i,
445
+ "Explicit assumption disclosure is missing.",
446
+ ),
447
+ );
420
448
  }
421
449
  if (requestedChecks.has("tax_caveat_present")) {
422
- checks.push(checkAnswerText(
423
- "tax_caveat_present",
424
- answerText,
425
- /\b(?:tax|taxable|after[-\s]?tax|capital gains?|ordinary income|qualified dividend|tax advisor|jurisdiction|account type)\b/i,
426
- "Tax/account caveat is missing.",
427
- ));
450
+ checks.push(
451
+ checkAnswerText(
452
+ "tax_caveat_present",
453
+ answerText,
454
+ /\b(?:tax|taxable|after[-\s]?tax|capital gains?|ordinary income|qualified dividend|tax advisor|jurisdiction|account type)\b/i,
455
+ "Tax/account caveat is missing.",
456
+ ),
457
+ );
428
458
  }
429
459
  if (requestedChecks.has("target_bands_present")) {
430
- checks.push(checkAnswerText(
431
- "target_bands_present",
432
- answerText,
433
- /\b(?:target bands?|bands?|range|threshold|drift|5\s*%|percentage points?)\b/i,
434
- "Target band, range, or rebalance threshold guidance is missing.",
435
- ));
460
+ checks.push(
461
+ checkAnswerText(
462
+ "target_bands_present",
463
+ answerText,
464
+ /\b(?:target bands?|bands?|range|threshold|drift|5\s*%|percentage points?)\b/i,
465
+ "Target band, range, or rebalance threshold guidance is missing.",
466
+ ),
467
+ );
436
468
  }
437
469
  if (requestedChecks.has("when_not_ideal_present")) {
438
- checks.push(checkAnswerText(
439
- "when_not_ideal_present",
440
- answerText,
441
- /\b(?:not ideal|avoid|bad fit|poor fit|when this fails|where it fails|doesn'?t work|not suitable|watch out)\b/i,
442
- "When-not-ideal or unsuitability guidance is missing.",
443
- ));
470
+ checks.push(
471
+ checkAnswerText(
472
+ "when_not_ideal_present",
473
+ answerText,
474
+ /\b(?:not ideal|avoid|bad fit|poor fit|when this fails|where it fails|doesn'?t work|not suitable|watch out)\b/i,
475
+ "When-not-ideal or unsuitability guidance is missing.",
476
+ ),
477
+ );
444
478
  }
445
479
  return checks;
446
480
  }
@@ -452,11 +486,7 @@ function checkAnswerText(
452
486
  failureReason: string,
453
487
  ): StructuredCheckResult {
454
488
  const passed = typeof answerText === "string" && pattern.test(answerText);
455
- return structuredResult(
456
- checkId,
457
- passed,
458
- passed ? undefined : failureReason,
459
- );
489
+ return structuredResult(checkId, passed, passed ? undefined : failureReason);
460
490
  }
461
491
 
462
492
  export function evaluateFrameworkFallbackEligibility(
@@ -471,9 +501,12 @@ export function evaluateFrameworkFallbackEligibility(
471
501
  };
472
502
  }
473
503
 
474
- const hasUnresolvedSymbol = input.evidenceRecords.some((record) =>
475
- record.evidenceType === "ticker_disambiguation" &&
476
- (record.caveats.length > 0 || record.entityScope.symbols === undefined || record.entityScope.symbols.length === 0),
504
+ const hasUnresolvedSymbol = input.evidenceRecords.some(
505
+ (record) =>
506
+ record.evidenceType === "ticker_disambiguation" &&
507
+ (record.caveats.length > 0 ||
508
+ record.entityScope.symbols === undefined ||
509
+ record.entityScope.symbols.length === 0),
477
510
  );
478
511
  if (!hasUnresolvedSymbol) {
479
512
  return {
@@ -513,7 +546,8 @@ function placeholderContract(
513
546
  requiresDataGapDisclosure: requiredFinalFields.includes("data_gap_disclosure"),
514
547
  requiresRiskDownside: requiredFinalFields.includes("risk_downside"),
515
548
  requiresSourceCoverage: requiredFinalFields.includes("source_coverage"),
516
- requiresConcreteCommitment: COMMITMENT_MODE_CONTRACTS[commitmentMode].requiresConcreteCommitment,
549
+ requiresConcreteCommitment:
550
+ COMMITMENT_MODE_CONTRACTS[commitmentMode].requiresConcreteCommitment,
517
551
  capabilityGapIds: [],
518
552
  frameworkFallback: "not_allowed",
519
553
  };
@@ -537,7 +571,8 @@ function checkFreshness(
537
571
  metadata: FinalAnswerMetadata,
538
572
  ): StructuredCheckResult {
539
573
  if (!contract.requiresFreshness) return structuredResult("freshness_disclosed", true);
540
- const present = metadata.finalFields.includes("freshness_disclosure") && metadata.freshness !== undefined;
574
+ const present =
575
+ metadata.finalFields.includes("freshness_disclosure") && metadata.freshness !== undefined;
541
576
  return structuredResult(
542
577
  "freshness_disclosed",
543
578
  present,
@@ -569,7 +604,9 @@ function checkCommitmentMode(
569
604
  ): StructuredCheckResult {
570
605
  const modeContract = COMMITMENT_MODE_CONTRACTS[contract.commitmentMode];
571
606
  const fields = new Set(metadata.finalFields);
572
- const requiredFieldsPresent = modeContract.requiredFinalFields.every((field) => fields.has(field));
607
+ const requiredFieldsPresent = modeContract.requiredFinalFields.every((field) =>
608
+ fields.has(field),
609
+ );
573
610
  const passed =
574
611
  metadata.commitmentMode === contract.commitmentMode &&
575
612
  requiredFieldsPresent &&
@@ -577,7 +614,9 @@ function checkCommitmentMode(
577
614
  return structuredResult(
578
615
  "commitment_mode_respected",
579
616
  passed,
580
- passed ? undefined : `Expected ${contract.commitmentMode} metadata and fields: ${modeContract.requiredFinalFields.join(", ")}`,
617
+ passed
618
+ ? undefined
619
+ : `Expected ${contract.commitmentMode} metadata and fields: ${modeContract.requiredFinalFields.join(", ")}`,
581
620
  );
582
621
  }
583
622
 
@@ -69,7 +69,8 @@ export function validateArtifactContractRegistry(): string[] {
69
69
  for (const [id, contract] of Object.entries(ARTIFACT_CONTRACT_REGISTRY)) {
70
70
  if (contract.id !== id) errors.push(`${id} key must match contract id`);
71
71
  if (contract.status !== "trace_only") errors.push(`${id} must remain trace-only in V1`);
72
- if (contract.taskFamilies.length === 0) errors.push(`${id} must declare at least one task family`);
72
+ if (contract.taskFamilies.length === 0)
73
+ errors.push(`${id} must declare at least one task family`);
73
74
  if (!contract.description.trim()) errors.push(`${id} must include a description`);
74
75
  }
75
76
  return errors;
@@ -1,5 +1,5 @@
1
- import { parseToolTag } from "../onboarding/tool-tags.js";
2
1
  import type { ParsedTag } from "../onboarding/tool-tags.js";
2
+ import { parseToolTag } from "../onboarding/tool-tags.js";
3
3
  import type { CapabilityGapId, EvidencePlanId, TaskFamily } from "../routing/planning.js";
4
4
  import type { ProviderResult } from "./evidence.js";
5
5
 
@@ -135,23 +135,71 @@ export const EVIDENCE_PLAN_REGISTRY: Record<EvidencePlanId, EvidencePlanDefiniti
135
135
  optionalEvidence: ["tool_result"],
136
136
  capabilityGapIds: ["earnings_event_risk"],
137
137
  },
138
- placeholder_single_asset_decision: placeholderPlan("placeholder_single_asset_decision", ["single_asset_decision"], []),
139
- placeholder_asset_compare: placeholderPlan("placeholder_asset_compare", ["asset_compare"], ["etf_holdings_overlap"]),
140
- placeholder_portfolio_build: placeholderPlan("placeholder_portfolio_build", ["portfolio_build"], []),
141
- placeholder_portfolio_review: placeholderPlan("placeholder_portfolio_review", ["portfolio_review"], []),
142
- placeholder_options_strategy: placeholderPlan("placeholder_options_strategy", ["options_strategy"], []),
143
- placeholder_current_event_explanation: placeholderPlan("placeholder_current_event_explanation", ["current_event_explanation"], ["market_calendar"]),
144
- placeholder_sentiment_snapshot: placeholderPlan("placeholder_sentiment_snapshot", ["sentiment_snapshot"], ["sentiment_sample_depth"]),
145
- placeholder_filing_thesis_review: placeholderPlan("placeholder_filing_thesis_review", ["filing_thesis_review"], []),
146
- placeholder_retail_finance_tradeoff: placeholderPlan("placeholder_retail_finance_tradeoff", ["retail_finance_tradeoff"], [
147
- "brokerage_comparison",
148
- "cash_yield_products",
149
- "fund_tax_efficiency",
150
- ]),
151
- placeholder_concept_explainer: placeholderPlan("placeholder_concept_explainer", ["concept_explainer"], []),
152
- placeholder_backtest_review: placeholderPlan("placeholder_backtest_review", ["backtest_review"], []),
153
- placeholder_stateful_tracking_update: placeholderPlan("placeholder_stateful_tracking_update", ["stateful_tracking_update"], []),
154
- placeholder_general_fallback: placeholderPlan("placeholder_general_fallback", ["general_fallback"], []),
138
+ placeholder_single_asset_decision: placeholderPlan(
139
+ "placeholder_single_asset_decision",
140
+ ["single_asset_decision"],
141
+ [],
142
+ ),
143
+ placeholder_asset_compare: placeholderPlan(
144
+ "placeholder_asset_compare",
145
+ ["asset_compare"],
146
+ ["etf_holdings_overlap"],
147
+ ),
148
+ placeholder_portfolio_build: placeholderPlan(
149
+ "placeholder_portfolio_build",
150
+ ["portfolio_build"],
151
+ [],
152
+ ),
153
+ placeholder_portfolio_review: placeholderPlan(
154
+ "placeholder_portfolio_review",
155
+ ["portfolio_review"],
156
+ [],
157
+ ),
158
+ placeholder_options_strategy: placeholderPlan(
159
+ "placeholder_options_strategy",
160
+ ["options_strategy"],
161
+ [],
162
+ ),
163
+ placeholder_current_event_explanation: placeholderPlan(
164
+ "placeholder_current_event_explanation",
165
+ ["current_event_explanation"],
166
+ ["market_calendar"],
167
+ ),
168
+ placeholder_sentiment_snapshot: placeholderPlan(
169
+ "placeholder_sentiment_snapshot",
170
+ ["sentiment_snapshot"],
171
+ ["sentiment_sample_depth"],
172
+ ),
173
+ placeholder_filing_thesis_review: placeholderPlan(
174
+ "placeholder_filing_thesis_review",
175
+ ["filing_thesis_review"],
176
+ [],
177
+ ),
178
+ placeholder_retail_finance_tradeoff: placeholderPlan(
179
+ "placeholder_retail_finance_tradeoff",
180
+ ["retail_finance_tradeoff"],
181
+ ["brokerage_comparison", "cash_yield_products", "fund_tax_efficiency"],
182
+ ),
183
+ placeholder_concept_explainer: placeholderPlan(
184
+ "placeholder_concept_explainer",
185
+ ["concept_explainer"],
186
+ [],
187
+ ),
188
+ placeholder_backtest_review: placeholderPlan(
189
+ "placeholder_backtest_review",
190
+ ["backtest_review"],
191
+ [],
192
+ ),
193
+ placeholder_stateful_tracking_update: placeholderPlan(
194
+ "placeholder_stateful_tracking_update",
195
+ ["stateful_tracking_update"],
196
+ [],
197
+ ),
198
+ placeholder_general_fallback: placeholderPlan(
199
+ "placeholder_general_fallback",
200
+ ["general_fallback"],
201
+ [],
202
+ ),
155
203
  };
156
204
 
157
205
  const KNOWN_US_MARKET_HOLIDAYS: Record<string, string> = {
@@ -193,11 +241,14 @@ export function buildMarketStatusEvidence(input: MarketStatusInput): PlanningEvi
193
241
  const isMarketHoliday = holidayName !== undefined;
194
242
  const marketStatus = classifyMarketStatus(local, isWeekend, isMarketHoliday, temporalReferences);
195
243
  const lastTradingDate = marketStatus === "open" ? local.date : lastTradingDay(local.date);
196
- const gaps: EvidenceGap[] = [{
197
- kind: "capability_gap",
198
- capabilityGapId: "market_calendar",
199
- reason: "V1 uses deterministic weekday and known-holiday grounding, not a live exchange-calendar provider.",
200
- }];
244
+ const gaps: EvidenceGap[] = [
245
+ {
246
+ kind: "capability_gap",
247
+ capabilityGapId: "market_calendar",
248
+ reason:
249
+ "V1 uses deterministic weekday and known-holiday grounding, not a live exchange-calendar provider.",
250
+ },
251
+ ];
201
252
 
202
253
  return {
203
254
  id: "market_status:deterministic",
@@ -219,20 +270,27 @@ export function buildMarketStatusEvidence(input: MarketStatusInput): PlanningEvi
219
270
  lastTradingDay: lastTradingDate,
220
271
  quoteAsOfCaveat: quoteAsOfCaveat(marketStatus),
221
272
  },
222
- rawTracePointer: input.traceId ? { traceId: input.traceId, toolName: "deterministic_market_status" } : undefined,
273
+ rawTracePointer: input.traceId
274
+ ? { traceId: input.traceId, toolName: "deterministic_market_status" }
275
+ : undefined,
223
276
  gaps,
224
- caveats: ["Market status is deterministic V1 grounding and should be verified against an exchange calendar for edge cases."],
277
+ caveats: [
278
+ "Market status is deterministic V1 grounding and should be verified against an exchange calendar for edge cases.",
279
+ ],
225
280
  };
226
281
  }
227
282
 
228
283
  export function buildTickerDisambiguationEvidence(
229
284
  input: TickerDisambiguationInput,
230
285
  ): PlanningEvidenceRecord {
231
- const gaps: EvidenceGap[] = [{
232
- kind: "capability_gap",
233
- capabilityGapId: "earnings_event_risk",
234
- reason: "Ticker disambiguation can preserve symbol-verification gaps, but V1 does not add richer earnings-event data.",
235
- }];
286
+ const gaps: EvidenceGap[] = [
287
+ {
288
+ kind: "capability_gap",
289
+ capabilityGapId: "earnings_event_risk",
290
+ reason:
291
+ "Ticker disambiguation can preserve symbol-verification gaps, but V1 does not add richer earnings-event data.",
292
+ },
293
+ ];
236
294
 
237
295
  return {
238
296
  id: "ticker_disambiguation:selected_slice",
@@ -247,9 +305,15 @@ export function buildTickerDisambiguationEvidence(
247
305
  requiresSymbolVerification: true,
248
306
  legacyBehaviorRemainsActive: true,
249
307
  },
250
- rawTracePointer: input.traceId ? { traceId: input.traceId, toolName: "planning_ticker_disambiguation" } : undefined,
308
+ rawTracePointer: input.traceId
309
+ ? { traceId: input.traceId, toolName: "planning_ticker_disambiguation" }
310
+ : undefined,
251
311
  gaps,
252
- caveats: input.symbols?.length ? [] : ["No symbol was verified by this evidence plan; active tools remain responsible for lookup."],
312
+ caveats: input.symbols?.length
313
+ ? []
314
+ : [
315
+ "No symbol was verified by this evidence plan; active tools remain responsible for lookup.",
316
+ ],
253
317
  };
254
318
  }
255
319
 
@@ -258,7 +322,8 @@ export function buildPortfolioExposureMapEvidence(
258
322
  ): PlanningEvidenceRecord {
259
323
  const sleeves = extractPortfolioSleeves(input.text);
260
324
  const normalizedSleeves = new Set(sleeves.map((sleeve) => sleeve.normalizedSleeve));
261
- const hasBroadIndex = normalizedSleeves.has("broad_us_index") || normalizedSleeves.has("broad_equity");
325
+ const hasBroadIndex =
326
+ normalizedSleeves.has("broad_us_index") || normalizedSleeves.has("broad_equity");
262
327
  const hasSectorSleeve = sleeves.some((sleeve) => sleeve.normalizedSleeve.endsWith("_sector"));
263
328
  const broadIndexOverlapCaveat = hasBroadIndex && hasSectorSleeve;
264
329
 
@@ -271,24 +336,36 @@ export function buildPortfolioExposureMapEvidence(
271
336
  providerStatus: "available",
272
337
  normalizedFacts: {
273
338
  directSleeves: sleeves,
274
- directExposureTotalPercent: roundPercent(sleeves.reduce((sum, sleeve) => sum + sleeve.percent, 0)),
339
+ directExposureTotalPercent: roundPercent(
340
+ sleeves.reduce((sum, sleeve) => sum + sleeve.percent, 0),
341
+ ),
275
342
  broadIndexOverlapCaveat,
276
343
  exactHoldingsOverlapAvailable: false,
277
- targetBandGuidanceNeeded: /\b(?:rebalance|target\s+bands?|drift|overweight|underweight|concentration|diversif)/i.test(input.text),
344
+ targetBandGuidanceNeeded:
345
+ /\b(?:rebalance|target\s+bands?|drift|overweight|underweight|concentration|diversif)/i.test(
346
+ input.text,
347
+ ),
278
348
  },
279
- rawTracePointer: input.traceId ? {
280
- traceId: input.traceId,
281
- toolName: "deterministic_portfolio_exposure_map",
282
- } : undefined,
283
- gaps: [{
284
- kind: "capability_gap",
285
- capabilityGapId: "etf_holdings_overlap",
286
- reason: "V1 records user-stated sleeves and overlap caveats but does not fetch exact ETF/index holdings or issuer weights.",
287
- }],
349
+ rawTracePointer: input.traceId
350
+ ? {
351
+ traceId: input.traceId,
352
+ toolName: "deterministic_portfolio_exposure_map",
353
+ }
354
+ : undefined,
355
+ gaps: [
356
+ {
357
+ kind: "capability_gap",
358
+ capabilityGapId: "etf_holdings_overlap",
359
+ reason:
360
+ "V1 records user-stated sleeves and overlap caveats but does not fetch exact ETF/index holdings or issuer weights.",
361
+ },
362
+ ],
288
363
  caveats: [
289
364
  "Exact ETF/index holdings overlap requires a provider-backed holdings source.",
290
365
  ...(broadIndexOverlapCaveat
291
- ? ["Broad index exposure may already include sector exposure; V1 does not estimate exact constituent weights."]
366
+ ? [
367
+ "Broad index exposure may already include sector exposure; V1 does not estimate exact constituent weights.",
368
+ ]
292
369
  : []),
293
370
  ],
294
371
  };
@@ -300,7 +377,8 @@ export function captureEvidenceFromToolCall(
300
377
  ): PlanningEvidenceRecord {
301
378
  const text = toolResultText(toolCall.result);
302
379
  const providerGap = text ? normalizeProviderGapFromToolText(text) : undefined;
303
- const providerStatus = providerGap?.providerStatus ?? (toolCall.isError ? "unavailable" : "available");
380
+ const providerStatus =
381
+ providerGap?.providerStatus ?? (toolCall.isError ? "unavailable" : "available");
304
382
  const gaps = providerGap ? [providerGapToEvidenceGap(providerGap)] : [];
305
383
  if (toolCall.isError && !providerGap) {
306
384
  gaps.push({
@@ -378,12 +456,14 @@ export function providerResultToPlanningEvidence<T>(
378
456
  providerStatus: "unavailable",
379
457
  normalizedFacts: { label },
380
458
  rawTracePointer,
381
- gaps: [{
382
- kind: "provider_status",
383
- providerStatus: "unavailable",
384
- provider: result.provider,
385
- reason: result.reason,
386
- }],
459
+ gaps: [
460
+ {
461
+ kind: "provider_status",
462
+ providerStatus: "unavailable",
463
+ provider: result.provider,
464
+ reason: result.reason,
465
+ },
466
+ ],
387
467
  caveats: [],
388
468
  };
389
469
  }
@@ -400,7 +480,9 @@ function providerGapToEvidenceGap(gap: NormalizedProviderGap): EvidenceGap {
400
480
  };
401
481
  }
402
482
 
403
- function providerStatusFromTag(tag: Exclude<ParsedTag, { kind: "connected" }>): Exclude<PlanningProviderStatus, "available"> {
483
+ function providerStatusFromTag(
484
+ tag: Exclude<ParsedTag, { kind: "connected" }>,
485
+ ): Exclude<PlanningProviderStatus, "available"> {
404
486
  if (tag.kind === "credential_required") return "credential_required";
405
487
  if (tag.kind === "soft_degraded") return "soft_degraded";
406
488
  return "skipped";
@@ -428,11 +510,14 @@ function toolResultText(result: unknown): string | undefined {
428
510
  const content = result.content;
429
511
  if (typeof content === "string") return content;
430
512
  if (Array.isArray(content)) {
431
- return content.map((item) => {
432
- if (typeof item === "string") return item;
433
- if (isRecord(item) && typeof item.text === "string") return item.text;
434
- return "";
435
- }).filter(Boolean).join("\n");
513
+ return content
514
+ .map((item) => {
515
+ if (typeof item === "string") return item;
516
+ if (isRecord(item) && typeof item.text === "string") return item.text;
517
+ return "";
518
+ })
519
+ .filter(Boolean)
520
+ .join("\n");
436
521
  }
437
522
  return undefined;
438
523
  }
@@ -449,7 +534,8 @@ function symbolsFromArgs(args: Record<string, unknown>): EntityScope {
449
534
 
450
535
  function extractPortfolioSleeves(text: string): PortfolioExposureSleeve[] {
451
536
  const matches: PortfolioExposureSleeve[] = [];
452
- const pattern = /(\d+(?:\.\d+)?)\s*%\s*(?:in|to|of|toward|towards|allocated\s+to)?\s*([^,;.\n?]+)/gi;
537
+ const pattern =
538
+ /(\d+(?:\.\d+)?)\s*%\s*(?:in|to|of|toward|towards|allocated\s+to)?\s*([^,;.\n?]+)/gi;
453
539
  for (const match of text.matchAll(pattern)) {
454
540
  const percent = Number(match[1]);
455
541
  if (!Number.isFinite(percent)) continue;
@@ -474,15 +560,18 @@ function cleanSleeveLabel(label: string): string {
474
560
  function normalizePortfolioSleeve(label: string): string {
475
561
  const lower = label.toLowerCase();
476
562
  if (/\b(?:s&p\s*500|sp\s*500|index|voo|spy|ivv)\b/.test(lower)) return "broad_us_index";
477
- if (/\b(?:tech|technology|software|semis?|semiconductors?)\b/.test(lower)) return "technology_sector";
563
+ if (/\b(?:tech|technology|software|semis?|semiconductors?)\b/.test(lower))
564
+ return "technology_sector";
478
565
  if (/\b(?:bond|bonds|fixed\s+income|treasur(?:y|ies))\b/.test(lower)) return "bonds";
479
566
  if (/\b(?:cash|savings?|money\s*market|t[-\s]?bills?)\b/.test(lower)) return "cash";
480
567
  if (/\b(?:international|ex[-\s]?us|foreign|global)\b/.test(lower)) return "international_equity";
481
568
  if (/\b(?:stock|stocks|equity|equities)\b/.test(lower)) return "broad_equity";
482
- return lower
483
- .replace(/[^a-z0-9]+/g, "_")
484
- .replace(/^_+|_+$/g, "")
485
- .slice(0, 48) || "unknown_sleeve";
569
+ return (
570
+ lower
571
+ .replace(/[^a-z0-9]+/g, "_")
572
+ .replace(/^_+|_+$/g, "")
573
+ .slice(0, 48) || "unknown_sleeve"
574
+ );
486
575
  }
487
576
 
488
577
  function roundPercent(value: number): number {
@@ -517,8 +606,10 @@ function classifyMarketStatus(
517
606
  }
518
607
 
519
608
  function quoteAsOfCaveat(marketStatus: string): string {
520
- if (marketStatus === "open") return "Quote evidence may be intraday or delayed depending on provider.";
521
- if (marketStatus === "pre_market") return "Quote evidence may reflect the previous regular session until premarket data is fetched.";
609
+ if (marketStatus === "open")
610
+ return "Quote evidence may be intraday or delayed depending on provider.";
611
+ if (marketStatus === "pre_market")
612
+ return "Quote evidence may reflect the previous regular session until premarket data is fetched.";
522
613
  return "Quote evidence should distinguish the current calendar date from the most recent trading session.";
523
614
  }
524
615
 
@@ -1,4 +1,4 @@
1
- import type { WorkflowStep, StepOutput } from "./workflow-types.js";
1
+ import type { StepOutput, WorkflowStep } from "./workflow-types.js";
2
2
 
3
3
  /**
4
4
  * A workflow step definition that carries its prompt text.
@@ -10,7 +10,6 @@ export interface PromptStep extends Omit<WorkflowStep, "status"> {
10
10
 
11
11
  /**
12
12
  * A complete workflow definition: typed step metadata + prompt text for each step.
13
- * Replaces the old WorkflowPlan { initialPrompt, followUps }.
14
13
  */
15
14
  export interface WorkflowDefinition {
16
15
  workflowType: string;
@@ -59,17 +58,3 @@ export function promptStepOutput(stepIndex: number, stepType: string): StepOutpu
59
58
  export function toStepDefinitions(steps: PromptStep[]): Omit<WorkflowStep, "status">[] {
60
59
  return steps.map(({ prompt: _prompt, ...step }) => step);
61
60
  }
62
-
63
- /**
64
- * Convert a WorkflowDefinition to the old WorkflowPlan format for backward compatibility.
65
- */
66
- export function toWorkflowPlan(definition: WorkflowDefinition): {
67
- initialPrompt: string;
68
- followUps: string[];
69
- } {
70
- const [first, ...rest] = definition.steps;
71
- return {
72
- initialPrompt: first?.prompt ?? "",
73
- followUps: rest.map((s) => s.prompt),
74
- };
75
- }