opencandle 0.3.0 → 0.4.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 (283) hide show
  1. package/assets/logo.svg +187 -0
  2. package/dist/cli.d.ts +1 -1
  3. package/dist/cli.js +38 -2
  4. package/dist/cli.js.map +1 -1
  5. package/dist/config.d.ts +9 -0
  6. package/dist/config.js +13 -0
  7. package/dist/config.js.map +1 -1
  8. package/dist/infra/browser.d.ts +10 -0
  9. package/dist/infra/browser.js +1 -0
  10. package/dist/infra/browser.js.map +1 -1
  11. package/dist/infra/native-dependencies.d.ts +1 -0
  12. package/dist/infra/native-dependencies.js +10 -0
  13. package/dist/infra/native-dependencies.js.map +1 -0
  14. package/dist/infra/node-version.d.ts +2 -0
  15. package/dist/infra/node-version.js +23 -0
  16. package/dist/infra/node-version.js.map +1 -0
  17. package/dist/memory/index.d.ts +2 -0
  18. package/dist/memory/index.js +1 -0
  19. package/dist/memory/index.js.map +1 -1
  20. package/dist/memory/sqlite.js +42 -4
  21. package/dist/memory/sqlite.js.map +1 -1
  22. package/dist/memory/storage.d.ts +6 -0
  23. package/dist/memory/storage.js +3 -3
  24. package/dist/memory/storage.js.map +1 -1
  25. package/dist/memory/tool-defaults.d.ts +8 -0
  26. package/dist/memory/tool-defaults.js +59 -0
  27. package/dist/memory/tool-defaults.js.map +1 -0
  28. package/dist/onboarding/connect.d.ts +13 -1
  29. package/dist/onboarding/connect.js +21 -10
  30. package/dist/onboarding/connect.js.map +1 -1
  31. package/dist/onboarding/prompt-user.d.ts +1 -1
  32. package/dist/onboarding/providers.d.ts +7 -0
  33. package/dist/onboarding/providers.js +6 -3
  34. package/dist/onboarding/providers.js.map +1 -1
  35. package/dist/onboarding/tool-helpers.d.ts +1 -1
  36. package/dist/pi/opencandle-extension.d.ts +7 -1
  37. package/dist/pi/opencandle-extension.js +186 -10
  38. package/dist/pi/opencandle-extension.js.map +1 -1
  39. package/dist/pi/session-storage.d.ts +2 -0
  40. package/dist/pi/session-storage.js +5 -0
  41. package/dist/pi/session-storage.js.map +1 -0
  42. package/dist/pi/session.d.ts +4 -1
  43. package/dist/pi/session.js +25 -3
  44. package/dist/pi/session.js.map +1 -1
  45. package/dist/pi/setup.d.ts +1 -1
  46. package/dist/pi/setup.js +1 -1
  47. package/dist/pi/setup.js.map +1 -1
  48. package/dist/pi/tool-adapter.d.ts +2 -2
  49. package/dist/pi/tool-adapter.js +14 -1
  50. package/dist/pi/tool-adapter.js.map +1 -1
  51. package/dist/prompts/context-builder.d.ts +22 -0
  52. package/dist/prompts/context-builder.js +45 -10
  53. package/dist/prompts/context-builder.js.map +1 -1
  54. package/dist/prompts/disclaimer.d.ts +6 -0
  55. package/dist/prompts/disclaimer.js +9 -0
  56. package/dist/prompts/disclaimer.js.map +1 -0
  57. package/dist/prompts/workflow-prompts.d.ts +8 -0
  58. package/dist/prompts/workflow-prompts.js +39 -5
  59. package/dist/prompts/workflow-prompts.js.map +1 -1
  60. package/dist/providers/yahoo-finance.js +70 -33
  61. package/dist/providers/yahoo-finance.js.map +1 -1
  62. package/dist/routing/defaults.js +1 -1
  63. package/dist/routing/defaults.js.map +1 -1
  64. package/dist/routing/index.d.ts +4 -0
  65. package/dist/routing/index.js +3 -0
  66. package/dist/routing/index.js.map +1 -1
  67. package/dist/routing/router-llm-client.d.ts +11 -0
  68. package/dist/routing/router-llm-client.js +42 -0
  69. package/dist/routing/router-llm-client.js.map +1 -0
  70. package/dist/routing/router-prompt.d.ts +2 -0
  71. package/dist/routing/router-prompt.js +138 -0
  72. package/dist/routing/router-prompt.js.map +1 -0
  73. package/dist/routing/router-types.d.ts +62 -0
  74. package/dist/routing/router-types.js +2 -0
  75. package/dist/routing/router-types.js.map +1 -0
  76. package/dist/routing/router.d.ts +10 -0
  77. package/dist/routing/router.js +194 -0
  78. package/dist/routing/router.js.map +1 -0
  79. package/dist/runtime/session-coordinator.d.ts +63 -3
  80. package/dist/runtime/session-coordinator.js +155 -4
  81. package/dist/runtime/session-coordinator.js.map +1 -1
  82. package/dist/runtime/tool-defaults-wrapper.d.ts +3 -0
  83. package/dist/runtime/tool-defaults-wrapper.js +25 -0
  84. package/dist/runtime/tool-defaults-wrapper.js.map +1 -0
  85. package/dist/sentiment/store.js +5 -0
  86. package/dist/sentiment/store.js.map +1 -1
  87. package/dist/system-prompt.js +20 -12
  88. package/dist/system-prompt.js.map +1 -1
  89. package/dist/tool-kit.d.ts +4 -4
  90. package/dist/tools/fundamentals/company-overview.d.ts +1 -1
  91. package/dist/tools/fundamentals/comps.d.ts +1 -1
  92. package/dist/tools/fundamentals/dcf.d.ts +1 -1
  93. package/dist/tools/fundamentals/earnings.d.ts +1 -1
  94. package/dist/tools/fundamentals/financials.d.ts +1 -1
  95. package/dist/tools/fundamentals/sec-filings.d.ts +1 -1
  96. package/dist/tools/index.d.ts +28 -1
  97. package/dist/tools/index.js +27 -0
  98. package/dist/tools/index.js.map +1 -1
  99. package/dist/tools/interaction/ask-user.d.ts +1 -1
  100. package/dist/tools/interaction/twitter-login.d.ts +1 -1
  101. package/dist/tools/macro/fear-greed.d.ts +1 -1
  102. package/dist/tools/macro/fred-data.d.ts +1 -1
  103. package/dist/tools/market/crypto-history.d.ts +1 -1
  104. package/dist/tools/market/crypto-price.d.ts +1 -1
  105. package/dist/tools/market/search-ticker.d.ts +1 -1
  106. package/dist/tools/market/stock-history.d.ts +1 -1
  107. package/dist/tools/market/stock-quote.d.ts +1 -1
  108. package/dist/tools/options/option-chain.d.ts +1 -1
  109. package/dist/tools/options/option-chain.js +4 -1
  110. package/dist/tools/options/option-chain.js.map +1 -1
  111. package/dist/tools/portfolio/correlation.d.ts +1 -1
  112. package/dist/tools/portfolio/predictions.d.ts +1 -1
  113. package/dist/tools/portfolio/risk-analysis.d.ts +1 -1
  114. package/dist/tools/portfolio/tracker.d.ts +1 -1
  115. package/dist/tools/portfolio/watchlist.d.ts +1 -1
  116. package/dist/tools/sentiment/reddit-sentiment.d.ts +1 -1
  117. package/dist/tools/sentiment/sentiment-summary.d.ts +1 -1
  118. package/dist/tools/sentiment/sentiment-trend.d.ts +1 -1
  119. package/dist/tools/sentiment/twitter-sentiment.d.ts +1 -1
  120. package/dist/tools/sentiment/web-search.d.ts +1 -1
  121. package/dist/tools/sentiment/web-sentiment.d.ts +1 -1
  122. package/dist/tools/technical/backtest.d.ts +1 -1
  123. package/dist/tools/technical/indicators.d.ts +1 -1
  124. package/dist/tools/technical/indicators.js +7 -1
  125. package/dist/tools/technical/indicators.js.map +1 -1
  126. package/dist/workflows/options-screener.js +7 -2
  127. package/dist/workflows/options-screener.js.map +1 -1
  128. package/dist/workflows/portfolio-builder.js +3 -3
  129. package/dist/workflows/portfolio-builder.js.map +1 -1
  130. package/gui/server/background-quotes.ts +31 -0
  131. package/gui/server/chat-event-adapter.ts +142 -0
  132. package/gui/server/invoke-tool.ts +89 -0
  133. package/gui/server/live-chat-event-adapter.ts +181 -0
  134. package/gui/server/model-setup.ts +100 -0
  135. package/gui/server/package.json +5 -0
  136. package/gui/server/projector.ts +212 -0
  137. package/gui/server/server.ts +592 -0
  138. package/gui/server/session-actions.ts +31 -0
  139. package/gui/server/tool-metadata.ts +88 -0
  140. package/gui/server/websocket.ts +128 -0
  141. package/gui/server/writer-lock.ts +118 -0
  142. package/gui/shared/chat-events.ts +118 -0
  143. package/gui/shared/event-reducer.ts +186 -0
  144. package/gui/web/dist/assets/CatalogOverlay-D1ImSJTe.js +1 -0
  145. package/gui/web/dist/assets/index-DBrWq43L.css +1 -0
  146. package/gui/web/dist/assets/index-RflHaj0y.js +67 -0
  147. package/gui/web/dist/assets/logo-CWpt6Y2a.svg +187 -0
  148. package/gui/web/dist/index.html +17 -0
  149. package/package.json +44 -18
  150. package/src/analysts/contracts.ts +189 -0
  151. package/src/analysts/orchestrator.ts +300 -0
  152. package/src/cli.ts +205 -0
  153. package/src/config.ts +161 -0
  154. package/src/index.ts +5 -0
  155. package/src/infra/browser.ts +111 -0
  156. package/src/infra/cache.ts +103 -0
  157. package/src/infra/http-client.ts +68 -0
  158. package/src/infra/index.ts +18 -0
  159. package/src/infra/native-dependencies.ts +12 -0
  160. package/src/infra/node-version.ts +24 -0
  161. package/src/infra/open-url.ts +28 -0
  162. package/src/infra/opencandle-paths.ts +64 -0
  163. package/src/infra/rate-limiter.ts +64 -0
  164. package/src/memory/index.ts +10 -0
  165. package/src/memory/manager.ts +159 -0
  166. package/src/memory/preference-extractor.ts +106 -0
  167. package/src/memory/retrieval.ts +70 -0
  168. package/src/memory/sqlite.ts +172 -0
  169. package/src/memory/storage.ts +204 -0
  170. package/src/memory/tool-defaults.ts +87 -0
  171. package/src/memory/types.ts +67 -0
  172. package/src/onboarding/connect.ts +184 -0
  173. package/src/onboarding/credential-interceptor.ts +134 -0
  174. package/src/onboarding/degradation-accumulator.ts +79 -0
  175. package/src/onboarding/prompt-user.ts +85 -0
  176. package/src/onboarding/providers.ts +315 -0
  177. package/src/onboarding/state.ts +218 -0
  178. package/src/onboarding/tool-helpers.ts +111 -0
  179. package/src/onboarding/tool-tags.ts +201 -0
  180. package/src/onboarding/validation.ts +158 -0
  181. package/src/pi/opencandle-extension.ts +724 -0
  182. package/src/pi/session-storage.ts +5 -0
  183. package/src/pi/session.ts +81 -0
  184. package/src/pi/setup.ts +371 -0
  185. package/src/pi/tool-adapter.ts +36 -0
  186. package/src/prompts/context-builder.ts +204 -0
  187. package/src/prompts/disclaimer.ts +9 -0
  188. package/src/prompts/sections.ts +46 -0
  189. package/src/prompts/workflow-prompts.ts +279 -0
  190. package/src/providers/alpha-vantage.ts +292 -0
  191. package/src/providers/coingecko.ts +96 -0
  192. package/src/providers/exa-search.ts +373 -0
  193. package/src/providers/fear-greed.ts +45 -0
  194. package/src/providers/finnhub.ts +124 -0
  195. package/src/providers/fred.ts +83 -0
  196. package/src/providers/index.ts +9 -0
  197. package/src/providers/provider-credential-error.ts +23 -0
  198. package/src/providers/reddit.ts +151 -0
  199. package/src/providers/sec-edgar.ts +96 -0
  200. package/src/providers/twitter.ts +173 -0
  201. package/src/providers/web-search.ts +293 -0
  202. package/src/providers/with-fallback.ts +41 -0
  203. package/src/providers/wrap-provider.ts +64 -0
  204. package/src/providers/yahoo-finance.ts +367 -0
  205. package/src/routing/classify-intent.ts +194 -0
  206. package/src/routing/defaults.ts +29 -0
  207. package/src/routing/entity-extractor.ts +140 -0
  208. package/src/routing/index.ts +26 -0
  209. package/src/routing/router-llm-client.ts +51 -0
  210. package/src/routing/router-prompt.ts +159 -0
  211. package/src/routing/router-types.ts +66 -0
  212. package/src/routing/router.ts +213 -0
  213. package/src/routing/slot-resolver.ts +152 -0
  214. package/src/routing/types.ts +63 -0
  215. package/src/runtime/evidence.ts +77 -0
  216. package/src/runtime/index.ts +55 -0
  217. package/src/runtime/prompt-step.ts +75 -0
  218. package/src/runtime/provider-ids.ts +15 -0
  219. package/src/runtime/provider-tracker.ts +40 -0
  220. package/src/runtime/run-context.ts +22 -0
  221. package/src/runtime/session-coordinator.ts +406 -0
  222. package/src/runtime/tool-defaults-wrapper.ts +35 -0
  223. package/src/runtime/validation.ts +214 -0
  224. package/src/runtime/workflow-events.ts +75 -0
  225. package/src/runtime/workflow-runner.ts +188 -0
  226. package/src/runtime/workflow-types.ts +102 -0
  227. package/src/sentiment/adapters/finnhub.ts +44 -0
  228. package/src/sentiment/adapters/reddit.ts +65 -0
  229. package/src/sentiment/adapters/twitter.ts +36 -0
  230. package/src/sentiment/adapters/web.ts +44 -0
  231. package/src/sentiment/index.ts +58 -0
  232. package/src/sentiment/keywords.ts +9 -0
  233. package/src/sentiment/pipeline.ts +68 -0
  234. package/src/sentiment/scorer.ts +78 -0
  235. package/src/sentiment/store.ts +260 -0
  236. package/src/sentiment/trends.ts +90 -0
  237. package/src/sentiment/types.ts +108 -0
  238. package/src/system-prompt.ts +115 -0
  239. package/src/tool-kit.ts +68 -0
  240. package/src/tools/AGENTS.md +36 -0
  241. package/src/tools/fundamentals/company-overview.ts +54 -0
  242. package/src/tools/fundamentals/comps.ts +156 -0
  243. package/src/tools/fundamentals/dcf.ts +267 -0
  244. package/src/tools/fundamentals/earnings.ts +47 -0
  245. package/src/tools/fundamentals/financials.ts +54 -0
  246. package/src/tools/fundamentals/sec-filings.ts +61 -0
  247. package/src/tools/index.ts +88 -0
  248. package/src/tools/interaction/ask-user.ts +81 -0
  249. package/src/tools/interaction/twitter-login.ts +93 -0
  250. package/src/tools/macro/fear-greed.ts +41 -0
  251. package/src/tools/macro/fred-data.ts +54 -0
  252. package/src/tools/market/crypto-history.ts +51 -0
  253. package/src/tools/market/crypto-price.ts +53 -0
  254. package/src/tools/market/search-ticker.ts +53 -0
  255. package/src/tools/market/stock-history.ts +79 -0
  256. package/src/tools/market/stock-quote.ts +64 -0
  257. package/src/tools/options/greeks.ts +82 -0
  258. package/src/tools/options/option-chain.ts +91 -0
  259. package/src/tools/portfolio/correlation.ts +162 -0
  260. package/src/tools/portfolio/predictions.ts +253 -0
  261. package/src/tools/portfolio/risk-analysis.ts +134 -0
  262. package/src/tools/portfolio/tracker.ts +147 -0
  263. package/src/tools/portfolio/watchlist.ts +153 -0
  264. package/src/tools/sentiment/reddit-sentiment.ts +164 -0
  265. package/src/tools/sentiment/sentiment-summary.ts +256 -0
  266. package/src/tools/sentiment/sentiment-trend.ts +58 -0
  267. package/src/tools/sentiment/twitter-sentiment.ts +96 -0
  268. package/src/tools/sentiment/web-search.ts +150 -0
  269. package/src/tools/sentiment/web-sentiment.ts +76 -0
  270. package/src/tools/technical/backtest.ts +246 -0
  271. package/src/tools/technical/indicators.ts +258 -0
  272. package/src/types/fundamentals.ts +46 -0
  273. package/src/types/index.ts +20 -0
  274. package/src/types/macro.ts +27 -0
  275. package/src/types/market.ts +43 -0
  276. package/src/types/options.ts +35 -0
  277. package/src/types/portfolio.ts +41 -0
  278. package/src/types/sentiment.ts +70 -0
  279. package/src/workflows/compare-assets.ts +39 -0
  280. package/src/workflows/index.ts +4 -0
  281. package/src/workflows/options-screener.ts +49 -0
  282. package/src/workflows/portfolio-builder.ts +52 -0
  283. package/src/workflows/types.ts +4 -0
