@spfunctions/cli 1.7.19 → 1.7.22

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 (180) hide show
  1. package/dist/101.index.js +1 -0
  2. package/dist/12.index.js +1 -0
  3. package/dist/160.index.js +1 -0
  4. package/dist/174.index.js +1 -0
  5. package/dist/278.index.js +6 -0
  6. package/dist/582.index.js +1 -0
  7. package/dist/641.index.js +324 -0
  8. package/dist/669.index.js +1 -0
  9. package/dist/722.index.js +1 -0
  10. package/dist/788.index.js +1 -0
  11. package/dist/816.index.js +12 -0
  12. package/dist/830.index.js +1 -0
  13. package/dist/921.index.js +1 -0
  14. package/dist/index.js +1 -833
  15. package/package.json +5 -2
  16. package/dist/cache.d.ts +0 -6
  17. package/dist/cache.js +0 -31
  18. package/dist/cache.test.d.ts +0 -1
  19. package/dist/cache.test.js +0 -73
  20. package/dist/client.d.ts +0 -56
  21. package/dist/client.js +0 -205
  22. package/dist/client.test.d.ts +0 -1
  23. package/dist/client.test.js +0 -89
  24. package/dist/commands/agent.d.ts +0 -20
  25. package/dist/commands/agent.js +0 -4119
  26. package/dist/commands/announcements.d.ts +0 -3
  27. package/dist/commands/announcements.js +0 -28
  28. package/dist/commands/augment.d.ts +0 -12
  29. package/dist/commands/augment.js +0 -56
  30. package/dist/commands/balance.d.ts +0 -3
  31. package/dist/commands/balance.js +0 -17
  32. package/dist/commands/book.d.ts +0 -17
  33. package/dist/commands/book.js +0 -220
  34. package/dist/commands/cancel.d.ts +0 -5
  35. package/dist/commands/cancel.js +0 -41
  36. package/dist/commands/context.d.ts +0 -6
  37. package/dist/commands/context.js +0 -208
  38. package/dist/commands/create.d.ts +0 -7
  39. package/dist/commands/create.js +0 -42
  40. package/dist/commands/dashboard.d.ts +0 -14
  41. package/dist/commands/dashboard.js +0 -215
  42. package/dist/commands/delta.d.ts +0 -16
  43. package/dist/commands/delta.js +0 -115
  44. package/dist/commands/edges.d.ts +0 -26
  45. package/dist/commands/edges.js +0 -246
  46. package/dist/commands/evaluate.d.ts +0 -4
  47. package/dist/commands/evaluate.js +0 -30
  48. package/dist/commands/explore.d.ts +0 -14
  49. package/dist/commands/explore.js +0 -116
  50. package/dist/commands/feed.d.ts +0 -13
  51. package/dist/commands/feed.js +0 -73
  52. package/dist/commands/fills.d.ts +0 -4
  53. package/dist/commands/fills.js +0 -29
  54. package/dist/commands/forecast.d.ts +0 -4
  55. package/dist/commands/forecast.js +0 -53
  56. package/dist/commands/get.d.ts +0 -5
  57. package/dist/commands/get.js +0 -98
  58. package/dist/commands/heartbeat.d.ts +0 -20
  59. package/dist/commands/heartbeat.js +0 -73
  60. package/dist/commands/history.d.ts +0 -3
  61. package/dist/commands/history.js +0 -38
  62. package/dist/commands/liquidity.d.ts +0 -14
  63. package/dist/commands/liquidity.js +0 -378
  64. package/dist/commands/list.d.ts +0 -5
  65. package/dist/commands/list.js +0 -38
  66. package/dist/commands/login.d.ts +0 -10
  67. package/dist/commands/login.js +0 -98
  68. package/dist/commands/markets.d.ts +0 -10
  69. package/dist/commands/markets.js +0 -39
  70. package/dist/commands/milestones.d.ts +0 -8
  71. package/dist/commands/milestones.js +0 -56
  72. package/dist/commands/orders.d.ts +0 -4
  73. package/dist/commands/orders.js +0 -28
  74. package/dist/commands/performance.d.ts +0 -11
  75. package/dist/commands/performance.js +0 -250
  76. package/dist/commands/positions.d.ts +0 -19
  77. package/dist/commands/positions.js +0 -294
  78. package/dist/commands/prompt.d.ts +0 -13
  79. package/dist/commands/prompt.js +0 -35
  80. package/dist/commands/publish.d.ts +0 -15
  81. package/dist/commands/publish.js +0 -39
  82. package/dist/commands/query.d.ts +0 -15
  83. package/dist/commands/query.js +0 -132
  84. package/dist/commands/rfq.d.ts +0 -5
  85. package/dist/commands/rfq.js +0 -35
  86. package/dist/commands/scan.d.ts +0 -11
  87. package/dist/commands/scan.js +0 -230
  88. package/dist/commands/schedule.d.ts +0 -3
  89. package/dist/commands/schedule.js +0 -38
  90. package/dist/commands/settlements.d.ts +0 -6
  91. package/dist/commands/settlements.js +0 -50
  92. package/dist/commands/setup.d.ts +0 -24
  93. package/dist/commands/setup.js +0 -700
  94. package/dist/commands/signal.d.ts +0 -6
  95. package/dist/commands/signal.js +0 -32
  96. package/dist/commands/strategies.d.ts +0 -11
  97. package/dist/commands/strategies.js +0 -130
  98. package/dist/commands/telegram.d.ts +0 -15
  99. package/dist/commands/telegram.js +0 -125
  100. package/dist/commands/trade.d.ts +0 -12
  101. package/dist/commands/trade.js +0 -112
  102. package/dist/commands/watch.d.ts +0 -19
  103. package/dist/commands/watch.js +0 -157
  104. package/dist/commands/whatif.d.ts +0 -17
  105. package/dist/commands/whatif.js +0 -209
  106. package/dist/commands/x.d.ts +0 -28
  107. package/dist/commands/x.js +0 -167
  108. package/dist/config.d.ts +0 -55
  109. package/dist/config.js +0 -139
  110. package/dist/config.test.d.ts +0 -1
  111. package/dist/config.test.js +0 -138
  112. package/dist/index.d.ts +0 -20
  113. package/dist/kalshi.d.ts +0 -144
  114. package/dist/kalshi.js +0 -498
  115. package/dist/polymarket.d.ts +0 -237
  116. package/dist/polymarket.js +0 -353
  117. package/dist/polymarket.test.d.ts +0 -1
  118. package/dist/polymarket.test.js +0 -424
  119. package/dist/share.d.ts +0 -4
  120. package/dist/share.js +0 -27
  121. package/dist/skills/loader.d.ts +0 -19
  122. package/dist/skills/loader.js +0 -86
  123. package/dist/telegram/agent-bridge.d.ts +0 -15
  124. package/dist/telegram/agent-bridge.js +0 -573
  125. package/dist/telegram/bot.d.ts +0 -10
  126. package/dist/telegram/bot.js +0 -297
  127. package/dist/telegram/commands.d.ts +0 -11
  128. package/dist/telegram/commands.js +0 -120
  129. package/dist/telegram/format.d.ts +0 -11
  130. package/dist/telegram/format.js +0 -51
  131. package/dist/telegram/format.test.d.ts +0 -1
  132. package/dist/telegram/format.test.js +0 -73
  133. package/dist/telegram/poller.d.ts +0 -6
  134. package/dist/telegram/poller.js +0 -32
  135. package/dist/topics.d.ts +0 -17
  136. package/dist/topics.js +0 -102
  137. package/dist/topics.test.d.ts +0 -1
  138. package/dist/topics.test.js +0 -131
  139. package/dist/tui/border.d.ts +0 -33
  140. package/dist/tui/border.js +0 -87
  141. package/dist/tui/chart.d.ts +0 -19
  142. package/dist/tui/chart.js +0 -117
  143. package/dist/tui/dashboard.d.ts +0 -9
  144. package/dist/tui/dashboard.js +0 -814
  145. package/dist/tui/layout.d.ts +0 -16
  146. package/dist/tui/layout.js +0 -41
  147. package/dist/tui/screen.d.ts +0 -33
  148. package/dist/tui/screen.js +0 -102
  149. package/dist/tui/state.d.ts +0 -40
  150. package/dist/tui/state.js +0 -36
  151. package/dist/tui/widgets/commandbar.d.ts +0 -8
  152. package/dist/tui/widgets/commandbar.js +0 -82
  153. package/dist/tui/widgets/detail.d.ts +0 -9
  154. package/dist/tui/widgets/detail.js +0 -151
  155. package/dist/tui/widgets/edges.d.ts +0 -4
  156. package/dist/tui/widgets/edges.js +0 -34
  157. package/dist/tui/widgets/liquidity.d.ts +0 -9
  158. package/dist/tui/widgets/liquidity.js +0 -142
  159. package/dist/tui/widgets/orders.d.ts +0 -4
  160. package/dist/tui/widgets/orders.js +0 -37
  161. package/dist/tui/widgets/portfolio.d.ts +0 -4
  162. package/dist/tui/widgets/portfolio.js +0 -59
  163. package/dist/tui/widgets/signals.d.ts +0 -4
  164. package/dist/tui/widgets/signals.js +0 -31
  165. package/dist/tui/widgets/statusbar.d.ts +0 -8
  166. package/dist/tui/widgets/statusbar.js +0 -72
  167. package/dist/tui/widgets/thesis.d.ts +0 -4
  168. package/dist/tui/widgets/thesis.js +0 -66
  169. package/dist/tui/widgets/trade.d.ts +0 -9
  170. package/dist/tui/widgets/trade.js +0 -117
  171. package/dist/tui/widgets/upcoming.d.ts +0 -4
  172. package/dist/tui/widgets/upcoming.js +0 -41
  173. package/dist/tui/widgets/whatif.d.ts +0 -7
  174. package/dist/tui/widgets/whatif.js +0 -113
  175. package/dist/types/output.d.ts +0 -412
  176. package/dist/types/output.js +0 -9
  177. package/dist/utils.d.ts +0 -52
  178. package/dist/utils.js +0 -146
  179. package/dist/utils.test.d.ts +0 -1
  180. package/dist/utils.test.js +0 -111
