opencandle 0.4.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 (564) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +186 -117
  3. package/dist/analysts/contracts.d.ts +1 -3
  4. package/dist/analysts/contracts.js +1 -11
  5. package/dist/analysts/contracts.js.map +1 -1
  6. package/dist/analysts/orchestrator.d.ts +1 -3
  7. package/dist/analysts/orchestrator.js +1 -26
  8. package/dist/analysts/orchestrator.js.map +1 -1
  9. package/dist/cli.js +32 -8
  10. package/dist/cli.js.map +1 -1
  11. package/dist/config.d.ts +19 -3
  12. package/dist/config.js +69 -3
  13. package/dist/config.js.map +1 -1
  14. package/dist/index.d.ts +1 -1
  15. package/dist/index.js +1 -1
  16. package/dist/index.js.map +1 -1
  17. package/dist/infra/browser.d.ts +1 -3
  18. package/dist/infra/browser.js +4 -2
  19. package/dist/infra/browser.js.map +1 -1
  20. package/dist/infra/cache.d.ts +8 -11
  21. package/dist/infra/cache.js +17 -15
  22. package/dist/infra/cache.js.map +1 -1
  23. package/dist/infra/http-client.d.ts +4 -1
  24. package/dist/infra/http-client.js +59 -6
  25. package/dist/infra/http-client.js.map +1 -1
  26. package/dist/infra/index.d.ts +3 -3
  27. package/dist/infra/index.js +3 -3
  28. package/dist/infra/index.js.map +1 -1
  29. package/dist/infra/native-dependencies.js +2 -2
  30. package/dist/infra/native-dependencies.js.map +1 -1
  31. package/dist/infra/node-version.js.map +1 -1
  32. package/dist/infra/opencandle-paths.d.ts +0 -3
  33. package/dist/infra/opencandle-paths.js +4 -11
  34. package/dist/infra/opencandle-paths.js.map +1 -1
  35. package/dist/infra/rate-limiter.d.ts +4 -0
  36. package/dist/infra/rate-limiter.js +17 -10
  37. package/dist/infra/rate-limiter.js.map +1 -1
  38. package/dist/market-state/alert-conditions.d.ts +34 -0
  39. package/dist/market-state/alert-conditions.js +23 -0
  40. package/dist/market-state/alert-conditions.js.map +1 -0
  41. package/dist/market-state/alert-runner.d.ts +55 -0
  42. package/dist/market-state/alert-runner.js +634 -0
  43. package/dist/market-state/alert-runner.js.map +1 -0
  44. package/dist/market-state/daily-report.d.ts +26 -0
  45. package/dist/market-state/daily-report.js +179 -0
  46. package/dist/market-state/daily-report.js.map +1 -0
  47. package/dist/market-state/local-automation-service.d.ts +25 -0
  48. package/dist/market-state/local-automation-service.js +119 -0
  49. package/dist/market-state/local-automation-service.js.map +1 -0
  50. package/dist/market-state/notification-delivery.d.ts +14 -0
  51. package/dist/market-state/notification-delivery.js +139 -0
  52. package/dist/market-state/notification-delivery.js.map +1 -0
  53. package/dist/market-state/resolve-for-mutation.d.ts +10 -0
  54. package/dist/market-state/resolve-for-mutation.js +15 -0
  55. package/dist/market-state/resolve-for-mutation.js.map +1 -0
  56. package/dist/market-state/resolve.d.ts +14 -0
  57. package/dist/market-state/resolve.js +89 -0
  58. package/dist/market-state/resolve.js.map +1 -0
  59. package/dist/market-state/service.d.ts +527 -0
  60. package/dist/market-state/service.js +1099 -0
  61. package/dist/market-state/service.js.map +1 -0
  62. package/dist/memory/index.d.ts +7 -7
  63. package/dist/memory/index.js +6 -6
  64. package/dist/memory/index.js.map +1 -1
  65. package/dist/memory/manager.d.ts +9 -0
  66. package/dist/memory/manager.js +39 -22
  67. package/dist/memory/manager.js.map +1 -1
  68. package/dist/memory/retrieval.js +7 -4
  69. package/dist/memory/retrieval.js.map +1 -1
  70. package/dist/memory/sqlite.js +385 -3
  71. package/dist/memory/sqlite.js.map +1 -1
  72. package/dist/memory/storage.d.ts +3 -2
  73. package/dist/memory/storage.js +1 -2
  74. package/dist/memory/storage.js.map +1 -1
  75. package/dist/memory/tool-defaults.js +64 -28
  76. package/dist/memory/tool-defaults.js.map +1 -1
  77. package/dist/memory/types.js +4 -0
  78. package/dist/memory/types.js.map +1 -1
  79. package/dist/monitor.d.ts +2 -0
  80. package/dist/monitor.js +104 -0
  81. package/dist/monitor.js.map +1 -0
  82. package/dist/onboarding/connect.js +4 -6
  83. package/dist/onboarding/connect.js.map +1 -1
  84. package/dist/onboarding/credential-interceptor.js +1 -1
  85. package/dist/onboarding/credential-interceptor.js.map +1 -1
  86. package/dist/onboarding/degradation-accumulator.js +1 -3
  87. package/dist/onboarding/degradation-accumulator.js.map +1 -1
  88. package/dist/onboarding/providers.js +3 -16
  89. package/dist/onboarding/providers.js.map +1 -1
  90. package/dist/onboarding/state.js.map +1 -1
  91. package/dist/onboarding/tool-helpers.js +1 -1
  92. package/dist/onboarding/tool-helpers.js.map +1 -1
  93. package/dist/onboarding/tool-tags.js +6 -4
  94. package/dist/onboarding/tool-tags.js.map +1 -1
  95. package/dist/onboarding/validation.js +1 -1
  96. package/dist/onboarding/validation.js.map +1 -1
  97. package/dist/pi/opencandle-extension.d.ts +8 -0
  98. package/dist/pi/opencandle-extension.js +637 -59
  99. package/dist/pi/opencandle-extension.js.map +1 -1
  100. package/dist/pi/session.d.ts +1 -1
  101. package/dist/pi/session.js +3 -1
  102. package/dist/pi/session.js.map +1 -1
  103. package/dist/pi/setup.js +17 -2
  104. package/dist/pi/setup.js.map +1 -1
  105. package/dist/pi/tool-adapter.js +5 -2
  106. package/dist/pi/tool-adapter.js.map +1 -1
  107. package/dist/prompts/context-builder.d.ts +18 -3
  108. package/dist/prompts/context-builder.js +117 -18
  109. package/dist/prompts/context-builder.js.map +1 -1
  110. package/dist/prompts/disclaimer.js +1 -1
  111. package/dist/prompts/disclaimer.js.map +1 -1
  112. package/dist/prompts/policy-cards.d.ts +13 -0
  113. package/dist/prompts/policy-cards.js +197 -0
  114. package/dist/prompts/policy-cards.js.map +1 -0
  115. package/dist/prompts/sections.d.ts +1 -1
  116. package/dist/prompts/sections.js +3 -3
  117. package/dist/prompts/sections.js.map +1 -1
  118. package/dist/prompts/symbol-preflight.d.ts +20 -0
  119. package/dist/prompts/symbol-preflight.js +49 -0
  120. package/dist/prompts/symbol-preflight.js.map +1 -0
  121. package/dist/prompts/workflow-prompts.d.ts +1 -1
  122. package/dist/prompts/workflow-prompts.js +209 -19
  123. package/dist/prompts/workflow-prompts.js.map +1 -1
  124. package/dist/providers/alpha-vantage.d.ts +1 -1
  125. package/dist/providers/alpha-vantage.js +49 -8
  126. package/dist/providers/alpha-vantage.js.map +1 -1
  127. package/dist/providers/coingecko.js +1 -1
  128. package/dist/providers/coingecko.js.map +1 -1
  129. package/dist/providers/errors.d.ts +5 -0
  130. package/dist/providers/errors.js +11 -0
  131. package/dist/providers/errors.js.map +1 -0
  132. package/dist/providers/exa-search.d.ts +2 -2
  133. package/dist/providers/exa-search.js +19 -11
  134. package/dist/providers/exa-search.js.map +1 -1
  135. package/dist/providers/fear-greed.js +1 -1
  136. package/dist/providers/fear-greed.js.map +1 -1
  137. package/dist/providers/finnhub.js +3 -5
  138. package/dist/providers/finnhub.js.map +1 -1
  139. package/dist/providers/fred.js +2 -2
  140. package/dist/providers/fred.js.map +1 -1
  141. package/dist/providers/index.d.ts +7 -6
  142. package/dist/providers/index.js +6 -5
  143. package/dist/providers/index.js.map +1 -1
  144. package/dist/providers/reddit.js +2 -2
  145. package/dist/providers/reddit.js.map +1 -1
  146. package/dist/providers/sec-edgar.d.ts +9 -1
  147. package/dist/providers/sec-edgar.js +181 -6
  148. package/dist/providers/sec-edgar.js.map +1 -1
  149. package/dist/providers/tradingview.d.ts +47 -0
  150. package/dist/providers/tradingview.js +275 -0
  151. package/dist/providers/tradingview.js.map +1 -0
  152. package/dist/providers/twitter.js +6 -8
  153. package/dist/providers/twitter.js.map +1 -1
  154. package/dist/providers/web-search.js +26 -12
  155. package/dist/providers/web-search.js.map +1 -1
  156. package/dist/providers/with-fallback.js +4 -2
  157. package/dist/providers/with-fallback.js.map +1 -1
  158. package/dist/providers/wrap-provider.d.ts +2 -3
  159. package/dist/providers/wrap-provider.js +14 -8
  160. package/dist/providers/wrap-provider.js.map +1 -1
  161. package/dist/providers/yahoo-finance.d.ts +3 -1
  162. package/dist/providers/yahoo-finance.js +226 -11
  163. package/dist/providers/yahoo-finance.js.map +1 -1
  164. package/dist/routing/classify-intent.d.ts +9 -0
  165. package/dist/routing/classify-intent.js +153 -3
  166. package/dist/routing/classify-intent.js.map +1 -1
  167. package/dist/routing/defaults.d.ts +1 -1
  168. package/dist/routing/defaults.js +3 -3
  169. package/dist/routing/defaults.js.map +1 -1
  170. package/dist/routing/entity-extractor.d.ts +2 -0
  171. package/dist/routing/entity-extractor.js +377 -26
  172. package/dist/routing/entity-extractor.js.map +1 -1
  173. package/dist/routing/fund-symbols.d.ts +2 -0
  174. package/dist/routing/fund-symbols.js +55 -0
  175. package/dist/routing/fund-symbols.js.map +1 -0
  176. package/dist/routing/horizon.d.ts +1 -0
  177. package/dist/routing/horizon.js +10 -0
  178. package/dist/routing/horizon.js.map +1 -0
  179. package/dist/routing/index.d.ts +12 -6
  180. package/dist/routing/index.js +8 -4
  181. package/dist/routing/index.js.map +1 -1
  182. package/dist/routing/legacy-rule-router.d.ts +9 -0
  183. package/dist/routing/legacy-rule-router.js +12 -0
  184. package/dist/routing/legacy-rule-router.js.map +1 -0
  185. package/dist/routing/planning.d.ts +54 -0
  186. package/dist/routing/planning.js +562 -0
  187. package/dist/routing/planning.js.map +1 -0
  188. package/dist/routing/route-manifest.d.ts +35 -0
  189. package/dist/routing/route-manifest.js +242 -0
  190. package/dist/routing/route-manifest.js.map +1 -0
  191. package/dist/routing/router-llm-client.js.map +1 -1
  192. package/dist/routing/router-prompt.js +46 -45
  193. package/dist/routing/router-prompt.js.map +1 -1
  194. package/dist/routing/router-types.d.ts +10 -0
  195. package/dist/routing/router.d.ts +1 -0
  196. package/dist/routing/router.js +572 -13
  197. package/dist/routing/router.js.map +1 -1
  198. package/dist/routing/slot-resolver.d.ts +1 -1
  199. package/dist/routing/slot-resolver.js +45 -7
  200. package/dist/routing/slot-resolver.js.map +1 -1
  201. package/dist/routing/symbol-disambiguator.d.ts +11 -0
  202. package/dist/routing/symbol-disambiguator.js +52 -0
  203. package/dist/routing/symbol-disambiguator.js.map +1 -0
  204. package/dist/routing/turn-context.d.ts +44 -0
  205. package/dist/routing/turn-context.js +45 -0
  206. package/dist/routing/turn-context.js.map +1 -0
  207. package/dist/routing/types.d.ts +15 -1
  208. package/dist/runtime/answer-contracts.d.ts +82 -0
  209. package/dist/runtime/answer-contracts.js +442 -0
  210. package/dist/runtime/answer-contracts.js.map +1 -0
  211. package/dist/runtime/artifact-contracts.d.ts +14 -0
  212. package/dist/runtime/artifact-contracts.js +57 -0
  213. package/dist/runtime/artifact-contracts.js.map +1 -0
  214. package/dist/runtime/planning-evidence.d.ts +99 -0
  215. package/dist/runtime/planning-evidence.js +466 -0
  216. package/dist/runtime/planning-evidence.js.map +1 -0
  217. package/dist/runtime/prompt-step.d.ts +1 -9
  218. package/dist/runtime/prompt-step.js +0 -10
  219. package/dist/runtime/prompt-step.js.map +1 -1
  220. package/dist/runtime/run-context.d.ts +5 -2
  221. package/dist/runtime/run-context.js +8 -1
  222. package/dist/runtime/run-context.js.map +1 -1
  223. package/dist/runtime/session-coordinator.d.ts +29 -3
  224. package/dist/runtime/session-coordinator.js +204 -31
  225. package/dist/runtime/session-coordinator.js.map +1 -1
  226. package/dist/runtime/session-title.d.ts +14 -0
  227. package/dist/runtime/session-title.js +50 -0
  228. package/dist/runtime/session-title.js.map +1 -0
  229. package/dist/runtime/tool-defaults-wrapper.js +1 -3
  230. package/dist/runtime/tool-defaults-wrapper.js.map +1 -1
  231. package/dist/runtime/validation.js.map +1 -1
  232. package/dist/runtime/workflow-events.js.map +1 -1
  233. package/dist/runtime/workflow-runner.d.ts +3 -3
  234. package/dist/runtime/workflow-runner.js +1 -1
  235. package/dist/runtime/workflow-runner.js.map +1 -1
  236. package/dist/sentiment/adapters/finnhub.d.ts +1 -1
  237. package/dist/sentiment/adapters/finnhub.js +6 -1
  238. package/dist/sentiment/adapters/finnhub.js.map +1 -1
  239. package/dist/sentiment/adapters/reddit.d.ts +2 -2
  240. package/dist/sentiment/adapters/twitter.d.ts +1 -1
  241. package/dist/sentiment/adapters/web.d.ts +1 -1
  242. package/dist/sentiment/index.d.ts +9 -11
  243. package/dist/sentiment/index.js +9 -20
  244. package/dist/sentiment/index.js.map +1 -1
  245. package/dist/sentiment/keywords.js +26 -4
  246. package/dist/sentiment/keywords.js.map +1 -1
  247. package/dist/sentiment/pipeline.d.ts +2 -2
  248. package/dist/sentiment/pipeline.js +1 -1
  249. package/dist/sentiment/pipeline.js.map +1 -1
  250. package/dist/sentiment/scorer.js +1 -1
  251. package/dist/sentiment/store.d.ts +1 -1
  252. package/dist/sentiment/store.js +1 -1
  253. package/dist/sentiment/store.js.map +1 -1
  254. package/dist/sentiment/trends.d.ts +1 -1
  255. package/dist/sentiment/trends.js.map +1 -1
  256. package/dist/sentiment/types.js.map +1 -1
  257. package/dist/system-prompt.js +7 -3
  258. package/dist/system-prompt.js.map +1 -1
  259. package/dist/tool-kit.d.ts +7 -7
  260. package/dist/tool-kit.js +4 -4
  261. package/dist/tool-kit.js.map +1 -1
  262. package/dist/tools/fundamentals/company-overview.js +12 -7
  263. package/dist/tools/fundamentals/company-overview.js.map +1 -1
  264. package/dist/tools/fundamentals/comps.js +19 -10
  265. package/dist/tools/fundamentals/comps.js.map +1 -1
  266. package/dist/tools/fundamentals/dcf.js +24 -12
  267. package/dist/tools/fundamentals/dcf.js.map +1 -1
  268. package/dist/tools/fundamentals/earnings.js +9 -4
  269. package/dist/tools/fundamentals/earnings.js.map +1 -1
  270. package/dist/tools/fundamentals/financials.js +9 -4
  271. package/dist/tools/fundamentals/financials.js.map +1 -1
  272. package/dist/tools/fundamentals/sec-filings.d.ts +1 -0
  273. package/dist/tools/fundamentals/sec-filings.js +36 -4
  274. package/dist/tools/fundamentals/sec-filings.js.map +1 -1
  275. package/dist/tools/index.d.ts +23 -18
  276. package/dist/tools/index.js +53 -38
  277. package/dist/tools/index.js.map +1 -1
  278. package/dist/tools/interaction/ask-user.js +15 -3
  279. package/dist/tools/interaction/ask-user.js.map +1 -1
  280. package/dist/tools/interaction/twitter-login.js +13 -3
  281. package/dist/tools/interaction/twitter-login.js.map +1 -1
  282. package/dist/tools/macro/fear-greed.js +1 -1
  283. package/dist/tools/macro/fear-greed.js.map +1 -1
  284. package/dist/tools/macro/fred-data.d.ts +1 -1
  285. package/dist/tools/macro/fred-data.js +44 -9
  286. package/dist/tools/macro/fred-data.js.map +1 -1
  287. package/dist/tools/market/crypto-history.js +21 -3
  288. package/dist/tools/market/crypto-history.js.map +1 -1
  289. package/dist/tools/market/crypto-price.js +4 -2
  290. package/dist/tools/market/crypto-price.js.map +1 -1
  291. package/dist/tools/market/screen-stocks.d.ts +18 -0
  292. package/dist/tools/market/screen-stocks.js +252 -0
  293. package/dist/tools/market/screen-stocks.js.map +1 -0
  294. package/dist/tools/market/search-ticker.js +161 -9
  295. package/dist/tools/market/search-ticker.js.map +1 -1
  296. package/dist/tools/market/stock-history.d.ts +2 -2
  297. package/dist/tools/market/stock-history.js +27 -8
  298. package/dist/tools/market/stock-history.js.map +1 -1
  299. package/dist/tools/market/stock-quote.js +6 -4
  300. package/dist/tools/market/stock-quote.js.map +1 -1
  301. package/dist/tools/options/greeks.js +1 -2
  302. package/dist/tools/options/greeks.js.map +1 -1
  303. package/dist/tools/options/option-chain.js +27 -9
  304. package/dist/tools/options/option-chain.js.map +1 -1
  305. package/dist/tools/portfolio/alerts.d.ts +15 -0
  306. package/dist/tools/portfolio/alerts.js +357 -0
  307. package/dist/tools/portfolio/alerts.js.map +1 -0
  308. package/dist/tools/portfolio/correlation.d.ts +1 -1
  309. package/dist/tools/portfolio/correlation.js +34 -14
  310. package/dist/tools/portfolio/correlation.js.map +1 -1
  311. package/dist/tools/portfolio/daily-report.d.ts +8 -0
  312. package/dist/tools/portfolio/daily-report.js +83 -0
  313. package/dist/tools/portfolio/daily-report.js.map +1 -0
  314. package/dist/tools/portfolio/holdings-overlap.d.ts +8 -0
  315. package/dist/tools/portfolio/holdings-overlap.js +112 -0
  316. package/dist/tools/portfolio/holdings-overlap.js.map +1 -0
  317. package/dist/tools/portfolio/notifications.d.ts +7 -0
  318. package/dist/tools/portfolio/notifications.js +43 -0
  319. package/dist/tools/portfolio/notifications.js.map +1 -0
  320. package/dist/tools/portfolio/predictions.d.ts +12 -6
  321. package/dist/tools/portfolio/predictions.js +338 -88
  322. package/dist/tools/portfolio/predictions.js.map +1 -1
  323. package/dist/tools/portfolio/risk-analysis.d.ts +1 -1
  324. package/dist/tools/portfolio/risk-analysis.js +46 -7
  325. package/dist/tools/portfolio/risk-analysis.js.map +1 -1
  326. package/dist/tools/portfolio/tracker.d.ts +4 -3
  327. package/dist/tools/portfolio/tracker.js +247 -102
  328. package/dist/tools/portfolio/tracker.js.map +1 -1
  329. package/dist/tools/portfolio/watchlist.d.ts +6 -4
  330. package/dist/tools/portfolio/watchlist.js +209 -101
  331. package/dist/tools/portfolio/watchlist.js.map +1 -1
  332. package/dist/tools/sentiment/reddit-sentiment.js +24 -11
  333. package/dist/tools/sentiment/reddit-sentiment.js.map +1 -1
  334. package/dist/tools/sentiment/sentiment-summary.js +71 -14
  335. package/dist/tools/sentiment/sentiment-summary.js.map +1 -1
  336. package/dist/tools/sentiment/sentiment-trend.d.ts +1 -1
  337. package/dist/tools/sentiment/sentiment-trend.js +12 -2
  338. package/dist/tools/sentiment/sentiment-trend.js.map +1 -1
  339. package/dist/tools/sentiment/twitter-sentiment.js +13 -6
  340. package/dist/tools/sentiment/twitter-sentiment.js.map +1 -1
  341. package/dist/tools/sentiment/untrusted-text.d.ts +2 -0
  342. package/dist/tools/sentiment/untrusted-text.js +17 -0
  343. package/dist/tools/sentiment/untrusted-text.js.map +1 -0
  344. package/dist/tools/sentiment/web-search.js +37 -12
  345. package/dist/tools/sentiment/web-search.js.map +1 -1
  346. package/dist/tools/sentiment/web-sentiment.js +16 -4
  347. package/dist/tools/sentiment/web-sentiment.js.map +1 -1
  348. package/dist/tools/technical/backtest.d.ts +3 -3
  349. package/dist/tools/technical/backtest.js +65 -44
  350. package/dist/tools/technical/backtest.js.map +1 -1
  351. package/dist/tools/technical/indicators.js +24 -8
  352. package/dist/tools/technical/indicators.js.map +1 -1
  353. package/dist/types/index.d.ts +3 -3
  354. package/dist/types/index.js.map +1 -1
  355. package/dist/types/market.d.ts +1 -0
  356. package/dist/types/options.d.ts +10 -0
  357. package/dist/types/portfolio.d.ts +41 -4
  358. package/dist/workflows/compare-assets.d.ts +0 -3
  359. package/dist/workflows/compare-assets.js +55 -10
  360. package/dist/workflows/compare-assets.js.map +1 -1
  361. package/dist/workflows/index.d.ts +3 -4
  362. package/dist/workflows/index.js +3 -3
  363. package/dist/workflows/index.js.map +1 -1
  364. package/dist/workflows/options-screener.d.ts +0 -3
  365. package/dist/workflows/options-screener.js +88 -14
  366. package/dist/workflows/options-screener.js.map +1 -1
  367. package/dist/workflows/portfolio-builder.d.ts +0 -3
  368. package/dist/workflows/portfolio-builder.js +7 -11
  369. package/dist/workflows/portfolio-builder.js.map +1 -1
  370. package/gui/server/ask-user-bridge.ts +82 -0
  371. package/gui/server/automation-heartbeat.ts +97 -0
  372. package/gui/server/background-quotes.ts +97 -1
  373. package/gui/server/chat-event-adapter.ts +32 -10
  374. package/gui/server/chat-run-session.ts +16 -0
  375. package/gui/server/gui-session-manager.ts +5 -0
  376. package/gui/server/invoke-tool.ts +144 -1
  377. package/gui/server/live-chat-event-adapter.ts +21 -6
  378. package/gui/server/market-state-api.ts +315 -0
  379. package/gui/server/model-setup.ts +149 -2
  380. package/gui/server/private-api-access.ts +62 -0
  381. package/gui/server/projector.ts +58 -11
  382. package/gui/server/prompt-observation.ts +58 -0
  383. package/gui/server/quote-snapshot-store.ts +50 -0
  384. package/gui/server/server.ts +236 -376
  385. package/gui/server/session-actions.ts +186 -1
  386. package/gui/server/session-entry-wait.ts +81 -0
  387. package/gui/server/shutdown.ts +47 -0
  388. package/gui/server/tool-invoke-ack.ts +49 -0
  389. package/gui/server/tool-metadata.ts +23 -10
  390. package/gui/server/websocket.ts +13 -3
  391. package/gui/server/writer-lock.ts +6 -2
  392. package/gui/server/ws-hub.ts +292 -0
  393. package/gui/shared/chat-events.ts +16 -1
  394. package/gui/shared/event-reducer.ts +24 -6
  395. package/gui/web/dist/assets/CatalogOverlay-eJ2cBk33.js +1 -0
  396. package/gui/web/dist/assets/index-2KZtKBmu.css +1 -0
  397. package/gui/web/dist/assets/index-CveNgtDg.js +69 -0
  398. package/gui/web/dist/index.html +2 -2
  399. package/package.json +22 -12
  400. package/src/analysts/contracts.ts +10 -23
  401. package/src/analysts/orchestrator.ts +8 -43
  402. package/src/cli.ts +37 -13
  403. package/src/config.ts +99 -7
  404. package/src/index.ts +1 -1
  405. package/src/infra/browser.ts +4 -2
  406. package/src/infra/cache.ts +41 -30
  407. package/src/infra/http-client.ts +72 -6
  408. package/src/infra/index.ts +7 -10
  409. package/src/infra/native-dependencies.ts +8 -3
  410. package/src/infra/node-version.ts +3 -1
  411. package/src/infra/opencandle-paths.ts +3 -14
  412. package/src/infra/rate-limiter.ts +32 -20
  413. package/src/market-state/alert-conditions.ts +82 -0
  414. package/src/market-state/alert-runner.ts +863 -0
  415. package/src/market-state/daily-report.ts +247 -0
  416. package/src/market-state/local-automation-service.ts +162 -0
  417. package/src/market-state/notification-delivery.ts +158 -0
  418. package/src/market-state/resolve-for-mutation.ts +24 -0
  419. package/src/market-state/resolve.ts +112 -0
  420. package/src/market-state/service.ts +2344 -0
  421. package/src/memory/index.ts +7 -7
  422. package/src/memory/manager.ts +57 -26
  423. package/src/memory/retrieval.ts +8 -7
  424. package/src/memory/sqlite.ts +407 -6
  425. package/src/memory/storage.ts +8 -17
  426. package/src/memory/tool-defaults.ts +60 -39
  427. package/src/memory/types.ts +7 -3
  428. package/src/monitor.ts +121 -0
  429. package/src/onboarding/connect.ts +10 -33
  430. package/src/onboarding/credential-interceptor.ts +3 -15
  431. package/src/onboarding/degradation-accumulator.ts +1 -3
  432. package/src/onboarding/providers.ts +9 -40
  433. package/src/onboarding/state.ts +4 -15
  434. package/src/onboarding/tool-helpers.ts +2 -9
  435. package/src/onboarding/tool-tags.ts +6 -6
  436. package/src/onboarding/validation.ts +14 -20
  437. package/src/pi/opencandle-extension.ts +795 -120
  438. package/src/pi/session.ts +7 -5
  439. package/src/pi/setup.ts +61 -33
  440. package/src/pi/tool-adapter.ts +5 -2
  441. package/src/prompts/context-builder.ts +143 -21
  442. package/src/prompts/disclaimer.ts +1 -1
  443. package/src/prompts/policy-cards.ts +220 -0
  444. package/src/prompts/sections.ts +4 -4
  445. package/src/prompts/symbol-preflight.ts +80 -0
  446. package/src/prompts/workflow-prompts.ts +231 -28
  447. package/src/providers/alpha-vantage.ts +82 -40
  448. package/src/providers/coingecko.ts +2 -5
  449. package/src/providers/errors.ts +9 -0
  450. package/src/providers/exa-search.ts +24 -22
  451. package/src/providers/fear-greed.ts +1 -1
  452. package/src/providers/finnhub.ts +7 -6
  453. package/src/providers/fred.ts +3 -3
  454. package/src/providers/index.ts +14 -6
  455. package/src/providers/reddit.ts +17 -6
  456. package/src/providers/sec-edgar.ts +235 -5
  457. package/src/providers/tradingview.ts +399 -0
  458. package/src/providers/twitter.ts +6 -8
  459. package/src/providers/web-search.ts +30 -20
  460. package/src/providers/with-fallback.ts +8 -7
  461. package/src/providers/wrap-provider.ts +15 -10
  462. package/src/providers/yahoo-finance.ts +292 -20
  463. package/src/routing/classify-intent.ts +186 -4
  464. package/src/routing/defaults.ts +4 -4
  465. package/src/routing/entity-extractor.ts +428 -28
  466. package/src/routing/fund-symbols.ts +58 -0
  467. package/src/routing/horizon.ts +7 -0
  468. package/src/routing/index.ts +60 -16
  469. package/src/routing/legacy-rule-router.ts +13 -0
  470. package/src/routing/planning.ts +823 -0
  471. package/src/routing/route-manifest.ts +309 -0
  472. package/src/routing/router-llm-client.ts +4 -4
  473. package/src/routing/router-prompt.ts +52 -52
  474. package/src/routing/router-types.ts +18 -0
  475. package/src/routing/router.ts +717 -20
  476. package/src/routing/slot-resolver.ts +75 -14
  477. package/src/routing/symbol-disambiguator.ts +72 -0
  478. package/src/routing/turn-context.ts +108 -0
  479. package/src/routing/types.ts +15 -1
  480. package/src/runtime/answer-contracts.ts +672 -0
  481. package/src/runtime/artifact-contracts.ts +77 -0
  482. package/src/runtime/planning-evidence.ts +682 -0
  483. package/src/runtime/prompt-step.ts +1 -16
  484. package/src/runtime/run-context.ts +12 -2
  485. package/src/runtime/session-coordinator.ts +297 -56
  486. package/src/runtime/session-title.ts +60 -0
  487. package/src/runtime/tool-defaults-wrapper.ts +1 -3
  488. package/src/runtime/validation.ts +1 -4
  489. package/src/runtime/workflow-events.ts +7 -7
  490. package/src/runtime/workflow-runner.ts +5 -11
  491. package/src/sentiment/adapters/finnhub.ts +7 -2
  492. package/src/sentiment/adapters/reddit.ts +2 -2
  493. package/src/sentiment/adapters/twitter.ts +1 -1
  494. package/src/sentiment/adapters/web.ts +1 -1
  495. package/src/sentiment/index.ts +16 -26
  496. package/src/sentiment/keywords.ts +26 -4
  497. package/src/sentiment/pipeline.ts +15 -4
  498. package/src/sentiment/scorer.ts +1 -1
  499. package/src/sentiment/store.ts +2 -2
  500. package/src/sentiment/trends.ts +9 -3
  501. package/src/sentiment/types.ts +5 -4
  502. package/src/system-prompt.ts +7 -3
  503. package/src/tool-kit.ts +10 -9
  504. package/src/tools/fundamentals/company-overview.ts +20 -10
  505. package/src/tools/fundamentals/comps.ts +69 -56
  506. package/src/tools/fundamentals/dcf.ts +146 -96
  507. package/src/tools/fundamentals/earnings.ts +17 -7
  508. package/src/tools/fundamentals/financials.ts +17 -8
  509. package/src/tools/fundamentals/sec-filings.ts +52 -8
  510. package/src/tools/index.ts +53 -38
  511. package/src/tools/interaction/ask-user.ts +22 -10
  512. package/src/tools/interaction/twitter-login.ts +17 -5
  513. package/src/tools/macro/fear-greed.ts +2 -2
  514. package/src/tools/macro/fred-data.ts +80 -42
  515. package/src/tools/market/crypto-history.ts +25 -4
  516. package/src/tools/market/crypto-price.ts +7 -7
  517. package/src/tools/market/screen-stocks.ts +279 -0
  518. package/src/tools/market/search-ticker.ts +219 -18
  519. package/src/tools/market/stock-history.ts +38 -13
  520. package/src/tools/market/stock-quote.ts +11 -8
  521. package/src/tools/options/greeks.ts +5 -6
  522. package/src/tools/options/option-chain.ts +47 -18
  523. package/src/tools/portfolio/alerts.ts +457 -0
  524. package/src/tools/portfolio/correlation.ts +48 -21
  525. package/src/tools/portfolio/daily-report.ts +101 -0
  526. package/src/tools/portfolio/holdings-overlap.ts +139 -0
  527. package/src/tools/portfolio/notifications.ts +45 -0
  528. package/src/tools/portfolio/predictions.ts +407 -107
  529. package/src/tools/portfolio/risk-analysis.ts +47 -8
  530. package/src/tools/portfolio/tracker.ts +271 -110
  531. package/src/tools/portfolio/watchlist.ts +251 -116
  532. package/src/tools/sentiment/reddit-sentiment.ts +51 -25
  533. package/src/tools/sentiment/sentiment-summary.ts +116 -35
  534. package/src/tools/sentiment/sentiment-trend.ts +24 -7
  535. package/src/tools/sentiment/twitter-sentiment.ts +23 -16
  536. package/src/tools/sentiment/untrusted-text.ts +21 -0
  537. package/src/tools/sentiment/web-search.ts +52 -16
  538. package/src/tools/sentiment/web-sentiment.ts +27 -11
  539. package/src/tools/technical/backtest.ts +78 -47
  540. package/src/tools/technical/indicators.ts +40 -17
  541. package/src/types/index.ts +8 -3
  542. package/src/types/market.ts +1 -0
  543. package/src/types/options.ts +17 -0
  544. package/src/types/portfolio.ts +46 -4
  545. package/src/types/sentiment.ts +2 -2
  546. package/src/workflows/compare-assets.ts +67 -19
  547. package/src/workflows/index.ts +3 -4
  548. package/src/workflows/options-screener.ts +98 -22
  549. package/src/workflows/portfolio-builder.ts +40 -29
  550. package/dist/runtime/index.d.ts +0 -16
  551. package/dist/runtime/index.js +0 -10
  552. package/dist/runtime/index.js.map +0 -1
  553. package/dist/runtime/provider-ids.d.ts +0 -14
  554. package/dist/runtime/provider-ids.js +0 -14
  555. package/dist/runtime/provider-ids.js.map +0 -1
  556. package/dist/workflows/types.d.ts +0 -4
  557. package/dist/workflows/types.js +0 -2
  558. package/dist/workflows/types.js.map +0 -1
  559. package/gui/web/dist/assets/CatalogOverlay-D1ImSJTe.js +0 -1
  560. package/gui/web/dist/assets/index-DBrWq43L.css +0 -1
  561. package/gui/web/dist/assets/index-RflHaj0y.js +0 -67
  562. package/src/runtime/index.ts +0 -55
  563. package/src/runtime/provider-ids.ts +0 -15
  564. package/src/workflows/types.ts +0 -4