@@ -0,0 +1,152 @@
1
+ import type {
2
+ ExtractedEntities,
3
+ PortfolioSlots,
4
+ OptionsScreenerSlots,
5
+ SlotResolution,
6
+ SlotSource,
7
+ } from "./types.js";
8
+ import { PORTFOLIO_DEFAULTS, OPTIONS_SCREENER_DEFAULTS } from "./defaults.js";
9
+
10
+ interface Preferences {
11
+ riskProfile?: string;
12
+ timeHorizon?: string;
13
+ assetScope?: string;
14
+ positionCount?: number;
15
+ maxSinglePositionPct?: number;
16
+ dteTarget?: string;
17
+ objective?: string;
18
+ moneynessPreference?: string;
19
+ liquidityMinimum?: string;
20
+ }
21
+
22
+ function mapDteHintToTarget(dteHint: string | undefined): string | undefined {
23
+ switch (dteHint) {
24
+ case "week":
25
+ return "7_to_14_days";
26
+ case "month":
27
+ return "25_to_45_days";
28
+ case "leaps":
29
+ return "180_plus_days";
30
+ default:
31
+ return undefined;
32
+ }
33
+ }
34
+
35
+ function resolve<T>(
36
+ userValue: T | undefined,
37
+ prefValue: T | undefined,
38
+ defaultValue: T,
39
+ ): { value: T; source: SlotSource } {
40
+ if (userValue !== undefined) return { value: userValue, source: "user" };
41
+ if (prefValue !== undefined) return { value: prefValue, source: "preference" };
42
+ return { value: defaultValue, source: "default" };
43
+ }
44
+
45
+ export function resolvePortfolioSlots(
46
+ entities: ExtractedEntities,
47
+ preferences: Preferences = {},
48
+ ): SlotResolution<PortfolioSlots> {
49
+ const sources = {} as Record<keyof PortfolioSlots, SlotSource>;
50
+ const defaultsUsed: string[] = [];
51
+ const missingRequired: string[] = [];
52
+
53
+ // Budget: required, no default
54
+ let budget = 0;
55
+ if (entities.budget !== undefined) {
56
+ budget = entities.budget;
57
+ sources.budget = "user";
58
+ } else {
59
+ missingRequired.push("budget");
60
+ sources.budget = "default";
61
+ }
62
+
63
+ const risk = resolve(entities.riskProfile, preferences.riskProfile, PORTFOLIO_DEFAULTS.riskProfile);
64
+ sources.riskProfile = risk.source;
65
+ if (risk.source === "default") defaultsUsed.push("riskProfile");
66
+
67
+ const horizon = resolve(entities.timeHorizon, preferences.timeHorizon, PORTFOLIO_DEFAULTS.timeHorizon);
68
+ sources.timeHorizon = horizon.source;
69
+ if (horizon.source === "default") defaultsUsed.push("timeHorizon");
70
+
71
+ const scope = resolve(undefined, preferences.assetScope, PORTFOLIO_DEFAULTS.assetScope);
72
+ sources.assetScope = scope.source;
73
+ if (scope.source === "default") defaultsUsed.push("assetScope");
74
+
75
+ const count = resolve(undefined, preferences.positionCount, PORTFOLIO_DEFAULTS.positionCount);
76
+ sources.positionCount = count.source;
77
+ if (count.source === "default") defaultsUsed.push("positionCount");
78
+
79
+ const maxPct = resolve(undefined, preferences.maxSinglePositionPct, PORTFOLIO_DEFAULTS.maxSinglePositionPct);
80
+ sources.maxSinglePositionPct = maxPct.source;
81
+ if (maxPct.source === "default") defaultsUsed.push("maxSinglePositionPct");
82
+
83
+ return {
84
+ resolved: {
85
+ budget,
86
+ riskProfile: risk.value,
87
+ timeHorizon: horizon.value,
88
+ assetScope: scope.value,
89
+ positionCount: count.value,
90
+ maxSinglePositionPct: maxPct.value,
91
+ },
92
+ sources,
93
+ defaultsUsed,
94
+ missingRequired,
95
+ };
96
+ }
97
+
98
+ export function resolveOptionsScreenerSlots(
99
+ entities: ExtractedEntities,
100
+ preferences: Preferences = {},
101
+ ): SlotResolution<OptionsScreenerSlots> {
102
+ const sources = {} as Record<keyof OptionsScreenerSlots, SlotSource>;
103
+ const defaultsUsed: string[] = [];
104
+ const missingRequired: string[] = [];
105
+
106
+ // Symbol: required, no default
107
+ let symbol = "";
108
+ if (entities.symbols.length > 0) {
109
+ symbol = entities.symbols[0];
110
+ sources.symbol = "user";
111
+ } else {
112
+ missingRequired.push("symbol");
113
+ sources.symbol = "default";
114
+ }
115
+
116
+ // Direction: default to bullish
117
+ const dir = resolve(entities.direction, undefined, "bullish" as const);
118
+ sources.direction = dir.source;
119
+ if (dir.source === "default") defaultsUsed.push("direction");
120
+
121
+ const dte = resolve(mapDteHintToTarget(entities.dteHint), preferences.dteTarget, OPTIONS_SCREENER_DEFAULTS.dteTarget);
122
+ sources.dteTarget = dte.source;
123
+ if (dte.source === "default") defaultsUsed.push("dteTarget");
124
+
125
+ const obj = resolve(undefined, preferences.objective, OPTIONS_SCREENER_DEFAULTS.objective);
126
+ sources.objective = obj.source;
127
+ if (obj.source === "default") defaultsUsed.push("objective");
128
+
129
+ const moneyness = resolve(undefined, preferences.moneynessPreference, OPTIONS_SCREENER_DEFAULTS.moneynessPreference);
130
+ sources.moneynessPreference = moneyness.source;
131
+ if (moneyness.source === "default") defaultsUsed.push("moneynessPreference");
132
+
133
+ const liquidity = resolve(undefined, preferences.liquidityMinimum, OPTIONS_SCREENER_DEFAULTS.liquidityMinimum);
134
+ sources.liquidityMinimum = liquidity.source;
135
+ if (liquidity.source === "default") defaultsUsed.push("liquidityMinimum");
136
+
137
+ return {
138
+ resolved: {
139
+ symbol,
140
+ direction: dir.value,
141
+ dteTarget: dte.value,
142
+ objective: obj.value,
143
+ moneynessPreference: moneyness.value,
144
+ liquidityMinimum: liquidity.value,
145
+ budget: entities.budget,
146
+ maxPremium: entities.maxPremium,
147
+ },
148
+ sources,
149
+ defaultsUsed,
150
+ missingRequired,
151
+ };
152
+ }
@@ -0,0 +1,63 @@
1
+ export type WorkflowType =
2
+ | "single_asset_analysis"
3
+ | "portfolio_builder"
4
+ | "options_screener"
5
+ | "compare_assets"
6
+ | "watchlist_or_tracking"
7
+ | "general_finance_qa"
8
+ | "unclassified";
9
+
10
+ export interface ExtractedEntities {
11
+ symbols: string[];
12
+ budget?: number;
13
+ maxPremium?: number;
14
+ timeHorizon?: string;
15
+ riskProfile?: string;
16
+ direction?: "bullish" | "bearish";
17
+ dteHint?: string;
18
+ }
19
+
20
+ export interface ClassificationResult {
21
+ workflow: WorkflowType;
22
+ confidence: number;
23
+ tier: "rule" | "llm";
24
+ entities: ExtractedEntities;
25
+ }
26
+
27
+ export interface PortfolioSlots {
28
+ budget: number;
29
+ riskProfile: string;
30
+ timeHorizon: string;
31
+ assetScope: string;
32
+ positionCount: number;
33
+ maxSinglePositionPct: number;
34
+ excludeSectors?: string[];
35
+ incomeVsGrowth?: string;
36
+ accountType?: string;
37
+ }
38
+
39
+ export interface OptionsScreenerSlots {
40
+ symbol: string;
41
+ direction: "bullish" | "bearish";
42
+ dteTarget: string;
43
+ objective: string;
44
+ moneynessPreference: string;
45
+ liquidityMinimum: string;
46
+ budget?: number;
47
+ maxPremium?: number;
48
+ ivPreference?: string;
49
+ }
50
+
51
+ export interface CompareAssetsSlots {
52
+ symbols: string[];
53
+ metrics?: string[];
54
+ }
55
+
56
+ export type SlotSource = "user" | "preference" | "default";
57
+
58
+ export interface SlotResolution<T> {
59
+ resolved: T;
60
+ sources: { [K in keyof T]?: SlotSource };
61
+ defaultsUsed: string[];
62
+ missingRequired: string[];
63
+ }
@@ -0,0 +1,77 @@
1
+ /** Source of a value flowing through the runtime. */
2
+ export type ProvenanceSource =
3
+ | "user"
4
+ | "preference"
5
+ | "default"
6
+ | "fetched"
7
+ | "computed"
8
+ | "unavailable"
9
+ | "stale_cache";
10
+
11
+ /** Tracks where a value came from, when, and with what confidence. */
12
+ export interface Provenance {
13
+ source: ProvenanceSource;
14
+ timestamp?: string;
15
+ provider?: string;
16
+ confidence?: number;
17
+ reason?: string;
18
+ }
19
+
20
+ /** A labeled data point with its provenance. */
21
+ export interface EvidenceRecord {
22
+ label: string;
23
+ value: unknown;
24
+ provenance: Provenance;
25
+ }
26
+
27
+ /** Successful provider result. */
28
+ export interface ProviderResultOk<T> {
29
+ status: "ok";
30
+ data: T;
31
+ timestamp: string;
32
+ stale?: boolean;
33
+ }
34
+
35
+ /** Failed/unavailable provider result. */
36
+ export interface ProviderResultUnavailable {
37
+ status: "unavailable";
38
+ reason: string;
39
+ provider: string;
40
+ }
41
+
42
+ /** Union of provider outcomes — every provider call returns one of these. */
43
+ export type ProviderResult<T> = ProviderResultOk<T> | ProviderResultUnavailable;
44
+
45
+ /** Type guard for successful provider results. */
46
+ export function isProviderOk<T>(result: ProviderResult<T>): result is ProviderResultOk<T> {
47
+ return result.status === "ok";
48
+ }
49
+
50
+ /** Convert a ProviderResult into an EvidenceRecord. */
51
+ export function toEvidenceRecord<T>(
52
+ label: string,
53
+ result: ProviderResult<T>,
54
+ providerId?: string,
55
+ ): EvidenceRecord {
56
+ if (isProviderOk(result)) {
57
+ return {
58
+ label,
59
+ value: result.data,
60
+ provenance: {
61
+ source: result.stale ? "stale_cache" : "fetched",
62
+ timestamp: result.timestamp,
63
+ provider: providerId,
64
+ confidence: result.stale ? 0.5 : undefined,
65
+ },
66
+ };
67
+ }
68
+ return {
69
+ label,
70
+ value: null,
71
+ provenance: {
72
+ source: "unavailable",
73
+ reason: result.reason,
74
+ provider: result.provider,
75
+ },
76
+ };
77
+ }
@@ -0,0 +1,55 @@
1
+ export type {
2
+ Provenance,
3
+ ProvenanceSource,
4
+ EvidenceRecord,
5
+ ProviderResult,
6
+ ProviderResultOk,
7
+ ProviderResultUnavailable,
8
+ } from "./evidence.js";
9
+ export { isProviderOk, toEvidenceRecord } from "./evidence.js";
10
+
11
+ export type {
12
+ StepStatus,
13
+ RunStatus,
14
+ WorkflowStep,
15
+ StepOutput,
16
+ AnalystSignal,
17
+ AnalystOutput,
18
+ WorkflowRun,
19
+ } from "./workflow-types.js";
20
+ export {
21
+ isValidStepTransition,
22
+ transitionStepStatus,
23
+ createWorkflowRun,
24
+ } from "./workflow-types.js";
25
+
26
+ export type {
27
+ ValidationEntry,
28
+ ValidationResult,
29
+ ValidatorConfig,
30
+ } from "./validation.js";
31
+ export {
32
+ emptyValidationResult,
33
+ checkTimestamps,
34
+ checkOptionsExpiries,
35
+ checkRequiredFields,
36
+ checkNumberMatch,
37
+ RuntimeValidator,
38
+ DEFAULT_MARKET_SENSITIVE_LABELS,
39
+ } from "./validation.js";
40
+
41
+ export type { WorkflowEventType, WorkflowEvent } from "./workflow-events.js";
42
+ export { WorkflowEventLogger } from "./workflow-events.js";
43
+
44
+ export { ProviderTracker } from "./provider-tracker.js";
45
+
46
+ export type { ProviderId } from "./provider-ids.js";
47
+ export { PROVIDER_ID } from "./provider-ids.js";
48
+
49
+ export { setRunContext, clearRunContext, getProviderTracker } from "./run-context.js";
50
+
51
+ export type { StepExecutor, StepExecutionContext, WorkflowRunnerOptions } from "./workflow-runner.js";
52
+ export { WorkflowRunner } from "./workflow-runner.js";
53
+
54
+ export type { PromptStep, WorkflowDefinition } from "./prompt-step.js";
55
+ export { promptStep, promptStepOutput, toStepDefinitions, toWorkflowPlan } from "./prompt-step.js";
@@ -0,0 +1,75 @@
1
+ import type { WorkflowStep, StepOutput } from "./workflow-types.js";
2
+
3
+ /**
4
+ * A workflow step definition that carries its prompt text.
5
+ * In Pi's model, each step is a prompt sent to the LLM.
6
+ */
7
+ export interface PromptStep extends Omit<WorkflowStep, "status"> {
8
+ prompt: string;
9
+ }
10
+
11
+ /**
12
+ * A complete workflow definition: typed step metadata + prompt text for each step.
13
+ * Replaces the old WorkflowPlan { initialPrompt, followUps }.
14
+ */
15
+ export interface WorkflowDefinition {
16
+ workflowType: string;
17
+ steps: PromptStep[];
18
+ }
19
+
20
+ /**
21
+ * Create a prompt-based step definition.
22
+ */
23
+ export function promptStep(
24
+ stepType: string,
25
+ description: string,
26
+ prompt: string,
27
+ options: {
28
+ skippable?: boolean;
29
+ requiredInputs?: string[];
30
+ expectedOutputs?: string[];
31
+ } = {},
32
+ ): PromptStep {
33
+ return {
34
+ stepType,
35
+ description,
36
+ prompt,
37
+ skippable: options.skippable ?? false,
38
+ requiredInputs: options.requiredInputs ?? [],
39
+ expectedOutputs: options.expectedOutputs ?? [],
40
+ };
41
+ }
42
+
43
+ /**
44
+ * Create a StepOutput for a prompt-based step (no structured evidence yet).
45
+ * Evidence will be captured separately via tool call hooks.
46
+ */
47
+ export function promptStepOutput(stepIndex: number, stepType: string): StepOutput {
48
+ return {
49
+ stepIndex,
50
+ stepType,
51
+ evidence: [],
52
+ };
53
+ }
54
+
55
+ /**
56
+ * Extract just the WorkflowStep metadata from PromptStep definitions
57
+ * (dropping the prompt field) for passing to WorkflowRunner.
58
+ */
59
+ export function toStepDefinitions(steps: PromptStep[]): Omit<WorkflowStep, "status">[] {
60
+ return steps.map(({ prompt: _prompt, ...step }) => step);
61
+ }
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
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Canonical provider IDs. These match the keys used in
3
+ * src/infra/rate-limiter.ts for providers that have rate limits.
4
+ */
5
+ export const PROVIDER_ID = {
6
+ YAHOO: "yahoo",
7
+ ALPHA_VANTAGE: "alphavantage",
8
+ COINGECKO: "coingecko",
9
+ FRED: "fred",
10
+ SEC_EDGAR: "sec-edgar",
11
+ REDDIT: "reddit",
12
+ FEAR_GREED: "feargreed",
13
+ } as const;
14
+
15
+ export type ProviderId = (typeof PROVIDER_ID)[keyof typeof PROVIDER_ID];
@@ -0,0 +1,40 @@
1
+ import type { ProviderResult } from "./evidence.js";
2
+
3
+ /**
4
+ * Tracks provider failures within a workflow run and short-circuits
5
+ * calls to providers that have exceeded the failure threshold.
6
+ */
7
+ export class ProviderTracker {
8
+ private readonly failures = new Map<string, number>();
9
+
10
+ constructor(private readonly maxFailures: number = 2) {}
11
+
12
+ /** Record a failure for a provider. */
13
+ recordFailure(provider: string): void {
14
+ this.failures.set(provider, (this.failures.get(provider) ?? 0) + 1);
15
+ }
16
+
17
+ /** Check whether a provider's circuit is open (too many failures). */
18
+ isCircuitOpen(provider: string): boolean {
19
+ return (this.failures.get(provider) ?? 0) >= this.maxFailures;
20
+ }
21
+
22
+ /** Get a short-circuit unavailable result for a provider. */
23
+ shortCircuit<T>(provider: string): ProviderResult<T> {
24
+ return {
25
+ status: "unavailable",
26
+ reason: "provider_circuit_open",
27
+ provider,
28
+ };
29
+ }
30
+
31
+ /** Reset failure count for a provider. */
32
+ reset(provider: string): void {
33
+ this.failures.delete(provider);
34
+ }
35
+
36
+ /** Reset all tracked failures. */
37
+ resetAll(): void {
38
+ this.failures.clear();
39
+ }
40
+ }
@@ -0,0 +1,22 @@
1
+ import type { ProviderTracker } from "./provider-tracker.js";
2
+
3
+ interface RunContext {
4
+ providerTracker: ProviderTracker;
5
+ }
6
+
7
+ let activeContext: RunContext | null = null;
8
+
9
+ /** Set the active run context. Called by SessionCoordinator at workflow start. */
10
+ export function setRunContext(ctx: RunContext): void {
11
+ activeContext = ctx;
12
+ }
13
+
14
+ /** Clear the active run context. Called when a workflow ends or is cancelled. */
15
+ export function clearRunContext(): void {
16
+ activeContext = null;
17
+ }
18
+
19
+ /** Get the current run's ProviderTracker, or undefined outside a workflow. */
20
+ export function getProviderTracker(): ProviderTracker | undefined {
21
+ return activeContext?.providerTracker;
22
+ }