@@ -1,378 +0,0 @@
1
- "use strict";
2
- /**
3
- * sf liquidity — Market liquidity scanner by topic and horizon
4
- *
5
- * Scans known series, fetches public orderbooks, and displays
6
- * spread/depth/slippage data grouped by topic and horizon.
7
- */
8
- Object.defineProperty(exports, "__esModule", { value: true });
9
- exports.liquidityCommand = liquidityCommand;
10
- const client_js_1 = require("../client.js");
11
- const kalshi_js_1 = require("../kalshi.js");
12
- const polymarket_js_1 = require("../polymarket.js");
13
- const topics_js_1 = require("../topics.js");
14
- const utils_js_1 = require("../utils.js");
15
- // ── Horizon classification ───────────────────────────────────────────────────
16
- function classifyHorizon(closeTime) {
17
- const now = Date.now();
18
- const close = new Date(closeTime).getTime();
19
- const daysAway = (close - now) / (1000 * 60 * 60 * 24);
20
- if (daysAway < 7)
21
- return 'weekly';
22
- if (daysAway <= 35)
23
- return 'monthly';
24
- return 'long-term';
25
- }
26
- function horizonLabel(h) {
27
- switch (h) {
28
- case 'weekly': return 'weekly (<7d)';
29
- case 'monthly': return 'monthly (7-35d)';
30
- case 'long-term': return 'long-term (>35d)';
31
- }
32
- }
33
- // ── Slippage calculation ─────────────────────────────────────────────────────
34
- /**
35
- * Calculate weighted average price to buy `qty` YES contracts
36
- * by eating NO bids (selling NO = buying YES).
37
- *
38
- * no_dollars are sorted low→high by price. The best NO bid
39
- * (highest price) is the cheapest YES ask.
40
- */
41
- function calcSlippage100(noDollars, qty) {
42
- // Sort descending by price (highest no bid = cheapest yes ask)
43
- const levels = noDollars
44
- .map(([price, amount]) => ({
45
- noPrice: parseFloat(price),
46
- yesAsk: 1.0 - parseFloat(price),
47
- qty: parseFloat(amount),
48
- }))
49
- .filter(l => l.noPrice > 0 && l.qty > 0)
50
- .sort((a, b) => b.noPrice - a.noPrice); // highest no price first = lowest yes ask
51
- let remaining = qty;
52
- let totalCost = 0;
53
- for (const level of levels) {
54
- if (remaining <= 0)
55
- break;
56
- const fill = Math.min(remaining, level.qty);
57
- totalCost += fill * level.yesAsk;
58
- remaining -= fill;
59
- }
60
- if (remaining > 0)
61
- return '∞';
62
- const avgPrice = totalCost / qty;
63
- return (avgPrice * 100).toFixed(1) + '¢';
64
- }
65
- // ── Batch concurrency helper ─────────────────────────────────────────────────
66
- async function batchProcess(items, fn, batchSize, delayMs) {
67
- const results = [];
68
- for (let i = 0; i < items.length; i += batchSize) {
69
- const batch = items.slice(i, i + batchSize);
70
- const settled = await Promise.allSettled(batch.map(fn));
71
- for (const s of settled) {
72
- results.push(s.status === 'fulfilled' ? s.value : null);
73
- }
74
- if (i + batchSize < items.length) {
75
- await new Promise(resolve => setTimeout(resolve, delayMs));
76
- }
77
- }
78
- return results;
79
- }
80
- // ── Main command ─────────────────────────────────────────────────────────────
81
- async function liquidityCommand(opts) {
82
- const allTopics = Object.keys(topics_js_1.TOPIC_SERIES);
83
- // If no topic and no --all, show available topics
84
- if (!opts.topic && !opts.all) {
85
- console.log();
86
- console.log(`${utils_js_1.c.bold}Available Topics${utils_js_1.c.reset} ${utils_js_1.c.dim}(${allTopics.length} topics)${utils_js_1.c.reset}`);
87
- console.log(utils_js_1.c.dim + '─'.repeat(50) + utils_js_1.c.reset);
88
- console.log();
89
- for (const topic of allTopics) {
90
- const series = topics_js_1.TOPIC_SERIES[topic];
91
- console.log(` ${utils_js_1.c.cyan}${(0, utils_js_1.pad)(topic, 14)}${utils_js_1.c.reset} ${utils_js_1.c.dim}${series.slice(0, 3).join(', ')}${series.length > 3 ? ` +${series.length - 3} more` : ''}${utils_js_1.c.reset}`);
92
- }
93
- console.log();
94
- console.log(`${utils_js_1.c.dim}Usage: sf liquidity <topic> (e.g. sf liquidity oil)${utils_js_1.c.reset}`);
95
- console.log(`${utils_js_1.c.dim} sf liquidity --all (scan all topics)${utils_js_1.c.reset}`);
96
- console.log();
97
- return;
98
- }
99
- // Determine which topics to scan
100
- const topics = opts.topic
101
- ? allTopics.filter(t => t.toLowerCase() === opts.topic.toLowerCase())
102
- : allTopics;
103
- if (opts.topic && topics.length === 0) {
104
- const valid = allTopics.join(', ');
105
- console.error(`Unknown topic: ${opts.topic}. Valid topics: ${valid}`);
106
- process.exit(1);
107
- }
108
- // Fetch held positions if Kalshi is configured
109
- let heldTickers = new Set();
110
- if ((0, kalshi_js_1.isKalshiConfigured)()) {
111
- try {
112
- const positions = await (0, kalshi_js_1.getPositions)();
113
- if (positions) {
114
- heldTickers = new Set(positions.map(p => p.ticker));
115
- }
116
- }
117
- catch {
118
- // ignore — positions are optional decoration
119
- }
120
- }
121
- // Collect all markets per topic
122
- const topicMarkets = {};
123
- for (const topic of topics) {
124
- const series = topics_js_1.TOPIC_SERIES[topic];
125
- const markets = [];
126
- for (const seriesTicker of series) {
127
- try {
128
- const m = await (0, client_js_1.kalshiFetchMarketsBySeries)(seriesTicker);
129
- markets.push(...m);
130
- }
131
- catch {
132
- // skip failed series
133
- }
134
- }
135
- if (markets.length > 0) {
136
- topicMarkets[topic] = markets;
137
- }
138
- }
139
- // ── Polymarket: search for matching markets ──
140
- const scanPoly = opts.venue !== 'kalshi';
141
- if (scanPoly) {
142
- for (const topic of topics) {
143
- try {
144
- const events = await (0, polymarket_js_1.polymarketSearch)(topic, 5);
145
- for (const event of events) {
146
- for (const m of (event.markets || [])) {
147
- if (!m.active || m.closed || !m.enableOrderBook)
148
- continue;
149
- if (!topicMarkets[topic])
150
- topicMarkets[topic] = [];
151
- topicMarkets[topic].push({
152
- ticker: m.conditionId?.slice(0, 16) || m.id,
153
- close_time: m.endDateIso || '',
154
- venue: 'polymarket',
155
- question: m.question || event.title,
156
- clobTokenIds: m.clobTokenIds,
157
- bestBid: m.bestBid,
158
- bestAsk: m.bestAsk,
159
- spread: m.spread,
160
- liquidityNum: m.liquidityNum,
161
- });
162
- }
163
- }
164
- }
165
- catch {
166
- // skip Polymarket errors
167
- }
168
- }
169
- }
170
- // Filter by horizon if specified, classify all markets
171
- const horizonFilter = opts.horizon;
172
- const marketInfos = [];
173
- for (const [topic, markets] of Object.entries(topicMarkets)) {
174
- for (const m of markets) {
175
- const closeTime = m.close_time || m.expiration_time || '';
176
- if (!closeTime)
177
- continue;
178
- const horizon = classifyHorizon(closeTime);
179
- if (horizonFilter && horizon !== horizonFilter)
180
- continue;
181
- marketInfos.push({
182
- ticker: m.ticker,
183
- closeTime,
184
- topic,
185
- horizon,
186
- venue: m.venue || 'kalshi',
187
- question: m.question,
188
- clobTokenIds: m.clobTokenIds,
189
- });
190
- }
191
- }
192
- if (marketInfos.length === 0) {
193
- console.log('No markets found matching filters.');
194
- return;
195
- }
196
- // Split by venue
197
- const kalshiInfos = marketInfos.filter(m => m.venue === 'kalshi');
198
- const polyInfos = marketInfos.filter(m => m.venue === 'polymarket');
199
- // Fetch Kalshi orderbooks in batches
200
- const kalshiResults = await batchProcess(kalshiInfos, async (info) => {
201
- const ob = await (0, kalshi_js_1.getPublicOrderbook)(info.ticker);
202
- return { info, ob };
203
- }, 5, 100);
204
- // Fetch Polymarket orderbooks in batches
205
- const polyResults = await batchProcess(polyInfos, async (info) => {
206
- if (!info.clobTokenIds)
207
- return { info, depth: null };
208
- const ids = (0, polymarket_js_1.parseClobTokenIds)(info.clobTokenIds);
209
- if (!ids)
210
- return { info, depth: null };
211
- const depth = await (0, polymarket_js_1.polymarketGetOrderbookWithDepth)(ids[0]);
212
- return { info, depth };
213
- }, 5, 100);
214
- // Build liquidity rows
215
- const rows = [];
216
- // Process Kalshi results
217
- for (const result of kalshiResults) {
218
- if (!result || !result.ob)
219
- continue;
220
- const { info, ob } = result;
221
- const yesDollars = ob.yes_dollars.map(([p, q]) => ({
222
- price: Math.round(parseFloat(p) * 100),
223
- qty: parseFloat(q),
224
- })).filter((l) => l.price > 0);
225
- const noDollars = ob.no_dollars.map(([p, q]) => ({
226
- price: Math.round(parseFloat(p) * 100),
227
- qty: parseFloat(q),
228
- })).filter((l) => l.price > 0);
229
- yesDollars.sort((a, b) => b.price - a.price);
230
- noDollars.sort((a, b) => b.price - a.price);
231
- const bestBid = yesDollars.length > 0 ? yesDollars[0].price : 0;
232
- const bestAsk = noDollars.length > 0 ? (100 - noDollars[0].price) : 100;
233
- const spread = bestAsk - bestBid;
234
- const bidDepth = yesDollars.reduce((sum, l) => sum + l.qty, 0);
235
- const askDepth = noDollars.reduce((sum, l) => sum + l.qty, 0);
236
- const slippage100 = calcSlippage100(ob.no_dollars, 100);
237
- if (opts.minDepth && (bidDepth + askDepth) < opts.minDepth)
238
- continue;
239
- rows.push({
240
- ticker: info.ticker,
241
- shortTicker: info.ticker,
242
- topic: info.topic.toUpperCase(),
243
- horizon: info.horizon,
244
- closeTime: info.closeTime,
245
- bestBid, bestAsk, spread, bidDepth, askDepth, slippage100,
246
- held: heldTickers.has(info.ticker),
247
- venue: 'kalshi',
248
- });
249
- }
250
- // Process Polymarket results
251
- for (const result of polyResults) {
252
- if (!result || !result.depth)
253
- continue;
254
- const { info, depth } = result;
255
- if (opts.minDepth && (depth.bidDepthTop3 + depth.askDepthTop3) < opts.minDepth)
256
- continue;
257
- rows.push({
258
- ticker: (info.question || info.ticker).slice(0, 30),
259
- shortTicker: (info.question || info.ticker).slice(0, 30),
260
- topic: info.topic.toUpperCase(),
261
- horizon: info.horizon,
262
- closeTime: info.closeTime,
263
- bestBid: depth.bestBid,
264
- bestAsk: depth.bestAsk,
265
- spread: depth.spread,
266
- bidDepth: depth.totalBidDepth,
267
- askDepth: depth.totalAskDepth,
268
- slippage100: '-',
269
- held: false,
270
- venue: 'polymarket',
271
- });
272
- }
273
- // ── JSON output ────────────────────────────────────────────────────────────
274
- if (opts.json) {
275
- console.log(JSON.stringify(rows, null, 2));
276
- return;
277
- }
278
- // ── Formatted output ───────────────────────────────────────────────────────
279
- const now = new Date().toISOString().slice(0, 10);
280
- console.log();
281
- console.log(`${utils_js_1.c.bold}Liquidity Scanner${utils_js_1.c.reset} ${utils_js_1.c.dim}(${now} UTC)${utils_js_1.c.reset}`);
282
- console.log(utils_js_1.c.dim + '─'.repeat(68) + utils_js_1.c.reset);
283
- // Group rows by topic → horizon (topic is pre-set on each row)
284
- const grouped = {};
285
- for (const row of rows) {
286
- const topic = row.topic || 'OTHER';
287
- if (!grouped[topic])
288
- grouped[topic] = {};
289
- if (!grouped[topic][row.horizon])
290
- grouped[topic][row.horizon] = [];
291
- grouped[topic][row.horizon].push(row);
292
- }
293
- let totalMarkets = 0;
294
- let thinMarkets = 0;
295
- let heldCount = 0;
296
- const horizonOrder = ['weekly', 'monthly', 'long-term'];
297
- for (const [topic, horizons] of Object.entries(grouped)) {
298
- for (const h of horizonOrder) {
299
- const marketRows = horizons[h];
300
- if (!marketRows || marketRows.length === 0)
301
- continue;
302
- // Abbreviate Kalshi tickers (strip common prefix), keep Polymarket titles as-is
303
- const kalshiRows = marketRows.filter(r => r.venue === 'kalshi');
304
- if (kalshiRows.length > 1) {
305
- const commonPrefix = findCommonPrefix(kalshiRows.map(r => r.ticker));
306
- for (const row of kalshiRows) {
307
- const short = commonPrefix.length > 0
308
- ? row.ticker.slice(commonPrefix.length).replace(/^-/, '')
309
- : row.ticker;
310
- row.shortTicker = short.length > 0 ? short : row.ticker;
311
- }
312
- }
313
- // Sort: Kalshi by ticker, Polymarket by spread
314
- marketRows.sort((a, b) => {
315
- if (a.venue !== b.venue)
316
- return a.venue === 'kalshi' ? -1 : 1;
317
- return a.venue === 'kalshi'
318
- ? a.ticker.localeCompare(b.ticker)
319
- : a.spread - b.spread;
320
- });
321
- console.log();
322
- console.log(`${utils_js_1.c.bold}${utils_js_1.c.cyan}${topic}${utils_js_1.c.reset} ${utils_js_1.c.dim}— ${horizonLabel(h)}${utils_js_1.c.reset}`);
323
- console.log(`${utils_js_1.c.dim} ${(0, utils_js_1.pad)('Market', 22)} ${(0, utils_js_1.rpad)('Bid¢', 5)} ${(0, utils_js_1.rpad)('Ask¢', 5)} ${(0, utils_js_1.rpad)('Spread', 6)} ${(0, utils_js_1.rpad)('BidDep', 6)} ${(0, utils_js_1.rpad)('AskDep', 6)} ${(0, utils_js_1.rpad)('Slip100', 7)}${utils_js_1.c.reset}`);
324
- for (const row of marketRows) {
325
- totalMarkets++;
326
- if (row.held)
327
- heldCount++;
328
- const thin = row.spread > 5;
329
- if (thin)
330
- thinMarkets++;
331
- // Color spread
332
- let spreadStr;
333
- if (row.spread <= 2) {
334
- spreadStr = `${utils_js_1.c.green}${row.spread}¢${utils_js_1.c.reset}`;
335
- }
336
- else if (row.spread <= 5) {
337
- spreadStr = `${utils_js_1.c.yellow}${row.spread}¢${utils_js_1.c.reset}`;
338
- }
339
- else {
340
- spreadStr = `${utils_js_1.c.red}${row.spread}¢${utils_js_1.c.reset}`;
341
- }
342
- const thinMark = thin ? ' \u26A0\uFE0F' : '';
343
- const heldMark = row.held ? ` ${utils_js_1.c.magenta}\u2190 held${utils_js_1.c.reset}` : '';
344
- // Pad spread field accounting for ANSI codes
345
- const spreadPadded = (0, utils_js_1.rpad)(`${row.spread}¢`, 6);
346
- const spreadColored = row.spread <= 2
347
- ? `${utils_js_1.c.green}${spreadPadded}${utils_js_1.c.reset}`
348
- : row.spread <= 5
349
- ? `${utils_js_1.c.yellow}${spreadPadded}${utils_js_1.c.reset}`
350
- : `${utils_js_1.c.red}${spreadPadded}${utils_js_1.c.reset}`;
351
- const venueTag = row.venue === 'polymarket' ? `${utils_js_1.c.blue}POLY${utils_js_1.c.reset} ` : `${utils_js_1.c.cyan}KLSH${utils_js_1.c.reset} `;
352
- console.log(`${venueTag}${(0, utils_js_1.pad)(row.shortTicker, 22)} ${(0, utils_js_1.rpad)(String(row.bestBid), 5)} ${(0, utils_js_1.rpad)(String(row.bestAsk), 5)} ${spreadColored} ${(0, utils_js_1.rpad)(String(Math.round(row.bidDepth)), 6)} ${(0, utils_js_1.rpad)(String(Math.round(row.askDepth)), 6)} ${(0, utils_js_1.rpad)(row.slippage100, 7)}${thinMark}${heldMark}`);
353
- }
354
- }
355
- }
356
- // Summary
357
- console.log();
358
- console.log(`${utils_js_1.c.dim}Summary: ${totalMarkets} markets | ${thinMarkets} thin (spread>5¢) | ${heldCount} held${utils_js_1.c.reset}`);
359
- console.log();
360
- }
361
- // ── Helpers ──────────────────────────────────────────────────────────────────
362
- function findCommonPrefix(strings) {
363
- if (strings.length === 0)
364
- return '';
365
- if (strings.length === 1)
366
- return '';
367
- let prefix = strings[0];
368
- for (let i = 1; i < strings.length; i++) {
369
- while (!strings[i].startsWith(prefix)) {
370
- prefix = prefix.slice(0, -1);
371
- if (prefix.length === 0)
372
- return '';
373
- }
374
- }
375
- // Don't strip if it would leave nothing for some tickers
376
- // Also strip trailing hyphen from prefix for cleaner display
377
- return prefix;
378
- }
@@ -1,5 +0,0 @@
1
- export declare function listCommand(opts: {
2
- json?: boolean;
3
- apiKey?: string;
4
- apiUrl?: string;
5
- }): Promise<void>;
@@ -1,38 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.listCommand = listCommand;
4
- const client_js_1 = require("../client.js");
5
- const utils_js_1 = require("../utils.js");
6
- async function listCommand(opts) {
7
- const client = new client_js_1.SFClient(opts.apiKey, opts.apiUrl);
8
- const { theses } = await client.listTheses();
9
- if (opts.json) {
10
- console.log(JSON.stringify(theses, null, 2));
11
- return;
12
- }
13
- if (theses.length === 0) {
14
- (0, utils_js_1.emptyState)('theses', 'Create one: sf create "your market thesis"');
15
- return;
16
- }
17
- console.log(`\n${utils_js_1.c.bold}` +
18
- (0, utils_js_1.pad)('ID', 12) +
19
- (0, utils_js_1.pad)('Status', 10) +
20
- (0, utils_js_1.rpad)('Conf', 6) +
21
- ' ' +
22
- (0, utils_js_1.pad)('Updated', 14) +
23
- ' Title' +
24
- utils_js_1.c.reset);
25
- (0, utils_js_1.hr)(90);
26
- for (const t of theses) {
27
- const statusColor = t.status === 'active' ? utils_js_1.c.green : t.status === 'forming' ? utils_js_1.c.yellow : utils_js_1.c.dim;
28
- const conf = t.confidence ? (0, utils_js_1.pct)(parseFloat(t.confidence)) : '-';
29
- console.log((0, utils_js_1.pad)((0, utils_js_1.shortId)(t.id), 12) +
30
- statusColor + (0, utils_js_1.pad)(t.status, 10) + utils_js_1.c.reset +
31
- (0, utils_js_1.rpad)(conf, 6) +
32
- ' ' +
33
- utils_js_1.c.dim + (0, utils_js_1.pad)((0, utils_js_1.shortDate)(t.updatedAt), 14) + utils_js_1.c.reset +
34
- ' ' +
35
- (0, utils_js_1.trunc)(t.title || t.rawThesis.slice(0, 60), 50));
36
- }
37
- console.log(`\n${utils_js_1.c.dim}${theses.length} thesis(es)${utils_js_1.c.reset}`);
38
- }
@@ -1,10 +0,0 @@
1
- /**
2
- * sf login — Browser-based authentication.
3
- *
4
- * Opens the browser, user logs in via magic link, CLI receives an API key.
5
- * Zero manual key configuration needed.
6
- */
7
- export declare function loginCommand(opts: {
8
- apiUrl?: string;
9
- force?: boolean;
10
- }): Promise<void>;
@@ -1,98 +0,0 @@
1
- "use strict";
2
- /**
3
- * sf login — Browser-based authentication.
4
- *
5
- * Opens the browser, user logs in via magic link, CLI receives an API key.
6
- * Zero manual key configuration needed.
7
- */
8
- Object.defineProperty(exports, "__esModule", { value: true });
9
- exports.loginCommand = loginCommand;
10
- const crypto_1 = require("crypto");
11
- const config_js_1 = require("../config.js");
12
- const utils_js_1 = require("../utils.js");
13
- const SF_API_URL = process.env.SF_API_URL || 'https://simplefunctions.dev';
14
- async function loginCommand(opts) {
15
- const apiUrl = opts.apiUrl || (0, config_js_1.loadConfig)().apiUrl || SF_API_URL;
16
- // If already configured, re-login replaces the existing key
17
- const fileConfig = (0, config_js_1.loadFileConfig)();
18
- if (fileConfig.apiKey && !opts.force) {
19
- console.log(`\n ${utils_js_1.c.dim}Already logged in (${fileConfig.apiKey.slice(0, 12)}...).${utils_js_1.c.reset}`);
20
- console.log(` ${utils_js_1.c.dim}Run ${utils_js_1.c.cyan}sf login --force${utils_js_1.c.dim} to re-authenticate, or ${utils_js_1.c.cyan}sf logout${utils_js_1.c.dim} to clear.${utils_js_1.c.reset}\n`);
21
- return;
22
- }
23
- // Generate session token
24
- const sessionToken = (0, crypto_1.randomBytes)(32).toString('base64url');
25
- // Register session on server
26
- console.log(`\n ${utils_js_1.c.dim}Registering login session...${utils_js_1.c.reset}`);
27
- try {
28
- const res = await fetch(`${apiUrl}/api/auth/cli`, {
29
- method: 'POST',
30
- headers: { 'Content-Type': 'application/json' },
31
- body: JSON.stringify({ sessionToken }),
32
- });
33
- if (!res.ok) {
34
- const data = await res.json().catch(() => ({}));
35
- console.error(` ${utils_js_1.c.red}Failed to create session: ${data.error || res.status}${utils_js_1.c.reset}`);
36
- return;
37
- }
38
- }
39
- catch (err) {
40
- console.error(` ${utils_js_1.c.red}Could not reach ${apiUrl}${utils_js_1.c.reset}`);
41
- return;
42
- }
43
- // Open browser
44
- const loginUrl = `${apiUrl}/auth/cli?token=${sessionToken}`;
45
- console.log(`\n ${utils_js_1.c.bold}Opening browser...${utils_js_1.c.reset}`);
46
- console.log(` ${utils_js_1.c.dim}${loginUrl}${utils_js_1.c.reset}\n`);
47
- try {
48
- const { exec } = await import('child_process');
49
- const platform = process.platform;
50
- const cmd = platform === 'darwin' ? 'open'
51
- : platform === 'win32' ? 'start'
52
- : 'xdg-open';
53
- exec(`${cmd} "${loginUrl}"`);
54
- }
55
- catch {
56
- console.log(` ${utils_js_1.c.dim}Could not open browser. Visit the URL above manually.${utils_js_1.c.reset}`);
57
- }
58
- // Poll for completion
59
- console.log(` ${utils_js_1.c.dim}Waiting for login...${utils_js_1.c.reset}`);
60
- const maxWait = 5 * 60 * 1000; // 5 minutes
61
- const pollInterval = 2000;
62
- const startTime = Date.now();
63
- while (Date.now() - startTime < maxWait) {
64
- await new Promise(r => setTimeout(r, pollInterval));
65
- try {
66
- const res = await fetch(`${apiUrl}/api/auth/cli/poll?token=${sessionToken}`);
67
- const data = await res.json();
68
- if (data.status === 'ready' && data.apiKey) {
69
- // Save to config
70
- (0, config_js_1.saveConfig)({
71
- ...fileConfig,
72
- apiKey: data.apiKey,
73
- apiUrl: apiUrl !== SF_API_URL ? apiUrl : undefined,
74
- });
75
- console.log(`\n ${utils_js_1.c.green}✓${utils_js_1.c.reset} ${utils_js_1.c.bold}Authenticated!${utils_js_1.c.reset}`);
76
- console.log(` ${utils_js_1.c.dim}API key saved to ~/.sf/config.json${utils_js_1.c.reset}`);
77
- console.log(`\n ${utils_js_1.c.dim}OpenRouter & Tavily are proxied through ${apiUrl}${utils_js_1.c.reset}`);
78
- console.log(` ${utils_js_1.c.dim}No additional API keys needed.${utils_js_1.c.reset}`);
79
- console.log(`\n ${utils_js_1.c.cyan}sf context${utils_js_1.c.reset} ${utils_js_1.c.dim}market intelligence${utils_js_1.c.reset}`);
80
- console.log(` ${utils_js_1.c.cyan}sf agent${utils_js_1.c.reset} ${utils_js_1.c.dim}<thesis>${utils_js_1.c.reset} ${utils_js_1.c.dim}start the agent${utils_js_1.c.reset}`);
81
- console.log(` ${utils_js_1.c.cyan}sf setup --check${utils_js_1.c.reset} ${utils_js_1.c.dim}verify config${utils_js_1.c.reset}`);
82
- console.log();
83
- return;
84
- }
85
- if (data.status === 'expired') {
86
- console.error(`\n ${utils_js_1.c.red}Session expired. Run ${utils_js_1.c.cyan}sf login${utils_js_1.c.red} again.${utils_js_1.c.reset}\n`);
87
- return;
88
- }
89
- // status === 'pending' — keep polling
90
- process.stdout.write('.');
91
- }
92
- catch {
93
- // Network error — keep trying
94
- process.stdout.write('x');
95
- }
96
- }
97
- console.error(`\n ${utils_js_1.c.red}Timed out waiting for login. Run ${utils_js_1.c.cyan}sf login${utils_js_1.c.red} again.${utils_js_1.c.reset}\n`);
98
- }
@@ -1,10 +0,0 @@
1
- /**
2
- * sf markets
3
- *
4
- * Traditional market snapshot via Databento (SPY, VIX, TLT, Gold, Oil).
5
- * No auth required — calls public endpoint.
6
- */
7
- export declare function marketsCommand(opts?: {
8
- json?: boolean;
9
- share?: boolean;
10
- }): Promise<void>;
@@ -1,39 +0,0 @@
1
- "use strict";
2
- /**
3
- * sf markets
4
- *
5
- * Traditional market snapshot via Databento (SPY, VIX, TLT, Gold, Oil).
6
- * No auth required — calls public endpoint.
7
- */
8
- Object.defineProperty(exports, "__esModule", { value: true });
9
- exports.marketsCommand = marketsCommand;
10
- const share_js_1 = require("../share.js");
11
- const BASE_URL = 'https://simplefunctions.dev';
12
- async function marketsCommand(opts) {
13
- const res = await fetch(`${BASE_URL}/api/public/markets`);
14
- if (!res.ok) {
15
- console.error(` Error: ${res.status} ${await res.text()}`);
16
- return;
17
- }
18
- const data = await res.json();
19
- if (opts?.share) {
20
- await (0, share_js_1.shareOutput)('markets', '', data);
21
- return;
22
- }
23
- if (opts?.json) {
24
- console.log(JSON.stringify(data, null, 2));
25
- return;
26
- }
27
- console.log(`\n \x1b[1mTraditional Markets\x1b[22m \x1b[2m${data.snapshotAt?.slice(0, 10) || ''}\x1b[22m\n`);
28
- if (!data.markets?.length) {
29
- console.log(' No data available.\n');
30
- return;
31
- }
32
- for (const m of data.markets) {
33
- const arrow = m.changePct >= 0 ? '\x1b[32m▲\x1b[39m' : '\x1b[31m▼\x1b[39m';
34
- const chg = m.changePct >= 0 ? `\x1b[32m+${m.changePct}%\x1b[39m` : `\x1b[31m${m.changePct}%\x1b[39m`;
35
- const price = `$${m.price.toFixed(2)}`;
36
- console.log(` ${arrow} ${m.symbol.padEnd(5)} ${price.padStart(10)} ${chg.padStart(16)} ${m.name}`);
37
- }
38
- console.log();
39
- }
@@ -1,8 +0,0 @@
1
- export declare function milestonesCommand(opts: {
2
- category?: string;
3
- thesis?: string;
4
- hours?: string;
5
- json?: boolean;
6
- apiKey?: string;
7
- apiUrl?: string;
8
- }): Promise<void>;
@@ -1,56 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.milestonesCommand = milestonesCommand;
4
- const client_js_1 = require("../client.js");
5
- const utils_js_1 = require("../utils.js");
6
- const KALSHI_API_BASE = 'https://api.elections.kalshi.com/trade-api/v2';
7
- async function milestonesCommand(opts) {
8
- const hours = parseInt(opts.hours || '168');
9
- const now = new Date();
10
- const cutoff = new Date(now.getTime() + hours * 3600000);
11
- // Fetch milestones (public endpoint)
12
- const url = `${KALSHI_API_BASE}/milestones?limit=200&minimum_start_date=${now.toISOString()}` +
13
- (opts.category ? `&category=${opts.category}` : '');
14
- const res = await fetch(url, { headers: { 'Accept': 'application/json' } });
15
- if (!res.ok)
16
- throw new Error(`Kalshi API ${res.status}`);
17
- const data = await res.json();
18
- let milestones = (data.milestones || []).filter((m) => new Date(m.start_date).getTime() <= cutoff.getTime());
19
- // If thesis specified, filter to matching event tickers
20
- if (opts.thesis) {
21
- const client = new client_js_1.SFClient(opts.apiKey, opts.apiUrl);
22
- const ctx = await client.getContext(opts.thesis);
23
- const edgeEventTickers = new Set((ctx.edges || []).map((e) => e.eventTicker).filter(Boolean));
24
- // Also match by related_event_tickers overlap
25
- const edgeSeriesTickers = new Set((ctx.edges || []).map((e) => e.seriesTicker).filter(Boolean));
26
- milestones = milestones.filter((m) => {
27
- const related = m.related_event_tickers || m.primary_event_tickers || [];
28
- return related.some((t) => edgeEventTickers.has(t) || edgeSeriesTickers.has(t.split('-')[0]));
29
- });
30
- }
31
- if (opts.json) {
32
- console.log(JSON.stringify(milestones, null, 2));
33
- return;
34
- }
35
- if (milestones.length === 0) {
36
- console.log(`${utils_js_1.c.dim}No milestones in the next ${hours} hours.${utils_js_1.c.reset}`);
37
- return;
38
- }
39
- // Sort by date
40
- milestones.sort((a, b) => new Date(a.start_date).getTime() - new Date(b.start_date).getTime());
41
- console.log(`${utils_js_1.c.bold}${utils_js_1.c.cyan}Upcoming Milestones (next ${hours}h)${utils_js_1.c.reset}`);
42
- console.log(`${utils_js_1.c.dim}${'─'.repeat(80)}${utils_js_1.c.reset}`);
43
- for (const m of milestones) {
44
- const date = new Date(m.start_date);
45
- const hoursUntil = Math.round((date.getTime() - now.getTime()) / 3600000);
46
- const timeStr = hoursUntil <= 24
47
- ? `${utils_js_1.c.bold}${hoursUntil}h${utils_js_1.c.reset}`
48
- : `${utils_js_1.c.dim}${Math.round(hoursUntil / 24)}d${utils_js_1.c.reset}`;
49
- const cat = `${utils_js_1.c.dim}[${m.category}]${utils_js_1.c.reset}`;
50
- const tickers = (m.related_event_tickers || []).slice(0, 3).join(', ');
51
- console.log(` ${timeStr.padEnd(12)} ${cat.padEnd(25)} ${m.title}`);
52
- if (tickers)
53
- console.log(` ${' '.repeat(10)} ${utils_js_1.c.dim}${tickers}${utils_js_1.c.reset}`);
54
- }
55
- console.log(`\n${utils_js_1.c.dim}${milestones.length} milestone(s)${utils_js_1.c.reset}`);
56
- }
@@ -1,4 +0,0 @@
1
- export declare function ordersCommand(opts: {
2
- status?: string;
3
- json?: boolean;
4
- }): Promise<void>;