@@ -1,10 +1,10 @@
1
- import { Type } from "@sinclair/typebox";
2
1
  import type { AgentTool } from "@earendil-works/pi-agent-core";
3
- import { getOverview, getFinancials } from "../../providers/alpha-vantage.js";
4
- import { getQuote } from "../../providers/yahoo-finance.js";
5
- import { wrapProvider } from "../../providers/wrap-provider.js";
2
+ import { Type } from "@sinclair/typebox";
6
3
  import { getConfig } from "../../config.js";
7
4
  import { withCredentialCheck } from "../../onboarding/tool-helpers.js";
5
+ import { getFinancials, getOverview } from "../../providers/alpha-vantage.js";
6
+ import { wrapProvider } from "../../providers/wrap-provider.js";
7
+ import { getQuote } from "../../providers/yahoo-finance.js";
8
8
  import type { FinancialStatement } from "../../types/fundamentals.js";
9
9
 
10
10
  export interface DCFResult {
@@ -35,7 +35,15 @@ export interface DCFParams {
35
35
  }
36
36
 
37
37
  export function computeDCF(params: DCFParams): DCFResult {
38
- const { freeCashFlow, growthRate, discountRate, terminalGrowth, years, netDebt, sharesOutstanding } = params;
38
+ const {
39
+ freeCashFlow,
40
+ growthRate,
41
+ discountRate,
42
+ terminalGrowth,
43
+ years,
44
+ netDebt,
45
+ sharesOutstanding,
46
+ } = params;
39
47
 
40
48
  // Project future cash flows (mid-year convention: discount at year-0.5)
41
49
  const projectedCashFlows: Array<{ year: number; fcf: number; presentValue: number }> = [];
@@ -59,13 +67,25 @@ export function computeDCF(params: DCFParams): DCFResult {
59
67
  const intrinsicValue = equityValue / sharesOutstanding;
60
68
 
61
69
  // Sensitivity table: vary growth ±2% and discount ±2%
62
- const sensitivityTable: Array<{ growthRate: number; discountRate: number; intrinsicValue: number }> = [];
70
+ const sensitivityTable: Array<{
71
+ growthRate: number;
72
+ discountRate: number;
73
+ intrinsicValue: number;
74
+ }> = [];
63
75
  for (let gDelta = -0.02; gDelta <= 0.02; gDelta += 0.01) {
64
76
  for (let dDelta = -0.02; dDelta <= 0.02; dDelta += 0.01) {
65
77
  const g = growthRate + gDelta;
66
78
  const d = discountRate + dDelta;
67
79
  if (d <= terminalGrowth || d <= 0 || g < 0) continue;
68
- const sensResult = computeDCFSimple(freeCashFlow, g, d, terminalGrowth, years, netDebt, sharesOutstanding);
80
+ const sensResult = computeDCFSimple(
81
+ freeCashFlow,
82
+ g,
83
+ d,
84
+ terminalGrowth,
85
+ years,
86
+ netDebt,
87
+ sharesOutstanding,
88
+ );
69
89
  sensitivityTable.push({ growthRate: g, discountRate: d, intrinsicValue: sensResult });
70
90
  }
71
91
  }
@@ -74,17 +94,25 @@ export function computeDCF(params: DCFParams): DCFResult {
74
94
  const warnings: string[] = [];
75
95
  const tvPctOfEV = pvTerminal / enterpriseValue;
76
96
  if (tvPctOfEV > 0.85) {
77
- warnings.push(`Terminal value is ${(tvPctOfEV * 100).toFixed(0)}% of enterprise value (typical: 40-80%). The valuation is heavily dependent on terminal assumptions.`);
97
+ warnings.push(
98
+ `Terminal value is ${(tvPctOfEV * 100).toFixed(0)}% of enterprise value (typical: 40-80%). The valuation is heavily dependent on terminal assumptions.`,
99
+ );
78
100
  }
79
101
  const spreadPct = discountRate - terminalGrowth;
80
102
  if (spreadPct < 0.02) {
81
- warnings.push(`Terminal growth (${(terminalGrowth * 100).toFixed(1)}%) is very close to discount rate (${(discountRate * 100).toFixed(1)}%). Small changes in assumptions will produce large swings in value.`);
103
+ warnings.push(
104
+ `Terminal growth (${(terminalGrowth * 100).toFixed(1)}%) is very close to discount rate (${(discountRate * 100).toFixed(1)}%). Small changes in assumptions will produce large swings in value.`,
105
+ );
82
106
  }
83
- if (discountRate < 0.05 || discountRate > 0.20) {
84
- warnings.push(`Discount rate of ${(discountRate * 100).toFixed(1)}% is outside typical WACC range (5-20%).`);
107
+ if (discountRate < 0.05 || discountRate > 0.2) {
108
+ warnings.push(
109
+ `Discount rate of ${(discountRate * 100).toFixed(1)}% is outside typical WACC range (5-20%).`,
110
+ );
85
111
  }
86
- if (growthRate > 0.20) {
87
- warnings.push(`Growth rate of ${(growthRate * 100).toFixed(1)}% exceeds 20%. High growth is difficult to sustain — consider a multi-stage model.`);
112
+ if (growthRate > 0.2) {
113
+ warnings.push(
114
+ `Growth rate of ${(growthRate * 100).toFixed(1)}% exceeds 20%. High growth is difficult to sustain — consider a multi-stage model.`,
115
+ );
88
116
  }
89
117
 
90
118
  return {
@@ -106,7 +134,13 @@ export function computeDCF(params: DCFParams): DCFResult {
106
134
  }
107
135
 
108
136
  function computeDCFSimple(
109
- fcf: number, g: number, d: number, tg: number, years: number, debt: number, shares: number,
137
+ fcf: number,
138
+ g: number,
139
+ d: number,
140
+ tg: number,
141
+ years: number,
142
+ debt: number,
143
+ shares: number,
110
144
  ): number {
111
145
  let sumPV = 0;
112
146
  for (let y = 1; y <= years; y++) {
@@ -129,7 +163,10 @@ export function computeNetDebt(f: FinancialStatement): number {
129
163
  const params = Type.Object({
130
164
  symbol: Type.String({ description: "Stock ticker symbol (e.g. AAPL, MSFT)" }),
131
165
  growth_rate: Type.Optional(
132
- Type.Number({ description: "Annual FCF growth rate as decimal (e.g. 0.10 for 10%). If omitted, estimated from historical data." }),
166
+ Type.Number({
167
+ description:
168
+ "Annual FCF growth rate as decimal (e.g. 0.10 for 10%). If omitted, estimated from historical data.",
169
+ }),
133
170
  ),
134
171
  discount_rate: Type.Optional(
135
172
  Type.Number({ description: "Discount rate / WACC as decimal (default: 0.10 for 10%)" }),
@@ -148,100 +185,113 @@ export const dcfTool: AgentTool<typeof params> = {
148
185
  description:
149
186
  "Compute a Discounted Cash Flow (DCF) intrinsic value estimate for a stock. Uses free cash flow, growth projections, and a discount rate to estimate what the stock is worth. Returns intrinsic value per share, margin of safety vs current price, and a sensitivity table.",
150
187
  parameters: params,
151
- async execute(toolCallId, args) {
188
+ async execute(_toolCallId, args) {
152
189
  return withCredentialCheck("alpha_vantage", async () => {
153
- const symbol = args.symbol.toUpperCase();
154
- const config = getConfig();
190
+ const symbol = args.symbol.toUpperCase();
191
+ const config = getConfig();
155
192
 
156
- const [overviewResult, financialsResult, quoteResult] = await Promise.all([
157
- wrapProvider("alphavantage", () => getOverview(symbol, config.alphaVantageApiKey!)),
158
- wrapProvider("alphavantage", () => getFinancials(symbol, config.alphaVantageApiKey!)),
159
- wrapProvider("yahoo", () => getQuote(symbol)),
160
- ]);
193
+ const [overviewResult, financialsResult, quoteResult] = await Promise.all([
194
+ wrapProvider("alphavantage", () => getOverview(symbol, config.alphaVantageApiKey!)),
195
+ wrapProvider("alphavantage", () => getFinancials(symbol, config.alphaVantageApiKey!)),
196
+ wrapProvider("yahoo", () => getQuote(symbol)),
197
+ ]);
161
198
 
162
- const missing: string[] = [];
163
- if (overviewResult.status === "unavailable") missing.push(`company overview (${overviewResult.reason})`);
164
- if (financialsResult.status === "unavailable") missing.push(`financial statements (${financialsResult.reason})`);
165
- if (quoteResult.status === "unavailable") missing.push(`stock quote (${quoteResult.reason})`);
199
+ const missing: string[] = [];
200
+ if (overviewResult.status === "unavailable")
201
+ missing.push(`company overview (${overviewResult.reason})`);
202
+ if (financialsResult.status === "unavailable")
203
+ missing.push(`financial statements (${financialsResult.reason})`);
204
+ if (quoteResult.status === "unavailable") missing.push(`stock quote (${quoteResult.reason})`);
166
205
 
167
- if (financialsResult.status === "unavailable" || quoteResult.status === "unavailable") {
168
- return {
169
- content: [{ type: "text", text: `⚠ DCF valuation unavailable for ${symbol}. Missing: ${missing.join(", ")}. Both financials and current price are required.` }],
170
- details: null,
171
- };
172
- }
206
+ if (financialsResult.status === "unavailable" || quoteResult.status === "unavailable") {
207
+ return {
208
+ content: [
209
+ {
210
+ type: "text",
211
+ text: `⚠ DCF valuation unavailable for ${symbol}. Missing: ${missing.join(", ")}. Both financials and current price are required.`,
212
+ },
213
+ ],
214
+ details: null,
215
+ };
216
+ }
173
217
 
174
- const overview = overviewResult.status === "ok" ? overviewResult.data : null;
175
- const financials = financialsResult.data;
176
- const quote = quoteResult.data;
218
+ const overview = overviewResult.status === "ok" ? overviewResult.data : null;
219
+ const financials = financialsResult.data;
220
+ const quote = quoteResult.data;
177
221
 
178
- const latestFCF = financials[0]?.freeCashFlow ?? 0;
179
- if (latestFCF <= 0) {
180
- return {
181
- content: [{ type: "text", text: `${symbol} has negative or zero free cash flow ($${latestFCF.toLocaleString()}). DCF is not meaningful for companies without positive FCF.` }],
182
- details: null,
183
- };
184
- }
222
+ const latestFCF = financials[0]?.freeCashFlow ?? 0;
223
+ if (latestFCF <= 0) {
224
+ return {
225
+ content: [
226
+ {
227
+ type: "text",
228
+ text: `${symbol} has negative or zero free cash flow ($${latestFCF.toLocaleString()}). DCF is not meaningful for companies without positive FCF.`,
229
+ },
230
+ ],
231
+ details: null,
232
+ };
233
+ }
185
234
 
186
- // Estimate growth from historical FCF if not provided
187
- let growthRate = args.growth_rate ?? 0.10;
188
- if (!args.growth_rate && financials.length >= 2) {
189
- const olderFCF = financials[1]?.freeCashFlow;
190
- if (olderFCF && olderFCF > 0) {
191
- growthRate = Math.max(0.02, Math.min(0.25, (latestFCF - olderFCF) / olderFCF));
235
+ // Estimate growth from historical FCF if not provided
236
+ let growthRate = args.growth_rate ?? 0.1;
237
+ if (!args.growth_rate && financials.length >= 2) {
238
+ const olderFCF = financials[1]?.freeCashFlow;
239
+ if (olderFCF && olderFCF > 0) {
240
+ growthRate = Math.max(0.02, Math.min(0.25, (latestFCF - olderFCF) / olderFCF));
241
+ }
192
242
  }
193
- }
194
243
 
195
- const discountRate = args.discount_rate ?? 0.10;
196
- const terminalGrowth = args.terminal_growth ?? 0.03;
197
- const years = args.projection_years ?? 5;
198
- const marketCap = overview?.marketCap ?? 0;
199
- const sharesOutstanding = quote.price > 0 && marketCap > 0 ? marketCap / quote.price : 1;
200
- const netDebt = financials[0] ? computeNetDebt(financials[0]) : 0;
244
+ const discountRate = args.discount_rate ?? 0.1;
245
+ const terminalGrowth = args.terminal_growth ?? 0.03;
246
+ const years = args.projection_years ?? 5;
247
+ const marketCap = overview?.marketCap ?? 0;
248
+ const sharesOutstanding = quote.price > 0 && marketCap > 0 ? marketCap / quote.price : 1;
249
+ const netDebt = financials[0] ? computeNetDebt(financials[0]) : 0;
201
250
 
202
- const result = computeDCF({
203
- freeCashFlow: latestFCF,
204
- growthRate,
205
- discountRate,
206
- terminalGrowth,
207
- years,
208
- netDebt: Math.max(0, netDebt),
209
- sharesOutstanding,
210
- });
251
+ const result = computeDCF({
252
+ freeCashFlow: latestFCF,
253
+ growthRate,
254
+ discountRate,
255
+ terminalGrowth,
256
+ years,
257
+ netDebt: Math.max(0, netDebt),
258
+ sharesOutstanding,
259
+ });
211
260
 
212
- const marginOfSafety = (result.intrinsicValue - quote.price) / result.intrinsicValue;
213
- const upside = (result.intrinsicValue - quote.price) / quote.price;
261
+ const marginOfSafety = (result.intrinsicValue - quote.price) / result.intrinsicValue;
262
+ const upside = (result.intrinsicValue - quote.price) / quote.price;
214
263
 
215
- const lines = [
216
- `**${symbol} DCF Valuation**`,
217
- ``,
218
- `Current Price: $${quote.price.toFixed(2)}`,
219
- `Intrinsic Value: $${result.intrinsicValue.toFixed(2)}`,
220
- `Margin of Safety: ${(marginOfSafety * 100).toFixed(1)}%`,
221
- `Upside/Downside: ${upside >= 0 ? "+" : ""}${(upside * 100).toFixed(1)}%`,
222
- ``,
223
- `**Assumptions**`,
224
- `Free Cash Flow: $${(latestFCF / 1e9).toFixed(2)}B`,
225
- `Growth Rate: ${(growthRate * 100).toFixed(1)}%`,
226
- `Discount Rate (WACC): ${(discountRate * 100).toFixed(1)}%`,
227
- `Terminal Growth: ${(terminalGrowth * 100).toFixed(1)}%`,
228
- `Projection: ${years} years`,
229
- ``,
230
- `**Projected Cash Flows**`,
231
- ...result.projectedCashFlows.map((cf) =>
232
- ` Year ${cf.year}: FCF $${(cf.fcf / 1e9).toFixed(2)}B → PV $${(cf.presentValue / 1e9).toFixed(2)}B`
233
- ),
234
- ` Terminal Value: $${(result.terminalValue / 1e9).toFixed(2)}B`,
235
- ` Enterprise Value: $${(result.enterpriseValue / 1e9).toFixed(2)}B`,
236
- ``,
237
- `**Sensitivity Table** (Intrinsic Value at different Growth/Discount rates)`,
238
- ...formatSensitivityTable(result.sensitivityTable),
239
- ];
264
+ const lines = [
265
+ `**${symbol} DCF Valuation**`,
266
+ ``,
267
+ `Current Price: $${quote.price.toFixed(2)}`,
268
+ `Intrinsic Value: $${result.intrinsicValue.toFixed(2)}`,
269
+ `Margin of Safety: ${(marginOfSafety * 100).toFixed(1)}%`,
270
+ `Upside/Downside: ${upside >= 0 ? "+" : ""}${(upside * 100).toFixed(1)}%`,
271
+ ``,
272
+ `**Assumptions**`,
273
+ `Free Cash Flow: $${(latestFCF / 1e9).toFixed(2)}B`,
274
+ `Growth Rate: ${(growthRate * 100).toFixed(1)}%`,
275
+ `Discount Rate (WACC): ${(discountRate * 100).toFixed(1)}%`,
276
+ `Terminal Growth: ${(terminalGrowth * 100).toFixed(1)}%`,
277
+ `Projection: ${years} years`,
278
+ ``,
279
+ `**Projected Cash Flows**`,
280
+ ...result.projectedCashFlows.map(
281
+ (cf) =>
282
+ ` Year ${cf.year}: FCF $${(cf.fcf / 1e9).toFixed(2)}B → PV $${(cf.presentValue / 1e9).toFixed(2)}B`,
283
+ ),
284
+ ` Terminal Value: $${(result.terminalValue / 1e9).toFixed(2)}B`,
285
+ ` Enterprise Value: $${(result.enterpriseValue / 1e9).toFixed(2)}B`,
286
+ ``,
287
+ `**Sensitivity Table** (Intrinsic Value at different Growth/Discount rates)`,
288
+ ...formatSensitivityTable(result.sensitivityTable),
289
+ ];
240
290
 
241
- return {
242
- content: [{ type: "text", text: lines.join("\n") }],
243
- details: { ...result, currentPrice: quote.price, marginOfSafety, upside },
244
- };
291
+ return {
292
+ content: [{ type: "text", text: lines.join("\n") }],
293
+ details: { ...result, currentPrice: quote.price, marginOfSafety, upside },
294
+ };
245
295
  });
246
296
  },
247
297
  };
@@ -1,28 +1,38 @@
1
- import { Type } from "@sinclair/typebox";
2
1
  import type { AgentTool } from "@earendil-works/pi-agent-core";
3
- import { getEarnings } from "../../providers/alpha-vantage.js";
4
- import { wrapProvider } from "../../providers/wrap-provider.js";
2
+ import { Type } from "@sinclair/typebox";
5
3
  import { getConfig } from "../../config.js";
6
4
  import { withCredentialCheck } from "../../onboarding/tool-helpers.js";
5
+ import { getEarnings } from "../../providers/alpha-vantage.js";
6
+ import { wrapProvider } from "../../providers/wrap-provider.js";
7
7
  import type { EarningsData } from "../../types/fundamentals.js";
8
8
 
9
9
  const params = Type.Object({
10
10
  symbol: Type.String({ description: "Stock ticker symbol (e.g. AAPL, MSFT)" }),
11
11
  });
12
12
 
13
- export const earningsTool: AgentTool<typeof params, EarningsData | { credentialRequired: unknown }> = {
13
+ export const earningsTool: AgentTool<
14
+ typeof params,
15
+ EarningsData | { credentialRequired: unknown }
16
+ > = {
14
17
  name: "get_earnings",
15
18
  label: "Earnings History",
16
19
  description:
17
20
  "Get quarterly earnings: reported EPS, estimated EPS, and surprise percentage for the last 8 quarters. Requires Alpha Vantage.",
18
21
  parameters: params,
19
- async execute(toolCallId, args) {
22
+ async execute(_toolCallId, args) {
20
23
  return withCredentialCheck("alpha_vantage", async () => {
21
24
  const apiKey = getConfig().alphaVantageApiKey!;
22
- const result = await wrapProvider("alphavantage", () => getEarnings(args.symbol.toUpperCase(), apiKey));
25
+ const result = await wrapProvider("alphavantage", () =>
26
+ getEarnings(args.symbol.toUpperCase(), apiKey),
27
+ );
23
28
  if (result.status === "unavailable") {
24
29
  return {
25
- content: [{ type: "text", text: `⚠ Earnings data unavailable for ${args.symbol.toUpperCase()} (${result.reason}). Analysis will proceed without earnings history.` }],
30
+ content: [
31
+ {
32
+ type: "text",
33
+ text: `⚠ Earnings data unavailable for ${args.symbol.toUpperCase()} (${result.reason}). Analysis will proceed without earnings history.`,
34
+ },
35
+ ],
26
36
  details: null as any,
27
37
  };
28
38
  }
@@ -1,22 +1,25 @@
1
- import { Type } from "@sinclair/typebox";
2
1
  import type { AgentTool } from "@earendil-works/pi-agent-core";
3
- import { getFinancials } from "../../providers/alpha-vantage.js";
4
- import { wrapProvider } from "../../providers/wrap-provider.js";
2
+ import { Type } from "@sinclair/typebox";
5
3
  import { getConfig } from "../../config.js";
6
4
  import { withCredentialCheck } from "../../onboarding/tool-helpers.js";
5
+ import { getFinancials } from "../../providers/alpha-vantage.js";
6
+ import { wrapProvider } from "../../providers/wrap-provider.js";
7
7
  import type { FinancialStatement } from "../../types/fundamentals.js";
8
8
 
9
9
  const params = Type.Object({
10
10
  symbol: Type.String({ description: "Stock ticker symbol (e.g. AAPL, MSFT)" }),
11
11
  });
12
12
 
13
- export const financialsTool: AgentTool<typeof params, FinancialStatement[] | { credentialRequired: unknown }> = {
13
+ export const financialsTool: AgentTool<
14
+ typeof params,
15
+ FinancialStatement[] | { credentialRequired: unknown }
16
+ > = {
14
17
  name: "get_financials",
15
18
  label: "Financial Statements",
16
19
  description:
17
20
  "Get annual income statement data: revenue, gross profit, operating income, net income, and EPS. Requires Alpha Vantage.",
18
21
  parameters: params,
19
- async execute(toolCallId, args) {
22
+ async execute(_toolCallId, args) {
20
23
  return withCredentialCheck("alpha_vantage", async () => {
21
24
  const apiKey = getConfig().alphaVantageApiKey!;
22
25
  const result = await wrapProvider("alphavantage", () =>
@@ -24,7 +27,12 @@ export const financialsTool: AgentTool<typeof params, FinancialStatement[] | { c
24
27
  );
25
28
  if (result.status === "unavailable") {
26
29
  return {
27
- content: [{ type: "text", text: `⚠ Financial statements unavailable for ${args.symbol.toUpperCase()} (${result.reason}). Analysis will proceed without financials.` }],
30
+ content: [
31
+ {
32
+ type: "text",
33
+ text: `⚠ Financial statements unavailable for ${args.symbol.toUpperCase()} (${result.reason}). Analysis will proceed without financials.`,
34
+ },
35
+ ],
28
36
  details: [],
29
37
  };
30
38
  }
@@ -37,8 +45,9 @@ export const financialsTool: AgentTool<typeof params, FinancialStatement[] | { c
37
45
  }
38
46
 
39
47
  const header = `${args.symbol.toUpperCase()} — Annual Income Statement (${statements.length} years)`;
40
- const rows = statements.map((s) =>
41
- `${s.fiscalDate} | Rev: $${fmt(s.revenue)} | GP: $${fmt(s.grossProfit)} | OpInc: $${fmt(s.operatingIncome)} | Net: $${fmt(s.netIncome)}`,
48
+ const rows = statements.map(
49
+ (s) =>
50
+ `${s.fiscalDate} | Rev: $${fmt(s.revenue)} | GP: $${fmt(s.grossProfit)} | OpInc: $${fmt(s.operatingIncome)} | Net: $${fmt(s.netIncome)}`,
42
51
  );
43
52
 
44
53
  const text = [header, ...rows].join("\n");
@@ -1,18 +1,26 @@
1
- import { Type } from "@sinclair/typebox";
2
1
  import type { AgentTool } from "@earendil-works/pi-agent-core";
2
+ import { Type } from "@sinclair/typebox";
3
3
  import { searchFilings } from "../../providers/sec-edgar.js";
4
4
  import { wrapProvider } from "../../providers/wrap-provider.js";
5
+ import { renderUntrustedText, untrustedContentHeader } from "../sentiment/untrusted-text.js";
5
6
 
6
7
  const params = Type.Object({
7
8
  symbol: Type.String({ description: "Stock ticker symbol (e.g. AAPL, MSFT, TSLA)" }),
8
9
  form_types: Type.Optional(
9
10
  Type.Array(Type.String(), {
10
- description: "Filing types to search: 10-K (annual), 10-Q (quarterly), 8-K (material events). Default: all three.",
11
+ description:
12
+ "Filing types to search: 10-K (annual), 10-Q (quarterly), 8-K (material events). Default: all three.",
11
13
  }),
12
14
  ),
13
15
  limit: Type.Optional(
14
16
  Type.Number({ description: "Maximum number of filings to return (default: 10)" }),
15
17
  ),
18
+ include_snippets: Type.Optional(
19
+ Type.Boolean({
20
+ description:
21
+ "Include short filing-text evidence snippets for risk/MD&A/litigation themes. Default: true.",
22
+ }),
23
+ ),
16
24
  });
17
25
 
18
26
  export const secFilingsTool: AgentTool<typeof params> = {
@@ -21,15 +29,20 @@ export const secFilingsTool: AgentTool<typeof params> = {
21
29
  description:
22
30
  "Search SEC EDGAR for company filings (10-K annual reports, 10-Q quarterly reports, 8-K material events). Returns filing dates, types, and direct links to the documents. Free API, no key required.",
23
31
  parameters: params,
24
- async execute(toolCallId, args) {
32
+ async execute(_toolCallId, args) {
25
33
  const symbol = args.symbol.toUpperCase();
26
34
  const formTypes = args.form_types ?? ["10-K", "10-Q", "8-K"];
27
35
  const limit = args.limit ?? 10;
36
+ const includeSnippets = args.include_snippets ?? true;
28
37
 
29
- const result = await wrapProvider("sec-edgar", () => searchFilings(symbol, formTypes, limit));
38
+ const result = await wrapProvider("sec-edgar", () =>
39
+ searchFilings(symbol, formTypes, limit, { includeSnippets, snippetLimitPerFiling: 2 }),
40
+ );
30
41
  if (result.status === "unavailable") {
31
42
  return {
32
- content: [{ type: "text", text: `⚠ SEC filings unavailable for ${symbol} (${result.reason}).` }],
43
+ content: [
44
+ { type: "text", text: `⚠ SEC filings unavailable for ${symbol} (${result.reason}).` },
45
+ ],
33
46
  details: null,
34
47
  };
35
48
  }
@@ -37,7 +50,12 @@ export const secFilingsTool: AgentTool<typeof params> = {
37
50
 
38
51
  if (filings.length === 0) {
39
52
  return {
40
- content: [{ type: "text", text: `No SEC filings found for ${symbol}. Verify the ticker is a US-listed company.` }],
53
+ content: [
54
+ {
55
+ type: "text",
56
+ text: `No SEC filings found for ${symbol}. Verify the ticker is a US-listed company.`,
57
+ },
58
+ ],
41
59
  details: null,
42
60
  };
43
61
  }
@@ -45,12 +63,38 @@ export const secFilingsTool: AgentTool<typeof params> = {
45
63
  const lines = [
46
64
  `**${symbol} SEC Filings** (${filings.length} found)`,
47
65
  ``,
48
- ...filings.map((f) =>
49
- ` ${f.formType.padEnd(6)} | Filed: ${f.filedDate} | Period: ${f.periodOfReport || "N/A"} | ${f.entityName}`
66
+ ...filings.map(
67
+ (f) =>
68
+ ` ${f.formType.padEnd(6)} | Filed: ${f.filedDate} | Period: ${f.periodOfReport || "N/A"} | ${f.entityName}`,
50
69
  ),
51
70
  ``,
52
71
  `Links:`,
53
72
  ...filings.map((f) => ` ${f.formType} (${f.filedDate}): ${f.url}`),
73
+ ``,
74
+ `Primary documents:`,
75
+ ...filings.flatMap((f) => [
76
+ ` ${f.formType} (${f.filedDate}): ${f.primaryDocumentUrl ?? "N/A"}`,
77
+ ...(f.items?.length ? [` 8-K items: ${f.items.join(", ")}`] : []),
78
+ ]),
79
+ ...(includeSnippets
80
+ ? [
81
+ ``,
82
+ `Evidence snippets (short excerpts; review source filing for full context):`,
83
+ untrustedContentHeader("SEC filing snippets"),
84
+ ...filings.flatMap((f) =>
85
+ f.evidenceWarning
86
+ ? [` ${f.formType} ${f.filedDate}: ${f.evidenceWarning}`]
87
+ : f.evidenceSnippets?.length
88
+ ? f.evidenceSnippets.map(
89
+ (snippet) =>
90
+ ` ${f.formType} ${f.filedDate}: ${renderUntrustedText(snippet, 500)}`,
91
+ )
92
+ : [
93
+ ` ${f.formType} ${f.filedDate}: No keyword snippet found in fetched primary document.`,
94
+ ],
95
+ ),
96
+ ]
97
+ : []),
54
98
  ];
55
99
 
56
100
  return {
@@ -1,65 +1,76 @@
1
1
  import type { AgentTool } from "@earendil-works/pi-agent-core";
2
- import { stockQuoteTool } from "./market/stock-quote.js";
3
- import { stockHistoryTool } from "./market/stock-history.js";
4
- import { cryptoPriceTool } from "./market/crypto-price.js";
5
- import { cryptoHistoryTool } from "./market/crypto-history.js";
6
- import { searchTickerTool } from "./market/search-ticker.js";
7
2
  import { companyOverviewTool } from "./fundamentals/company-overview.js";
8
- import { financialsTool } from "./fundamentals/financials.js";
3
+ import { compsTool } from "./fundamentals/comps.js";
4
+ import { dcfTool } from "./fundamentals/dcf.js";
9
5
  import { earningsTool } from "./fundamentals/earnings.js";
10
- import { fredDataTool } from "./macro/fred-data.js";
6
+ import { financialsTool } from "./fundamentals/financials.js";
7
+ import { secFilingsTool } from "./fundamentals/sec-filings.js";
11
8
  import { fearGreedTool } from "./macro/fear-greed.js";
12
- import { redditSentimentTool } from "./sentiment/reddit-sentiment.js";
13
- import { twitterSentimentTool } from "./sentiment/twitter-sentiment.js";
14
- import { technicalIndicatorsTool } from "./technical/indicators.js";
15
- import { portfolioTrackerTool } from "./portfolio/tracker.js";
16
- import { riskAnalysisTool } from "./portfolio/risk-analysis.js";
17
- import { watchlistTool } from "./portfolio/watchlist.js";
18
- import { correlationTool } from "./portfolio/correlation.js";
9
+ import { fredDataTool } from "./macro/fred-data.js";
10
+ import { cryptoHistoryTool } from "./market/crypto-history.js";
11
+ import { cryptoPriceTool } from "./market/crypto-price.js";
12
+ import { screenStocksTool } from "./market/screen-stocks.js";
13
+ import { searchTickerTool } from "./market/search-ticker.js";
14
+ import { stockHistoryTool } from "./market/stock-history.js";
15
+ import { stockQuoteTool } from "./market/stock-quote.js";
19
16
  import { optionChainTool } from "./options/option-chain.js";
20
- import { dcfTool } from "./fundamentals/dcf.js";
21
- import { compsTool } from "./fundamentals/comps.js";
22
- import { secFilingsTool } from "./fundamentals/sec-filings.js";
23
- import { backtestTool } from "./technical/backtest.js";
17
+ import { alertsTool } from "./portfolio/alerts.js";
18
+ import { correlationTool } from "./portfolio/correlation.js";
19
+ import { dailyReportTool } from "./portfolio/daily-report.js";
20
+ import { holdingsOverlapTool } from "./portfolio/holdings-overlap.js";
21
+ import { notificationsTool } from "./portfolio/notifications.js";
24
22
  import { predictionsTool } from "./portfolio/predictions.js";
23
+ import { riskAnalysisTool } from "./portfolio/risk-analysis.js";
24
+ import { portfolioTrackerTool } from "./portfolio/tracker.js";
25
+ import { watchlistTool } from "./portfolio/watchlist.js";
26
+ import { redditSentimentTool } from "./sentiment/reddit-sentiment.js";
27
+ import { sentimentSummaryTool } from "./sentiment/sentiment-summary.js";
28
+ import { sentimentTrendTool } from "./sentiment/sentiment-trend.js";
29
+ import { twitterSentimentTool } from "./sentiment/twitter-sentiment.js";
25
30
  import { webSearchTool } from "./sentiment/web-search.js";
26
31
  import { webSentimentTool } from "./sentiment/web-sentiment.js";
27
- import { sentimentTrendTool } from "./sentiment/sentiment-trend.js";
28
- import { sentimentSummaryTool } from "./sentiment/sentiment-summary.js";
32
+ import { backtestTool } from "./technical/backtest.js";
33
+ import { technicalIndicatorsTool } from "./technical/indicators.js";
29
34
 
30
- export { stockQuoteTool } from "./market/stock-quote.js";
31
- export { stockHistoryTool } from "./market/stock-history.js";
32
- export { cryptoPriceTool } from "./market/crypto-price.js";
33
- export { cryptoHistoryTool } from "./market/crypto-history.js";
34
- export { searchTickerTool } from "./market/search-ticker.js";
35
35
  export { companyOverviewTool } from "./fundamentals/company-overview.js";
36
- export { financialsTool } from "./fundamentals/financials.js";
37
- export { earningsTool } from "./fundamentals/earnings.js";
38
- export { dcfTool } from "./fundamentals/dcf.js";
39
36
  export { compsTool } from "./fundamentals/comps.js";
37
+ export { dcfTool } from "./fundamentals/dcf.js";
38
+ export { earningsTool } from "./fundamentals/earnings.js";
39
+ export { financialsTool } from "./fundamentals/financials.js";
40
40
  export { secFilingsTool } from "./fundamentals/sec-filings.js";
41
- export { fredDataTool } from "./macro/fred-data.js";
42
41
  export { fearGreedTool } from "./macro/fear-greed.js";
42
+ export { fredDataTool } from "./macro/fred-data.js";
43
+ export { cryptoHistoryTool } from "./market/crypto-history.js";
44
+ export { cryptoPriceTool } from "./market/crypto-price.js";
45
+ export { screenStocksTool } from "./market/screen-stocks.js";
46
+ export { searchTickerTool } from "./market/search-ticker.js";
47
+ export { stockHistoryTool } from "./market/stock-history.js";
48
+ export { stockQuoteTool } from "./market/stock-quote.js";
49
+ export { optionChainTool } from "./options/option-chain.js";
50
+ export { alertsTool } from "./portfolio/alerts.js";
51
+ export { correlationTool } from "./portfolio/correlation.js";
52
+ export { dailyReportTool } from "./portfolio/daily-report.js";
53
+ export { holdingsOverlapTool } from "./portfolio/holdings-overlap.js";
54
+ export { notificationsTool } from "./portfolio/notifications.js";
55
+ export { predictionsTool } from "./portfolio/predictions.js";
56
+ export { riskAnalysisTool } from "./portfolio/risk-analysis.js";
57
+ export { portfolioTrackerTool } from "./portfolio/tracker.js";
58
+ export { watchlistTool } from "./portfolio/watchlist.js";
43
59
  export { redditSentimentTool } from "./sentiment/reddit-sentiment.js";
60
+ export { sentimentSummaryTool } from "./sentiment/sentiment-summary.js";
61
+ export { sentimentTrendTool } from "./sentiment/sentiment-trend.js";
44
62
  export { twitterSentimentTool } from "./sentiment/twitter-sentiment.js";
45
63
  export { webSearchTool } from "./sentiment/web-search.js";
46
64
  export { webSentimentTool } from "./sentiment/web-sentiment.js";
47
- export { sentimentTrendTool } from "./sentiment/sentiment-trend.js";
48
- export { sentimentSummaryTool } from "./sentiment/sentiment-summary.js";
49
- export { technicalIndicatorsTool } from "./technical/indicators.js";
50
65
  export { backtestTool } from "./technical/backtest.js";
51
- export { portfolioTrackerTool } from "./portfolio/tracker.js";
52
- export { riskAnalysisTool } from "./portfolio/risk-analysis.js";
53
- export { watchlistTool } from "./portfolio/watchlist.js";
54
- export { correlationTool } from "./portfolio/correlation.js";
55
- export { predictionsTool } from "./portfolio/predictions.js";
56
- export { optionChainTool } from "./options/option-chain.js";
66
+ export { technicalIndicatorsTool } from "./technical/indicators.js";
57
67
 
58
68
  export function getAllTools(): AgentTool<any>[] {
59
69
  return [
60
70
  searchTickerTool,
61
71
  stockQuoteTool,
62
72
  stockHistoryTool,
73
+ screenStocksTool,
63
74
  cryptoPriceTool,
64
75
  cryptoHistoryTool,
65
76
  companyOverviewTool,
@@ -78,7 +89,11 @@ export function getAllTools(): AgentTool<any>[] {
78
89
  riskAnalysisTool,
79
90
  watchlistTool,
80
91
  correlationTool,
92
+ holdingsOverlapTool,
81
93
  predictionsTool,
94
+ alertsTool,
95
+ dailyReportTool,
96
+ notificationsTool,
82
97
  optionChainTool,
83
98
  webSearchTool,
84
99
  webSentimentTool,