@spfunctions/cli 1.1.2 → 1.1.4
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/commands/agent.js +233 -31
- package/dist/commands/edges.d.ts +21 -0
- package/dist/commands/edges.js +205 -0
- package/dist/commands/setup.d.ts +20 -0
- package/dist/commands/setup.js +569 -0
- package/dist/config.d.ts +50 -0
- package/dist/config.js +117 -0
- package/dist/index.d.ts +6 -3
- package/dist/index.js +54 -11
- package/package.json +1 -1
package/dist/config.js
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* CLI Configuration — ~/.sf/config.json
|
|
4
|
+
*
|
|
5
|
+
* Priority: env vars > config file > defaults
|
|
6
|
+
*
|
|
7
|
+
* After `sf setup`, all keys are stored in config.json.
|
|
8
|
+
* `applyConfig()` sets process.env from config so all existing code
|
|
9
|
+
* (client.ts, kalshi.ts, agent.ts) keeps working without changes.
|
|
10
|
+
*/
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.loadFileConfig = loadFileConfig;
|
|
16
|
+
exports.loadConfig = loadConfig;
|
|
17
|
+
exports.saveConfig = saveConfig;
|
|
18
|
+
exports.resetConfig = resetConfig;
|
|
19
|
+
exports.applyConfig = applyConfig;
|
|
20
|
+
exports.isConfigured = isConfigured;
|
|
21
|
+
exports.getConfigPath = getConfigPath;
|
|
22
|
+
const fs_1 = __importDefault(require("fs"));
|
|
23
|
+
const path_1 = __importDefault(require("path"));
|
|
24
|
+
const os_1 = __importDefault(require("os"));
|
|
25
|
+
const CONFIG_DIR = path_1.default.join(os_1.default.homedir(), '.sf');
|
|
26
|
+
const CONFIG_PATH = path_1.default.join(CONFIG_DIR, 'config.json');
|
|
27
|
+
const DEFAULT_API_URL = 'https://simplefunctions.dev';
|
|
28
|
+
const DEFAULT_MODEL = 'anthropic/claude-sonnet-4.6';
|
|
29
|
+
/**
|
|
30
|
+
* Load config from file. Does NOT apply env overrides — use resolveConfig() for that.
|
|
31
|
+
*/
|
|
32
|
+
function loadFileConfig() {
|
|
33
|
+
try {
|
|
34
|
+
if (fs_1.default.existsSync(CONFIG_PATH)) {
|
|
35
|
+
return JSON.parse(fs_1.default.readFileSync(CONFIG_PATH, 'utf-8'));
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
catch { /* corrupt file, ignore */ }
|
|
39
|
+
return {};
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Resolve final config: env vars > config file > defaults.
|
|
43
|
+
*/
|
|
44
|
+
function loadConfig() {
|
|
45
|
+
const file = loadFileConfig();
|
|
46
|
+
return {
|
|
47
|
+
apiKey: process.env.SF_API_KEY || file.apiKey,
|
|
48
|
+
apiUrl: process.env.SF_API_URL || file.apiUrl || DEFAULT_API_URL,
|
|
49
|
+
openrouterKey: process.env.OPENROUTER_API_KEY || file.openrouterKey,
|
|
50
|
+
kalshiKeyId: process.env.KALSHI_API_KEY_ID || file.kalshiKeyId,
|
|
51
|
+
kalshiPrivateKeyPath: process.env.KALSHI_PRIVATE_KEY_PATH || file.kalshiPrivateKeyPath,
|
|
52
|
+
tavilyKey: process.env.TAVILY_API_KEY || file.tavilyKey,
|
|
53
|
+
model: process.env.SF_MODEL || file.model || DEFAULT_MODEL,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Save config to ~/.sf/config.json.
|
|
58
|
+
*/
|
|
59
|
+
function saveConfig(config) {
|
|
60
|
+
fs_1.default.mkdirSync(CONFIG_DIR, { recursive: true });
|
|
61
|
+
fs_1.default.writeFileSync(CONFIG_PATH, JSON.stringify({ ...config, configuredAt: new Date().toISOString() }, null, 2));
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Delete config file (for --reset).
|
|
65
|
+
*/
|
|
66
|
+
function resetConfig() {
|
|
67
|
+
try {
|
|
68
|
+
if (fs_1.default.existsSync(CONFIG_PATH)) {
|
|
69
|
+
fs_1.default.unlinkSync(CONFIG_PATH);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
catch { /* ignore */ }
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Apply config to process.env.
|
|
76
|
+
*
|
|
77
|
+
* Call this ONCE at CLI startup, before any command runs.
|
|
78
|
+
* This means client.ts, kalshi.ts, agent.ts etc. keep reading process.env
|
|
79
|
+
* and just work — no code changes needed in those files.
|
|
80
|
+
*
|
|
81
|
+
* Env vars already set by the user take priority (we only fill gaps).
|
|
82
|
+
*/
|
|
83
|
+
function applyConfig() {
|
|
84
|
+
const file = loadFileConfig();
|
|
85
|
+
// Only set process.env if not already set (env vars > config file)
|
|
86
|
+
if (!process.env.SF_API_KEY && file.apiKey) {
|
|
87
|
+
process.env.SF_API_KEY = file.apiKey;
|
|
88
|
+
}
|
|
89
|
+
if (!process.env.SF_API_URL && file.apiUrl) {
|
|
90
|
+
process.env.SF_API_URL = file.apiUrl;
|
|
91
|
+
}
|
|
92
|
+
if (!process.env.OPENROUTER_API_KEY && file.openrouterKey) {
|
|
93
|
+
process.env.OPENROUTER_API_KEY = file.openrouterKey;
|
|
94
|
+
}
|
|
95
|
+
if (!process.env.KALSHI_API_KEY_ID && file.kalshiKeyId) {
|
|
96
|
+
process.env.KALSHI_API_KEY_ID = file.kalshiKeyId;
|
|
97
|
+
}
|
|
98
|
+
if (!process.env.KALSHI_PRIVATE_KEY_PATH && file.kalshiPrivateKeyPath) {
|
|
99
|
+
process.env.KALSHI_PRIVATE_KEY_PATH = file.kalshiPrivateKeyPath;
|
|
100
|
+
}
|
|
101
|
+
if (!process.env.TAVILY_API_KEY && file.tavilyKey) {
|
|
102
|
+
process.env.TAVILY_API_KEY = file.tavilyKey;
|
|
103
|
+
}
|
|
104
|
+
if (!process.env.SF_MODEL && file.model) {
|
|
105
|
+
process.env.SF_MODEL = file.model;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Check if SF API key is configured (from any source).
|
|
110
|
+
*/
|
|
111
|
+
function isConfigured() {
|
|
112
|
+
const config = loadConfig();
|
|
113
|
+
return !!config.apiKey;
|
|
114
|
+
}
|
|
115
|
+
function getConfigPath() {
|
|
116
|
+
return CONFIG_PATH;
|
|
117
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -6,12 +6,15 @@
|
|
|
6
6
|
* Zero heavy dependencies: commander + native fetch.
|
|
7
7
|
*
|
|
8
8
|
* Usage:
|
|
9
|
-
* sf
|
|
10
|
-
* sf
|
|
11
|
-
* sf
|
|
9
|
+
* sf setup — Interactive configuration wizard
|
|
10
|
+
* sf list — List all theses
|
|
11
|
+
* sf get <id> — Full thesis details
|
|
12
|
+
* sf context <id> [--json] — Thesis context snapshot
|
|
12
13
|
* sf create "thesis text" [--async]
|
|
13
14
|
* sf signal <id> "content" [--type news|user_note|external]
|
|
14
15
|
* sf evaluate <id>
|
|
15
16
|
* sf scan "keywords" [--series TICKER] [--market TICKER] [--json]
|
|
17
|
+
* sf positions — Kalshi positions with edge overlay
|
|
18
|
+
* sf agent [thesisId] — Interactive agent mode
|
|
16
19
|
*/
|
|
17
20
|
export {};
|
package/dist/index.js
CHANGED
|
@@ -7,16 +7,20 @@
|
|
|
7
7
|
* Zero heavy dependencies: commander + native fetch.
|
|
8
8
|
*
|
|
9
9
|
* Usage:
|
|
10
|
-
* sf
|
|
11
|
-
* sf
|
|
12
|
-
* sf
|
|
10
|
+
* sf setup — Interactive configuration wizard
|
|
11
|
+
* sf list — List all theses
|
|
12
|
+
* sf get <id> — Full thesis details
|
|
13
|
+
* sf context <id> [--json] — Thesis context snapshot
|
|
13
14
|
* sf create "thesis text" [--async]
|
|
14
15
|
* sf signal <id> "content" [--type news|user_note|external]
|
|
15
16
|
* sf evaluate <id>
|
|
16
17
|
* sf scan "keywords" [--series TICKER] [--market TICKER] [--json]
|
|
18
|
+
* sf positions — Kalshi positions with edge overlay
|
|
19
|
+
* sf agent [thesisId] — Interactive agent mode
|
|
17
20
|
*/
|
|
18
21
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
22
|
const commander_1 = require("commander");
|
|
23
|
+
const config_js_1 = require("./config.js");
|
|
20
24
|
const list_js_1 = require("./commands/list.js");
|
|
21
25
|
const get_js_1 = require("./commands/get.js");
|
|
22
26
|
const context_js_1 = require("./commands/context.js");
|
|
@@ -25,8 +29,13 @@ const signal_js_1 = require("./commands/signal.js");
|
|
|
25
29
|
const evaluate_js_1 = require("./commands/evaluate.js");
|
|
26
30
|
const scan_js_1 = require("./commands/scan.js");
|
|
27
31
|
const positions_js_1 = require("./commands/positions.js");
|
|
32
|
+
const edges_js_1 = require("./commands/edges.js");
|
|
28
33
|
const agent_js_1 = require("./commands/agent.js");
|
|
34
|
+
const setup_js_1 = require("./commands/setup.js");
|
|
29
35
|
const utils_js_1 = require("./utils.js");
|
|
36
|
+
// ── Apply ~/.sf/config.json to process.env BEFORE any command ────────────────
|
|
37
|
+
// This means client.ts, kalshi.ts, agent.ts keep reading process.env and just work.
|
|
38
|
+
(0, config_js_1.applyConfig)();
|
|
30
39
|
const program = new commander_1.Command();
|
|
31
40
|
program
|
|
32
41
|
.name('sf')
|
|
@@ -34,14 +43,33 @@ program
|
|
|
34
43
|
.version('0.1.0')
|
|
35
44
|
.option('--api-key <key>', 'API key (or set SF_API_KEY env var)')
|
|
36
45
|
.option('--api-url <url>', 'API base URL (or set SF_API_URL env var)');
|
|
37
|
-
//
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
46
|
+
// ── Pre-action guard: check configuration ────────────────────────────────────
|
|
47
|
+
const NO_CONFIG_COMMANDS = new Set(['setup', 'help', 'scan']);
|
|
48
|
+
program.hook('preAction', (thisCommand) => {
|
|
49
|
+
const cmdName = thisCommand.name();
|
|
50
|
+
if (NO_CONFIG_COMMANDS.has(cmdName))
|
|
51
|
+
return;
|
|
52
|
+
// --api-key flag overrides config check
|
|
53
|
+
const g = thisCommand.optsWithGlobals?.() || thisCommand.opts();
|
|
54
|
+
if (g.apiKey)
|
|
55
|
+
return;
|
|
56
|
+
if (!(0, config_js_1.isConfigured)()) {
|
|
57
|
+
console.log();
|
|
58
|
+
console.log(' SimpleFunctions 未配置。运行 \x1b[36msf setup\x1b[39m 开始。');
|
|
59
|
+
console.log();
|
|
60
|
+
process.exit(1);
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
// ── sf setup ──────────────────────────────────────────────────────────────────
|
|
64
|
+
program
|
|
65
|
+
.command('setup')
|
|
66
|
+
.description('Interactive configuration wizard')
|
|
67
|
+
.option('--check', 'Show current configuration status')
|
|
68
|
+
.option('--reset', 'Delete config and start over')
|
|
69
|
+
.option('--key <key>', 'Set SF API key (non-interactive, for CI)')
|
|
70
|
+
.action(async (opts) => {
|
|
71
|
+
await run(() => (0, setup_js_1.setupCommand)({ check: opts.check, reset: opts.reset, key: opts.key }));
|
|
72
|
+
});
|
|
45
73
|
// ── sf list ──────────────────────────────────────────────────────────────────
|
|
46
74
|
program
|
|
47
75
|
.command('list')
|
|
@@ -116,6 +144,21 @@ program
|
|
|
116
144
|
apiUrl: g.apiUrl,
|
|
117
145
|
}));
|
|
118
146
|
});
|
|
147
|
+
// ── sf edges ──────────────────────────────────────────────────────────────────
|
|
148
|
+
program
|
|
149
|
+
.command('edges')
|
|
150
|
+
.description('Top edges across all theses — what to trade now')
|
|
151
|
+
.option('--json', 'JSON output for agents')
|
|
152
|
+
.option('--limit <n>', 'Max edges to show', '20')
|
|
153
|
+
.action(async (opts, cmd) => {
|
|
154
|
+
const g = cmd.optsWithGlobals();
|
|
155
|
+
await run(() => (0, edges_js_1.edgesCommand)({
|
|
156
|
+
json: opts.json,
|
|
157
|
+
limit: opts.limit,
|
|
158
|
+
apiKey: g.apiKey,
|
|
159
|
+
apiUrl: g.apiUrl,
|
|
160
|
+
}));
|
|
161
|
+
});
|
|
119
162
|
// ── sf positions ──────────────────────────────────────────────────────────────
|
|
120
163
|
program
|
|
121
164
|
.command('positions')
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@spfunctions/cli",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.4",
|
|
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"
|