@spfunctions/cli 1.6.1 → 1.7.1
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.
- package/dist/client.d.ts +2 -0
- package/dist/client.js +16 -0
- package/dist/commands/agent.js +44 -0
- package/dist/commands/context.d.ts +1 -1
- package/dist/commands/context.js +57 -0
- package/dist/index.js +5 -5
- package/dist/telegram/agent-bridge.js +20 -0
- package/package.json +1 -1
package/dist/client.d.ts
CHANGED
|
@@ -33,3 +33,5 @@ export declare function kalshiFetchEvents(seriesTicker: string): Promise<any[]>;
|
|
|
33
33
|
export declare function kalshiFetchMarket(ticker: string): Promise<any>;
|
|
34
34
|
export declare function kalshiFetchMarketsBySeries(seriesTicker: string): Promise<any[]>;
|
|
35
35
|
export declare function kalshiFetchMarketsByEvent(eventTicker: string): Promise<any[]>;
|
|
36
|
+
export declare function fetchGlobalContext(): Promise<any>;
|
|
37
|
+
export declare function fetchQuery(q: string): Promise<any>;
|
package/dist/client.js
CHANGED
|
@@ -12,6 +12,8 @@ exports.kalshiFetchEvents = kalshiFetchEvents;
|
|
|
12
12
|
exports.kalshiFetchMarket = kalshiFetchMarket;
|
|
13
13
|
exports.kalshiFetchMarketsBySeries = kalshiFetchMarketsBySeries;
|
|
14
14
|
exports.kalshiFetchMarketsByEvent = kalshiFetchMarketsByEvent;
|
|
15
|
+
exports.fetchGlobalContext = fetchGlobalContext;
|
|
16
|
+
exports.fetchQuery = fetchQuery;
|
|
15
17
|
const DEFAULT_API_URL = 'https://simplefunctions.dev';
|
|
16
18
|
const KALSHI_BASE = 'https://api.elections.kalshi.com/trade-api/v2';
|
|
17
19
|
// ===== SF API Client =====
|
|
@@ -154,3 +156,17 @@ async function kalshiFetchMarketsByEvent(eventTicker) {
|
|
|
154
156
|
});
|
|
155
157
|
return data.markets || [];
|
|
156
158
|
}
|
|
159
|
+
// ===== Public Endpoints (no auth) =====
|
|
160
|
+
const SF_PUBLIC_BASE = 'https://simplefunctions.dev';
|
|
161
|
+
async function fetchGlobalContext() {
|
|
162
|
+
const res = await fetch(`${SF_PUBLIC_BASE}/api/public/context`);
|
|
163
|
+
if (!res.ok)
|
|
164
|
+
throw new Error(`Context API error: ${res.status}`);
|
|
165
|
+
return res.json();
|
|
166
|
+
}
|
|
167
|
+
async function fetchQuery(q) {
|
|
168
|
+
const res = await fetch(`${SF_PUBLIC_BASE}/api/public/query?q=${encodeURIComponent(q)}`);
|
|
169
|
+
if (!res.ok)
|
|
170
|
+
throw new Error(`Query API error: ${res.status}`);
|
|
171
|
+
return res.json();
|
|
172
|
+
}
|
package/dist/commands/agent.js
CHANGED
|
@@ -746,6 +746,30 @@ async function agentCommand(thesisId, opts) {
|
|
|
746
746
|
};
|
|
747
747
|
},
|
|
748
748
|
},
|
|
749
|
+
{
|
|
750
|
+
name: 'global_context',
|
|
751
|
+
label: 'Market Snapshot',
|
|
752
|
+
description: 'Global market snapshot — top movers, expiring contracts, milestones, liquidity, signals. No thesis needed.',
|
|
753
|
+
parameters: emptyParams,
|
|
754
|
+
execute: async () => {
|
|
755
|
+
const { fetchGlobalContext } = await import('../client.js');
|
|
756
|
+
const data = await fetchGlobalContext();
|
|
757
|
+
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }], details: {} };
|
|
758
|
+
},
|
|
759
|
+
},
|
|
760
|
+
{
|
|
761
|
+
name: 'query',
|
|
762
|
+
label: 'Query',
|
|
763
|
+
description: 'LLM-enhanced prediction market knowledge search. Ask any question about prediction markets, macro, geopolitics. Returns structured answer with live market prices, thesis data, and key factors.',
|
|
764
|
+
parameters: Type.Object({
|
|
765
|
+
q: Type.String({ description: 'Natural language query (e.g. "iran oil prices", "fed rate cut 2026")' }),
|
|
766
|
+
}),
|
|
767
|
+
execute: async (_toolCallId, params) => {
|
|
768
|
+
const { fetchQuery } = await import('../client.js');
|
|
769
|
+
const data = await fetchQuery(params.q);
|
|
770
|
+
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }], details: {} };
|
|
771
|
+
},
|
|
772
|
+
},
|
|
749
773
|
{
|
|
750
774
|
name: 'inject_signal',
|
|
751
775
|
label: 'Inject Signal',
|
|
@@ -2540,6 +2564,26 @@ async function runPlainTextAgent(params) {
|
|
|
2540
2564
|
return { content: [{ type: 'text', text: JSON.stringify(ctx, null, 2) }], details: {} };
|
|
2541
2565
|
},
|
|
2542
2566
|
},
|
|
2567
|
+
{
|
|
2568
|
+
name: 'global_context', label: 'Market Snapshot',
|
|
2569
|
+
description: 'Global market snapshot — top movers, expiring contracts, milestones, liquidity, signals. No thesis needed.',
|
|
2570
|
+
parameters: emptyParams,
|
|
2571
|
+
execute: async () => {
|
|
2572
|
+
const { fetchGlobalContext } = await import('../client.js');
|
|
2573
|
+
const data = await fetchGlobalContext();
|
|
2574
|
+
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }], details: {} };
|
|
2575
|
+
},
|
|
2576
|
+
},
|
|
2577
|
+
{
|
|
2578
|
+
name: 'query', label: 'Query',
|
|
2579
|
+
description: 'LLM-enhanced prediction market knowledge search. Returns structured answer with live prices, thesis data, key factors.',
|
|
2580
|
+
parameters: Type.Object({ q: Type.String({ description: 'Natural language query' }) }),
|
|
2581
|
+
execute: async (_id, p) => {
|
|
2582
|
+
const { fetchQuery } = await import('../client.js');
|
|
2583
|
+
const data = await fetchQuery(p.q);
|
|
2584
|
+
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }], details: {} };
|
|
2585
|
+
},
|
|
2586
|
+
},
|
|
2543
2587
|
{
|
|
2544
2588
|
name: 'inject_signal', label: 'Inject Signal',
|
|
2545
2589
|
description: 'Inject a signal into the thesis',
|
package/dist/commands/context.js
CHANGED
|
@@ -5,6 +5,63 @@ const client_js_1 = require("../client.js");
|
|
|
5
5
|
const kalshi_js_1 = require("../kalshi.js");
|
|
6
6
|
const utils_js_1 = require("../utils.js");
|
|
7
7
|
async function contextCommand(id, opts) {
|
|
8
|
+
// No thesis ID → global market snapshot
|
|
9
|
+
if (!id) {
|
|
10
|
+
const res = await fetch('https://simplefunctions.dev/api/public/context');
|
|
11
|
+
if (!res.ok) {
|
|
12
|
+
console.error(` Error: ${res.status} ${await res.text()}`);
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
const data = await res.json();
|
|
16
|
+
if (opts.json) {
|
|
17
|
+
console.log(JSON.stringify(data, null, 2));
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
console.log(`\n${utils_js_1.c.bold}Market Snapshot${utils_js_1.c.reset} ${(0, utils_js_1.shortDate)(data.snapshotAt)}\n`);
|
|
21
|
+
if (data.movers?.length > 0) {
|
|
22
|
+
console.log(`${utils_js_1.c.bold}Movers (24h)${utils_js_1.c.reset}`);
|
|
23
|
+
for (const m of data.movers.slice(0, 10)) {
|
|
24
|
+
const venue = m.venue === 'kalshi' ? `${utils_js_1.c.cyan}K${utils_js_1.c.reset}` : `${utils_js_1.c.magenta}P${utils_js_1.c.reset}`;
|
|
25
|
+
const ch = m.change24h > 0 ? `${utils_js_1.c.green}+${m.change24h}¢${utils_js_1.c.reset}` : `${utils_js_1.c.red}${m.change24h}¢${utils_js_1.c.reset}`;
|
|
26
|
+
console.log(` ${venue} ${String(m.price).padStart(3)}¢ ${ch.padStart(16)} ${m.title.slice(0, 55)}`);
|
|
27
|
+
}
|
|
28
|
+
console.log();
|
|
29
|
+
}
|
|
30
|
+
if (data.milestones?.length > 0) {
|
|
31
|
+
console.log(`${utils_js_1.c.bold}Upcoming (48h)${utils_js_1.c.reset}`);
|
|
32
|
+
for (const m of data.milestones.slice(0, 8)) {
|
|
33
|
+
console.log(` ${utils_js_1.c.dim}${String(m.hoursUntil).padStart(3)}h${utils_js_1.c.reset} ${m.title.slice(0, 55)} ${utils_js_1.c.dim}${m.category}${utils_js_1.c.reset}`);
|
|
34
|
+
}
|
|
35
|
+
console.log();
|
|
36
|
+
}
|
|
37
|
+
if (data.expiring?.length > 0) {
|
|
38
|
+
console.log(`${utils_js_1.c.bold}Expiring (7d)${utils_js_1.c.reset}`);
|
|
39
|
+
for (const m of data.expiring.slice(0, 8)) {
|
|
40
|
+
const venue = m.venue === 'kalshi' ? `${utils_js_1.c.cyan}K${utils_js_1.c.reset}` : `${utils_js_1.c.magenta}P${utils_js_1.c.reset}`;
|
|
41
|
+
console.log(` ${venue} ${String(m.price).padStart(3)}¢ ${utils_js_1.c.dim}${String(m.hoursUntil).padStart(3)}h${utils_js_1.c.reset} ${m.title.slice(0, 55)}`);
|
|
42
|
+
}
|
|
43
|
+
console.log();
|
|
44
|
+
}
|
|
45
|
+
if (data.liquid?.length > 0) {
|
|
46
|
+
console.log(`${utils_js_1.c.bold}Liquid${utils_js_1.c.reset}`);
|
|
47
|
+
for (const m of data.liquid.slice(0, 8)) {
|
|
48
|
+
const venue = m.venue === 'kalshi' ? `${utils_js_1.c.cyan}K${utils_js_1.c.reset}` : `${utils_js_1.c.magenta}P${utils_js_1.c.reset}`;
|
|
49
|
+
console.log(` ${venue} ${String(m.price).padStart(3)}¢ spread ${m.spread}¢ ${m.title.slice(0, 55)}`);
|
|
50
|
+
}
|
|
51
|
+
console.log();
|
|
52
|
+
}
|
|
53
|
+
if (data.signals?.length > 0) {
|
|
54
|
+
console.log(`${utils_js_1.c.bold}Recent Signals${utils_js_1.c.reset}`);
|
|
55
|
+
for (const s of data.signals.slice(0, 5)) {
|
|
56
|
+
const d = s.confidenceDelta > 0 ? `${utils_js_1.c.green}▲${s.confidenceDelta}${utils_js_1.c.reset}` : s.confidenceDelta < 0 ? `${utils_js_1.c.red}▼${s.confidenceDelta}${utils_js_1.c.reset}` : `${s.confidenceDelta}`;
|
|
57
|
+
console.log(` ${d} ${s.confidence}% ${s.summary.slice(0, 60)}`);
|
|
58
|
+
console.log(` ${utils_js_1.c.dim}${s.thesisTitle.slice(0, 40)} ${(0, utils_js_1.shortDate)(s.evaluatedAt)}${utils_js_1.c.reset}`);
|
|
59
|
+
}
|
|
60
|
+
console.log();
|
|
61
|
+
}
|
|
62
|
+
console.log(` ${utils_js_1.c.dim}Create a thesis for focused context: sf create "your market view"${utils_js_1.c.reset}\n`);
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
8
65
|
const client = new client_js_1.SFClient(opts.apiKey, opts.apiUrl);
|
|
9
66
|
const ctx = await client.getContext(id);
|
|
10
67
|
if (opts.json) {
|
package/dist/index.js
CHANGED
|
@@ -77,7 +77,7 @@ const GROUPED_HELP = `
|
|
|
77
77
|
\x1b[1mThesis\x1b[22m
|
|
78
78
|
\x1b[36mlist\x1b[39m List all theses
|
|
79
79
|
\x1b[36mget\x1b[39m <id> Full thesis details
|
|
80
|
-
\x1b[36mcontext\x1b[39m
|
|
80
|
+
\x1b[36mcontext\x1b[39m [id] [--json] Market snapshot (no id) or thesis context (with id)
|
|
81
81
|
\x1b[36mcreate\x1b[39m "thesis" Create a new thesis
|
|
82
82
|
\x1b[36msignal\x1b[39m <id> "content" Inject a signal
|
|
83
83
|
\x1b[36mevaluate\x1b[39m <id> Trigger deep evaluation
|
|
@@ -221,7 +221,7 @@ async function interactiveEntry() {
|
|
|
221
221
|
console.log();
|
|
222
222
|
}
|
|
223
223
|
// ── Pre-action guard: check configuration ────────────────────────────────────
|
|
224
|
-
const NO_CONFIG_COMMANDS = new Set(['setup', 'help', 'scan', 'explore', 'query', 'milestones', 'forecast', 'settlements', 'balance', 'orders', 'fills', 'schedule', 'announcements', 'history', 'liquidity', 'book', 'prompt', 'sf']);
|
|
224
|
+
const NO_CONFIG_COMMANDS = new Set(['setup', 'help', 'scan', 'explore', 'query', 'context', 'milestones', 'forecast', 'settlements', 'balance', 'orders', 'fills', 'schedule', 'announcements', 'history', 'liquidity', 'book', 'prompt', 'sf']);
|
|
225
225
|
program.hook('preAction', (thisCommand, actionCommand) => {
|
|
226
226
|
const cmdName = actionCommand.name();
|
|
227
227
|
if (NO_CONFIG_COMMANDS.has(cmdName))
|
|
@@ -279,10 +279,10 @@ program
|
|
|
279
279
|
const g = cmd.optsWithGlobals();
|
|
280
280
|
await run(() => (0, get_js_1.getCommand)(id, { json: opts.json, apiKey: g.apiKey, apiUrl: g.apiUrl }));
|
|
281
281
|
});
|
|
282
|
-
// ── sf context
|
|
282
|
+
// ── sf context [id] ───────────────────────────────────────────────────────────
|
|
283
283
|
program
|
|
284
|
-
.command('context
|
|
285
|
-
.description('
|
|
284
|
+
.command('context [id]')
|
|
285
|
+
.description('Context snapshot. With ID: thesis-specific. Without: global market snapshot (no auth)')
|
|
286
286
|
.option('--json', 'Output raw JSON')
|
|
287
287
|
.action(async (id, opts, cmd) => {
|
|
288
288
|
const g = cmd.optsWithGlobals();
|
|
@@ -38,6 +38,26 @@ async function buildTools(sfClient, thesisId, latestContext) {
|
|
|
38
38
|
return { content: [{ type: 'text', text: JSON.stringify(ctx, null, 2) }], details: {} };
|
|
39
39
|
},
|
|
40
40
|
},
|
|
41
|
+
{
|
|
42
|
+
name: 'global_context', label: 'Snapshot',
|
|
43
|
+
description: 'Global market snapshot — movers, expiring, milestones, liquidity, signals. No thesis needed.',
|
|
44
|
+
parameters: emptyParams,
|
|
45
|
+
execute: async () => {
|
|
46
|
+
const { fetchGlobalContext } = await import('../client.js');
|
|
47
|
+
const data = await fetchGlobalContext();
|
|
48
|
+
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }], details: {} };
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
name: 'query', label: 'Query',
|
|
53
|
+
description: 'LLM-enhanced prediction market search. Returns answer, live prices, key factors.',
|
|
54
|
+
parameters: Type.Object({ q: Type.String({ description: 'Question' }) }),
|
|
55
|
+
execute: async (_id, p) => {
|
|
56
|
+
const { fetchQuery } = await import('../client.js');
|
|
57
|
+
const data = await fetchQuery(p.q);
|
|
58
|
+
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }], details: {} };
|
|
59
|
+
},
|
|
60
|
+
},
|
|
41
61
|
{
|
|
42
62
|
name: 'inject_signal', label: 'Signal',
|
|
43
63
|
description: 'Inject a signal (news, note, observation) into the thesis',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@spfunctions/cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.7.1",
|
|
4
4
|
"description": "Prediction market intelligence CLI. Causal thesis model, 24/7 Kalshi/Polymarket scan, live orderbook, edge detection. Interactive agent mode with tool calling.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"sf": "./dist/index.js"
|