@spfunctions/cli 1.7.19 → 1.7.20

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,700 +0,0 @@
1
- "use strict";
2
- /**
3
- * sf setup — Interactive configuration wizard
4
- *
5
- * Walks user through:
6
- * 1. SF API key (required)
7
- * 2. OpenRouter API key (optional, for agent)
8
- * 3. Kalshi exchange credentials (optional, for positions)
9
- * 4. Tavily API key (optional, for web search)
10
- * 5. First thesis creation (if none exist)
11
- *
12
- * Each key is validated in real-time.
13
- * Config is saved to ~/.sf/config.json.
14
- */
15
- var __importDefault = (this && this.__importDefault) || function (mod) {
16
- return (mod && mod.__esModule) ? mod : { "default": mod };
17
- };
18
- Object.defineProperty(exports, "__esModule", { value: true });
19
- exports.setupCommand = setupCommand;
20
- const readline_1 = __importDefault(require("readline"));
21
- const child_process_1 = require("child_process");
22
- const config_js_1 = require("../config.js");
23
- const client_js_1 = require("../client.js");
24
- const kalshi_js_1 = require("../kalshi.js");
25
- const agent_js_1 = require("./agent.js");
26
- // ─── ANSI helpers ────────────────────────────────────────────────────────────
27
- const green = (s) => `\x1b[32m${s}\x1b[39m`;
28
- const red = (s) => `\x1b[31m${s}\x1b[39m`;
29
- const dim = (s) => `\x1b[2m${s}\x1b[22m`;
30
- const bold = (s) => `\x1b[1m${s}\x1b[22m`;
31
- const cyan = (s) => `\x1b[36m${s}\x1b[39m`;
32
- function ok(msg) { console.log(` ${green('✓')} ${msg}`); }
33
- function fail(msg) { console.log(` ${red('✗')} ${msg}`); }
34
- function info(msg) { console.log(` ${msg}`); }
35
- function blank() { console.log(); }
36
- // ─── Prompt helper ───────────────────────────────────────────────────────────
37
- function prompt(question) {
38
- const rl = readline_1.default.createInterface({
39
- input: process.stdin,
40
- output: process.stdout,
41
- terminal: true,
42
- });
43
- return new Promise(resolve => {
44
- rl.question(question, answer => {
45
- rl.close();
46
- resolve(answer.trim());
47
- });
48
- });
49
- }
50
- function promptYN(question, defaultYes = true) {
51
- return prompt(question).then(ans => {
52
- if (!ans)
53
- return defaultYes;
54
- return ans.toLowerCase().startsWith('y');
55
- });
56
- }
57
- function openBrowser(url) {
58
- const cmd = process.platform === 'darwin' ? 'open' :
59
- process.platform === 'win32' ? 'start' : 'xdg-open';
60
- (0, child_process_1.exec)(`${cmd} ${url}`);
61
- }
62
- function mask(s) {
63
- if (!s || s.length <= 12)
64
- return s;
65
- return s.slice(0, 8) + '...' + s.slice(-4);
66
- }
67
- // ─── Validators ──────────────────────────────────────────────────────────────
68
- async function validateSFKey(key, apiUrl) {
69
- try {
70
- const res = await fetch(`${apiUrl}/api/thesis`, {
71
- headers: { 'Authorization': `Bearer ${key}` },
72
- });
73
- if (res.ok)
74
- return { valid: true, msg: `API key valid — connected to ${apiUrl.replace('https://', '')}` };
75
- if (res.status === 401)
76
- return { valid: false, msg: 'Invalid key, please try again' };
77
- return { valid: false, msg: `Server returned ${res.status}` };
78
- }
79
- catch (err) {
80
- return { valid: false, msg: `Connection failed: ${err.message}` };
81
- }
82
- }
83
- async function validateOpenRouterKey(key) {
84
- try {
85
- const res = await fetch('https://openrouter.ai/api/v1/models', {
86
- headers: { 'Authorization': `Bearer ${key}` },
87
- });
88
- if (res.ok)
89
- return { valid: true, msg: 'OpenRouter connected — available model: claude-sonnet-4.6' };
90
- return { valid: false, msg: `OpenRouter returned ${res.status}` };
91
- }
92
- catch (err) {
93
- return { valid: false, msg: `Connection failed: ${err.message}` };
94
- }
95
- }
96
- async function validateKalshi() {
97
- try {
98
- const positions = await (0, kalshi_js_1.getPositions)();
99
- if (positions === null)
100
- return { valid: false, msg: 'Kalshi authentication failed', posCount: 0 };
101
- return { valid: true, msg: `Kalshi authenticated — found ${positions.length} position(s)`, posCount: positions.length };
102
- }
103
- catch (err) {
104
- return { valid: false, msg: `Kalshi connection failed: ${err.message}`, posCount: 0 };
105
- }
106
- }
107
- async function validateTavily(key) {
108
- try {
109
- const res = await fetch('https://api.tavily.com/search', {
110
- method: 'POST',
111
- headers: { 'Content-Type': 'application/json' },
112
- body: JSON.stringify({ api_key: key, query: 'test', max_results: 1 }),
113
- });
114
- if (res.ok)
115
- return { valid: true, msg: 'Tavily connected' };
116
- return { valid: false, msg: `Tavily returned ${res.status}` };
117
- }
118
- catch (err) {
119
- return { valid: false, msg: `Connection failed: ${err.message}` };
120
- }
121
- }
122
- async function setupCommand(opts) {
123
- // ── sf setup --check ──────────────────────────────────────────────────────
124
- if (opts.check) {
125
- return showCheck();
126
- }
127
- // ── sf setup --reset ──────────────────────────────────────────────────────
128
- if (opts.reset) {
129
- (0, config_js_1.resetConfig)();
130
- ok('Config reset');
131
- blank();
132
- info('Run sf setup to reconfigure');
133
- blank();
134
- return;
135
- }
136
- // ── sf setup --key <key> (non-interactive) ────────────────────────────────
137
- if (opts.key) {
138
- const apiUrl = process.env.SF_API_URL || 'https://simplefunctions.dev';
139
- const result = await validateSFKey(opts.key, apiUrl);
140
- if (!result.valid) {
141
- fail(result.msg);
142
- process.exit(1);
143
- }
144
- const existing = (0, config_js_1.loadFileConfig)();
145
- (0, config_js_1.saveConfig)({ ...existing, apiKey: opts.key, apiUrl });
146
- ok(result.msg);
147
- ok(`Saved to ${(0, config_js_1.getConfigPath)()}`);
148
- return;
149
- }
150
- // ── sf setup --kalshi (reconfigure Kalshi credentials) ──────────────────
151
- if (opts.kalshi) {
152
- const existing = (0, config_js_1.loadFileConfig)();
153
- blank();
154
- console.log(` ${bold('Reconfigure Kalshi Credentials')}`);
155
- blank();
156
- info('Go to https://kalshi.com/account/api-keys to generate a new API key.');
157
- info('If you need trading, make sure to enable read+write permissions.');
158
- blank();
159
- await promptForKalshi(existing);
160
- (0, config_js_1.saveConfig)(existing);
161
- if (existing.kalshiKeyId) {
162
- process.env.KALSHI_API_KEY_ID = existing.kalshiKeyId;
163
- process.env.KALSHI_PRIVATE_KEY_PATH = existing.kalshiPrivateKeyPath;
164
- }
165
- blank();
166
- return;
167
- }
168
- // ── sf setup --polymarket (reconfigure Polymarket credentials) ──────────
169
- if (opts.polymarket) {
170
- const existing = (0, config_js_1.loadFileConfig)();
171
- blank();
172
- console.log(` ${bold('Reconfigure Polymarket Credentials')}`);
173
- blank();
174
- await promptForPolymarket(existing);
175
- (0, config_js_1.saveConfig)(existing);
176
- blank();
177
- return;
178
- }
179
- // ── sf setup --enable-trading / --disable-trading ────────────────────────
180
- if (opts.enableTrading) {
181
- const existing = (0, config_js_1.loadFileConfig)();
182
- (0, config_js_1.saveConfig)({ ...existing, tradingEnabled: true });
183
- ok('Trading enabled. sf buy / sf sell / sf cancel now available.');
184
- blank();
185
- return;
186
- }
187
- if (opts.disableTrading) {
188
- const existing = (0, config_js_1.loadFileConfig)();
189
- (0, config_js_1.saveConfig)({ ...existing, tradingEnabled: false });
190
- ok('Trading disabled.');
191
- blank();
192
- return;
193
- }
194
- // ── Full interactive wizard ───────────────────────────────────────────────
195
- return runWizard();
196
- }
197
- // ─── Check command ───────────────────────────────────────────────────────────
198
- async function showCheck() {
199
- const config = (0, config_js_1.loadConfig)();
200
- blank();
201
- console.log(` ${bold('SimpleFunctions Config Status')}`);
202
- console.log(` ${dim('─'.repeat(35))}`);
203
- blank();
204
- // SF API Key
205
- if (config.apiKey) {
206
- ok(`SF_API_KEY ${dim(mask(config.apiKey))}`);
207
- }
208
- else {
209
- fail('SF_API_KEY not configured (required)');
210
- }
211
- // OpenRouter
212
- if (config.openrouterKey) {
213
- ok(`OPENROUTER ${dim(mask(config.openrouterKey))} (direct)`);
214
- }
215
- else if (config.apiKey) {
216
- ok(`OPENROUTER ${dim('proxied via SimpleFunctions')}`);
217
- }
218
- else {
219
- fail(`OPENROUTER not configured (run sf login or set key)`);
220
- }
221
- // Kalshi
222
- if (config.kalshiKeyId && config.kalshiPrivateKeyPath) {
223
- ok(`KALSHI ${dim(mask(config.kalshiKeyId))}`);
224
- }
225
- else {
226
- info(`${dim('○')} KALSHI ${dim('skipped')}`);
227
- }
228
- // Polymarket
229
- if (config.polymarketWalletAddress) {
230
- ok(`POLYMARKET ${dim(mask(config.polymarketWalletAddress))}`);
231
- }
232
- else {
233
- info(`${dim('○')} POLYMARKET ${dim('skipped')}`);
234
- }
235
- // Tavily
236
- if (config.tavilyKey) {
237
- ok(`TAVILY ${dim(mask(config.tavilyKey))} (direct)`);
238
- }
239
- else if (config.apiKey) {
240
- ok(`TAVILY ${dim('proxied via SimpleFunctions')}`);
241
- }
242
- else {
243
- info(`${dim('○')} TAVILY ${dim('skipped')}`);
244
- }
245
- // Trading
246
- if (config.tradingEnabled) {
247
- ok('TRADING enabled');
248
- }
249
- else {
250
- info(`${dim('○')} TRADING ${dim('disabled — sf setup --enable-trading')}`);
251
- }
252
- blank();
253
- console.log(` ${dim('Config file: ' + (0, config_js_1.getConfigPath)())}`);
254
- blank();
255
- }
256
- // ─── Interactive Wizard ──────────────────────────────────────────────────────
257
- async function runWizard() {
258
- blank();
259
- console.log(` ${bold('SimpleFunctions Setup')}`);
260
- console.log(` ${dim('─'.repeat(25))}`);
261
- blank();
262
- const config = (0, config_js_1.loadFileConfig)();
263
- const apiUrl = config.apiUrl || 'https://simplefunctions.dev';
264
- // ════════════════════════════════════════════════════════════════════════════
265
- // Step 1: SF API Key
266
- // ════════════════════════════════════════════════════════════════════════════
267
- console.log(` ${bold('Step 1: API Key')}`);
268
- blank();
269
- const existingSfKey = process.env.SF_API_KEY || config.apiKey;
270
- if (existingSfKey) {
271
- const result = await validateSFKey(existingSfKey, apiUrl);
272
- if (result.valid) {
273
- ok(`Detected SF_API_KEY — ${dim(mask(existingSfKey))}`);
274
- info(dim('Skipping.'));
275
- config.apiKey = existingSfKey;
276
- blank();
277
- }
278
- else {
279
- fail(`Existing key invalid: ${result.msg}`);
280
- config.apiKey = await promptForSFKey(apiUrl);
281
- }
282
- }
283
- else {
284
- config.apiKey = await promptForSFKey(apiUrl);
285
- }
286
- // Save after each step (so partial progress is preserved)
287
- config.apiUrl = apiUrl;
288
- (0, config_js_1.saveConfig)(config);
289
- // Also apply so subsequent validation calls can use it
290
- process.env.SF_API_KEY = config.apiKey;
291
- // ════════════════════════════════════════════════════════════════════════════
292
- // Step 2: OpenRouter API Key
293
- // ════════════════════════════════════════════════════════════════════════════
294
- console.log(` ${bold('Step 2: AI Model (for sf agent)')}`);
295
- blank();
296
- const existingOrKey = process.env.OPENROUTER_API_KEY || config.openrouterKey;
297
- if (existingOrKey) {
298
- const result = await validateOpenRouterKey(existingOrKey);
299
- if (result.valid) {
300
- ok(`Detected OPENROUTER_API_KEY — ${dim(mask(existingOrKey))}`);
301
- info(dim('Skipping.'));
302
- config.openrouterKey = existingOrKey;
303
- blank();
304
- }
305
- else {
306
- fail(`Existing key invalid: ${result.msg}`);
307
- config.openrouterKey = await promptForOpenRouterKey();
308
- }
309
- }
310
- else {
311
- config.openrouterKey = await promptForOpenRouterKey();
312
- }
313
- (0, config_js_1.saveConfig)(config);
314
- if (config.openrouterKey)
315
- process.env.OPENROUTER_API_KEY = config.openrouterKey;
316
- // ════════════════════════════════════════════════════════════════════════════
317
- // Step 3: Kalshi Exchange
318
- // ════════════════════════════════════════════════════════════════════════════
319
- console.log(` ${bold('Step 3: Kalshi Exchange (optional)')}`);
320
- blank();
321
- const existingKalshiId = process.env.KALSHI_API_KEY_ID || config.kalshiKeyId;
322
- const existingKalshiPath = process.env.KALSHI_PRIVATE_KEY_PATH || config.kalshiPrivateKeyPath;
323
- if (existingKalshiId && existingKalshiPath) {
324
- // Temporarily apply for validation
325
- process.env.KALSHI_API_KEY_ID = existingKalshiId;
326
- process.env.KALSHI_PRIVATE_KEY_PATH = existingKalshiPath;
327
- const result = await validateKalshi();
328
- if (result.valid) {
329
- ok(`Detected Kalshi — ${dim(mask(existingKalshiId))} (${result.posCount} position(s))`);
330
- info(dim('Skipping.'));
331
- config.kalshiKeyId = existingKalshiId;
332
- config.kalshiPrivateKeyPath = existingKalshiPath;
333
- blank();
334
- }
335
- else {
336
- fail(`Existing credentials invalid: ${result.msg}`);
337
- await promptForKalshi(config);
338
- }
339
- }
340
- else {
341
- await promptForKalshi(config);
342
- }
343
- (0, config_js_1.saveConfig)(config);
344
- // ════════════════════════════════════════════════════════════════════════════
345
- // Step 4: Polymarket
346
- // ════════════════════════════════════════════════════════════════════════════
347
- console.log(` ${bold('Step 4: Polymarket (optional)')}`);
348
- blank();
349
- const existingPolyWallet = process.env.POLYMARKET_WALLET_ADDRESS || config.polymarketWalletAddress;
350
- if (existingPolyWallet) {
351
- ok(`Detected wallet — ${dim(mask(existingPolyWallet))}`);
352
- info(dim('Skipping.'));
353
- config.polymarketWalletAddress = existingPolyWallet;
354
- blank();
355
- }
356
- else {
357
- await promptForPolymarket(config);
358
- }
359
- (0, config_js_1.saveConfig)(config);
360
- if (config.polymarketWalletAddress)
361
- process.env.POLYMARKET_WALLET_ADDRESS = config.polymarketWalletAddress;
362
- // ════════════════════════════════════════════════════════════════════════════
363
- // Step 5: Tavily
364
- // ════════════════════════════════════════════════════════════════════════════
365
- console.log(` ${bold('Step 5: News Search (optional)')}`);
366
- blank();
367
- const existingTavily = process.env.TAVILY_API_KEY || config.tavilyKey;
368
- if (existingTavily) {
369
- const result = await validateTavily(existingTavily);
370
- if (result.valid) {
371
- ok(`Detected TAVILY_API_KEY — ${dim(mask(existingTavily))}`);
372
- info(dim('Skipping.'));
373
- config.tavilyKey = existingTavily;
374
- blank();
375
- }
376
- else {
377
- fail(`Existing key invalid: ${result.msg}`);
378
- config.tavilyKey = await promptForTavily();
379
- }
380
- }
381
- else {
382
- config.tavilyKey = await promptForTavily();
383
- }
384
- (0, config_js_1.saveConfig)(config);
385
- if (config.tavilyKey)
386
- process.env.TAVILY_API_KEY = config.tavilyKey;
387
- // ════════════════════════════════════════════════════════════════════════════
388
- // Step 5: Trading
389
- // ════════════════════════════════════════════════════════════════════════════
390
- if (config.kalshiKeyId) {
391
- console.log(` ${bold('Step 6: Trading (optional)')}`);
392
- blank();
393
- info('Warning: enabling this unlocks sf buy / sf sell / sf cancel.');
394
- info('Your Kalshi API key must have read+write permissions.');
395
- blank();
396
- const enableTrading = await promptYN(' Enable trading? (y/N) ', false);
397
- config.tradingEnabled = enableTrading;
398
- if (enableTrading) {
399
- ok('Trading enabled');
400
- }
401
- else {
402
- info(dim('Skipped. You can enable later with sf setup --enable-trading.'));
403
- }
404
- blank();
405
- (0, config_js_1.saveConfig)(config);
406
- }
407
- // ════════════════════════════════════════════════════════════════════════════
408
- // Summary
409
- // ════════════════════════════════════════════════════════════════════════════
410
- console.log(` ${dim('─'.repeat(25))}`);
411
- info(`Config saved to ${dim((0, config_js_1.getConfigPath)())}`);
412
- blank();
413
- if (config.apiKey)
414
- ok('SF_API_KEY configured');
415
- else
416
- fail('SF_API_KEY not configured');
417
- if (config.openrouterKey)
418
- ok('OPENROUTER_KEY configured');
419
- else
420
- fail('OPENROUTER_KEY skipped');
421
- if (config.kalshiKeyId)
422
- ok('KALSHI configured');
423
- else
424
- info(`${dim('○')} KALSHI skipped`);
425
- if (config.tavilyKey)
426
- ok('TAVILY configured');
427
- else
428
- info(`${dim('○')} TAVILY skipped`);
429
- blank();
430
- // ════════════════════════════════════════════════════════════════════════════
431
- // Step 5: Thesis creation
432
- // ════════════════════════════════════════════════════════════════════════════
433
- if (config.apiKey) {
434
- await handleThesisStep(config);
435
- }
436
- }
437
- // ─── Step prompt helpers ─────────────────────────────────────────────────────
438
- async function promptForSFKey(apiUrl) {
439
- info(`Don't have a key? Sign up at ${cyan('https://simplefunctions.dev/dashboard')}.`);
440
- info('Press Enter to open browser, or paste your key:');
441
- blank();
442
- while (true) {
443
- const answer = await prompt(' > ');
444
- if (!answer) {
445
- // Open browser
446
- openBrowser('https://simplefunctions.dev/dashboard');
447
- info(dim('Browser opened. Paste your key here once you have it:'));
448
- continue;
449
- }
450
- info(dim('Validating...'));
451
- const result = await validateSFKey(answer, apiUrl);
452
- if (result.valid) {
453
- ok(result.msg);
454
- blank();
455
- return answer;
456
- }
457
- else {
458
- fail(result.msg);
459
- }
460
- }
461
- }
462
- async function promptForOpenRouterKey() {
463
- info(`Requires an OpenRouter API key. Get one at ${cyan('https://openrouter.ai/settings/keys')}.`);
464
- info('Press Enter to skip (agent unavailable), or paste key:');
465
- blank();
466
- const answer = await prompt(' > ');
467
- if (!answer) {
468
- info(dim('Skipped.'));
469
- blank();
470
- return undefined;
471
- }
472
- info(dim('Validating...'));
473
- const result = await validateOpenRouterKey(answer);
474
- if (result.valid) {
475
- ok(result.msg);
476
- }
477
- else {
478
- fail(result.msg);
479
- info(dim('Saved. You can re-run sf setup later to fix this.'));
480
- }
481
- blank();
482
- return answer;
483
- }
484
- async function promptForKalshi(config) {
485
- info(`Connect Kalshi to view your positions and P&L.`);
486
- info(`Requires an API Key ID and private key file.`);
487
- info(`Get them at ${cyan('https://kalshi.com/account/api-keys')}.`);
488
- info('Press Enter to skip, or paste Key ID:');
489
- blank();
490
- const keyId = await prompt(' > ');
491
- if (!keyId) {
492
- info(dim('Skipped.'));
493
- blank();
494
- return;
495
- }
496
- info('Private key file path (default ~/.kalshi/private.pem):');
497
- const keyPathInput = await prompt(' > ');
498
- const keyPath = keyPathInput || '~/.kalshi/private.pem';
499
- config.kalshiKeyId = keyId;
500
- config.kalshiPrivateKeyPath = keyPath;
501
- // Temporarily set for validation
502
- process.env.KALSHI_API_KEY_ID = keyId;
503
- process.env.KALSHI_PRIVATE_KEY_PATH = keyPath;
504
- info(dim('Validating...'));
505
- const result = await validateKalshi();
506
- if (result.valid) {
507
- ok(result.msg);
508
- }
509
- else {
510
- fail(result.msg);
511
- info(dim('Saved. You can re-run sf setup later to fix this.'));
512
- }
513
- blank();
514
- }
515
- async function promptForTavily() {
516
- info(`Tavily API powers the agent's web_search tool.`);
517
- info(`Get a free key at ${cyan('https://tavily.com')}.`);
518
- info('Press Enter to skip:');
519
- blank();
520
- const answer = await prompt(' > ');
521
- if (!answer) {
522
- info(dim('Skipped.'));
523
- blank();
524
- return undefined;
525
- }
526
- info(dim('Validating...'));
527
- const result = await validateTavily(answer);
528
- if (result.valid) {
529
- ok(result.msg);
530
- }
531
- else {
532
- fail(result.msg);
533
- info(dim('Saved. You can re-run sf setup later to fix this.'));
534
- }
535
- blank();
536
- return answer;
537
- }
538
- async function promptForPolymarket(config) {
539
- info('Connect Polymarket to view positions and scan orderbooks.');
540
- info('Your Polygon wallet address is needed (starts with 0x...).');
541
- info(`Find it at ${cyan('https://polymarket.com')} → Settings → Profile.`);
542
- info('Press Enter to skip:');
543
- blank();
544
- const walletAddress = await prompt(' Wallet address > ');
545
- if (!walletAddress) {
546
- info(dim('Skipped.'));
547
- blank();
548
- return;
549
- }
550
- if (!walletAddress.startsWith('0x') || walletAddress.length < 40) {
551
- fail('Invalid wallet address (must start with 0x and be 42 characters)');
552
- info(dim('Saved anyway. You can fix it later with sf setup.'));
553
- }
554
- else {
555
- ok(`Wallet: ${mask(walletAddress)}`);
556
- }
557
- config.polymarketWalletAddress = walletAddress;
558
- // Optionally configure private key for future trading
559
- info(dim('Private key (for future trading) — press Enter to skip:'));
560
- const keyPath = await prompt(' Key path > ');
561
- if (keyPath) {
562
- config.polymarketPrivateKeyPath = keyPath;
563
- ok(`Private key path: ${dim(keyPath)}`);
564
- }
565
- blank();
566
- }
567
- // ─── Step 7: Thesis ──────────────────────────────────────────────────────────
568
- async function handleThesisStep(config) {
569
- try {
570
- const client = new client_js_1.SFClient(config.apiKey, config.apiUrl);
571
- const data = await client.listTheses();
572
- const theses = data.theses || [];
573
- const activeTheses = theses.filter((t) => t.status === 'active');
574
- if (activeTheses.length > 0) {
575
- console.log(` ${bold('Step 7: Theses')}`);
576
- blank();
577
- ok(`Found ${activeTheses.length} active thesis(es):`);
578
- for (const t of activeTheses.slice(0, 5)) {
579
- const conf = typeof t.confidence === 'number' ? Math.round(t.confidence * 100) : 0;
580
- const thesis = (t.rawThesis || t.thesis || t.title || '').slice(0, 60);
581
- info(` ${dim(t.id.slice(0, 8))} — ${thesis} — ${conf}%`);
582
- }
583
- info(dim('Skipping creation.'));
584
- blank();
585
- // Offer to launch agent
586
- if (config.openrouterKey) {
587
- console.log(` ${dim('─'.repeat(25))}`);
588
- console.log(` ${bold('All set!')}`);
589
- blank();
590
- info(` ${cyan('sf agent')} Chat with your thesis`);
591
- info(` ${cyan('sf context <id>')} View thesis snapshot`);
592
- info(` ${cyan('sf positions')} View positions`);
593
- info(` ${cyan('sf setup --check')} Check config`);
594
- blank();
595
- const shouldLaunch = await promptYN(` Launch agent now? (Y/n) `);
596
- if (shouldLaunch) {
597
- blank();
598
- info('Launching...');
599
- blank();
600
- await (0, agent_js_1.agentCommand)(activeTheses[0].id, { model: config.model });
601
- }
602
- }
603
- else {
604
- blank();
605
- console.log(` ${bold('All set!')}`);
606
- blank();
607
- info(` ${cyan('sf list')} List all theses`);
608
- info(` ${cyan('sf context <id>')} View thesis snapshot`);
609
- info(` ${cyan('sf positions')} View positions`);
610
- info(` ${cyan('sf setup --check')} Check config`);
611
- blank();
612
- }
613
- return;
614
- }
615
- // No theses — offer to create one
616
- console.log(` ${bold('Step 7: Create Your First Thesis')}`);
617
- blank();
618
- info('A thesis is your core market conviction. The system builds a causal model');
619
- info('from it, then continuously scans prediction markets for mispriced contracts.');
620
- blank();
621
- info('Examples:');
622
- info(` ${dim('"The Fed won\'t cut rates in 2026 — inflation stays elevated due to oil prices"')}`);
623
- info(` ${dim('"AI-driven layoffs cause consumer spending to contract, S&P drops 20% by year-end"')}`);
624
- info(` ${dim('"Trump can\'t exit the Iran conflict — oil stays above $100 for six months"')}`);
625
- blank();
626
- const thesis = await prompt(' Enter your thesis (press Enter to skip, use sf create later):\n > ');
627
- if (!thesis) {
628
- blank();
629
- info(dim('Skipped. Use sf create "your thesis" to create one later.'));
630
- blank();
631
- showFinalHints(config);
632
- return;
633
- }
634
- blank();
635
- info('Building causal model... (~30s)');
636
- blank();
637
- try {
638
- const result = await client.createThesis(thesis, true);
639
- if (result.id) {
640
- const nodeCount = result.causalTree?.nodes?.length || 0;
641
- const edgeCount = result.edgeAnalysis?.edges?.length || 0;
642
- const totalMarkets = result.edgeAnalysis?.totalMarketsAnalyzed || 0;
643
- const confidence = Math.round((parseFloat(result.confidence) || 0.5) * 100);
644
- ok(`Causal tree: ${nodeCount} node(s)`);
645
- ok(`Scanned ${totalMarkets} markets, found ${edgeCount} contract(s) with edge`);
646
- ok(`Confidence: ${confidence}%`);
647
- ok(`Thesis ID: ${result.id.slice(0, 8)}`);
648
- blank();
649
- // Offer to launch agent
650
- if (config.openrouterKey) {
651
- console.log(` ${dim('─'.repeat(25))}`);
652
- console.log(` ${bold('All set!')}`);
653
- blank();
654
- const shouldLaunch = await promptYN(` Launch agent now? (Y/n) `);
655
- if (shouldLaunch) {
656
- blank();
657
- info('Launching...');
658
- blank();
659
- await (0, agent_js_1.agentCommand)(result.id, { model: config.model });
660
- }
661
- else {
662
- blank();
663
- showFinalHints(config);
664
- }
665
- }
666
- else {
667
- showFinalHints(config);
668
- }
669
- }
670
- else {
671
- fail(`Creation failed: ${result.error || 'unknown error'}`);
672
- info(dim('You can retry later with sf create "your thesis"'));
673
- blank();
674
- showFinalHints(config);
675
- }
676
- }
677
- catch (err) {
678
- fail(`Creation failed: ${err.message}`);
679
- info(dim('You can retry later with sf create "your thesis"'));
680
- blank();
681
- showFinalHints(config);
682
- }
683
- }
684
- catch {
685
- // Can't connect to API, skip thesis step
686
- blank();
687
- showFinalHints(config);
688
- }
689
- }
690
- function showFinalHints(config) {
691
- console.log(` ${dim('─'.repeat(25))}`);
692
- console.log(` ${bold('All set!')}`);
693
- blank();
694
- info(` ${cyan('sf agent')} Chat with your thesis`);
695
- info(` ${cyan('sf list')} List all theses`);
696
- info(` ${cyan('sf context <id>')} View thesis snapshot`);
697
- info(` ${cyan('sf positions')} View positions`);
698
- info(` ${cyan('sf setup --check')} Check config`);
699
- blank();
700
- }