@alphafox/cli 0.2.0 → 0.3.3
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/README.md +42 -4
- package/dist/auth/loopback-callback.js +6 -6
- package/dist/catalog/command-tree.d.ts +1 -0
- package/dist/catalog/command-tree.js +5 -3
- package/dist/catalog/validate-body.d.ts +22 -0
- package/dist/catalog/validate-body.js +98 -0
- package/dist/commands/request-body.d.ts +21 -0
- package/dist/commands/request-body.js +92 -0
- package/dist/commands/run.js +113 -10
- package/dist/engine-backtest/errors.d.ts +18 -0
- package/dist/engine-backtest/errors.js +26 -0
- package/dist/engine-backtest/fetch-runtime.d.ts +38 -0
- package/dist/engine-backtest/fetch-runtime.js +170 -0
- package/dist/engine-backtest/native-import.d.ts +1 -0
- package/dist/engine-backtest/native-import.js +10 -0
- package/dist/engine-backtest/parse-args.d.ts +6 -0
- package/dist/engine-backtest/parse-args.js +281 -0
- package/dist/engine-backtest/persist.d.ts +32 -0
- package/dist/engine-backtest/persist.js +94 -0
- package/dist/engine-backtest/replay-timeframe.d.ts +16 -0
- package/dist/engine-backtest/replay-timeframe.js +48 -0
- package/dist/engine-backtest/resolve-packages.d.ts +27 -0
- package/dist/engine-backtest/resolve-packages.js +288 -0
- package/dist/engine-backtest/run-command.d.ts +38 -0
- package/dist/engine-backtest/run-command.js +540 -0
- package/dist/engine-backtest/types.d.ts +249 -0
- package/dist/engine-backtest/types.js +2 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +16 -1
- package/dist/install/exec.d.ts +13 -0
- package/dist/install/exec.js +77 -0
- package/dist/install/package-root.d.ts +4 -0
- package/dist/install/package-root.js +59 -0
- package/dist/install/types.d.ts +69 -0
- package/dist/install/types.js +26 -0
- package/dist/install/wizard.d.ts +21 -0
- package/dist/install/wizard.js +330 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/docs/.nojekyll +0 -0
- package/docs/alphafox-cli-installation-guide.md +105 -0
- package/docs/favicon.svg +4 -0
- package/docs/index.html +748 -0
- package/docs/logo/alphafox-mark.svg +4 -0
- package/docs/logo/alphafox-wordmark-black-en.svg +17 -0
- package/docs/logo/alphafox-wordmark-white-en.svg +16 -0
- package/docs/release-supply-chain.md +10 -2
- package/package.json +7 -2
- package/skills/account/SKILL.md +2 -2
- package/skills/admin/SKILL.md +2 -2
- package/skills/alphafox-shared/SKILL.md +22 -1
- package/skills/auth/SKILL.md +1 -1
- package/skills/engine-backtest/SKILL.md +71 -0
- package/skills/exchange/SKILL.md +2 -2
- package/skills/market/SKILL.md +1 -1
- package/skills/notification/SKILL.md +2 -2
- package/skills/strategy/SKILL.md +10 -2
- package/skills/trading/SKILL.md +6 -3
- package/vendor/backtest-runner/NOTICE.md +1 -0
- package/vendor/backtest-runner/README.md +97 -0
- package/vendor/backtest-runner/index.d.ts +423 -0
- package/vendor/backtest-runner/index.mjs +59 -0
- package/vendor/backtest-runner/lib/abortable.mjs +23 -0
- package/vendor/backtest-runner/lib/cache.mjs +159 -0
- package/vendor/backtest-runner/lib/coverage.mjs +238 -0
- package/vendor/backtest-runner/lib/encode.mjs +28 -0
- package/vendor/backtest-runner/lib/exchanges.mjs +143 -0
- package/vendor/backtest-runner/lib/proxy.mjs +78 -0
- package/vendor/backtest-runner/lib/scenario.mjs +66 -0
- package/vendor/backtest-runner/lib/series.mjs +370 -0
- package/vendor/backtest-runner/lib/tape-loader.mjs +614 -0
- package/vendor/backtest-runner/lib/timeframes.mjs +55 -0
- package/vendor/backtest-runner/package.json +13 -0
|
@@ -0,0 +1,330 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseInstallArgs = parseInstallArgs;
|
|
4
|
+
exports.semverLessThan = semverLessThan;
|
|
5
|
+
exports.parseNpmListVersion = parseNpmListVersion;
|
|
6
|
+
exports.skillsListHasAlphafox = skillsListHasAlphafox;
|
|
7
|
+
exports.nextSteps = nextSteps;
|
|
8
|
+
exports.runInstallWizard = runInstallWizard;
|
|
9
|
+
exports.installHelpData = installHelpData;
|
|
10
|
+
exports.resolveLocalSkillsDir = resolveLocalSkillsDir;
|
|
11
|
+
const node_fs_1 = require("node:fs");
|
|
12
|
+
const node_path_1 = require("node:path");
|
|
13
|
+
const version_1 = require("../version");
|
|
14
|
+
const exec_1 = require("./exec");
|
|
15
|
+
const package_root_1 = require("./package-root");
|
|
16
|
+
const types_1 = require("./types");
|
|
17
|
+
const NPM_TIMEOUT_MS = 120_000;
|
|
18
|
+
const SKILLS_TIMEOUT_MS = 120_000;
|
|
19
|
+
function parseInstallArgs(args) {
|
|
20
|
+
let noAuth = false;
|
|
21
|
+
let help = false;
|
|
22
|
+
const unknown = [];
|
|
23
|
+
for (const arg of args) {
|
|
24
|
+
if (arg === "--no-auth") {
|
|
25
|
+
noAuth = true;
|
|
26
|
+
}
|
|
27
|
+
else if (arg === "--help" || arg === "-h") {
|
|
28
|
+
help = true;
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
unknown.push(arg);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return { noAuth, help, unknown };
|
|
35
|
+
}
|
|
36
|
+
function semverLessThan(a, b) {
|
|
37
|
+
const pa = stripPrerelease(a).split(".").map((part) => Number(part) || 0);
|
|
38
|
+
const pb = stripPrerelease(b).split(".").map((part) => Number(part) || 0);
|
|
39
|
+
for (let i = 0; i < 3; i += 1) {
|
|
40
|
+
if ((pa[i] ?? 0) < (pb[i] ?? 0))
|
|
41
|
+
return true;
|
|
42
|
+
if ((pa[i] ?? 0) > (pb[i] ?? 0))
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
function parseNpmListVersion(output) {
|
|
48
|
+
const match = output.match(/@(\d+\.\d+\.\d+[^\s]*)/);
|
|
49
|
+
return match?.[1] ?? null;
|
|
50
|
+
}
|
|
51
|
+
function skillsListHasAlphafox(output) {
|
|
52
|
+
const prefix = types_1.SKILLS_NAME_PREFIX.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
53
|
+
return new RegExp(`(^|\\s)${prefix}[\\w-]+`, "m").test(output);
|
|
54
|
+
}
|
|
55
|
+
function nextSteps(input) {
|
|
56
|
+
const steps = ["请重启 AI 工具,以便加载刚安装的 Skills。"];
|
|
57
|
+
if (input.auth.action === "skipped" || input.auth.action === "planned") {
|
|
58
|
+
steps.push("alphafox auth login --browser --format json --no-input", "alphafox auth login --no-wait --format json --no-input");
|
|
59
|
+
}
|
|
60
|
+
steps.push("alphafox doctor --format json --no-input", `Agent 安装指南:${types_1.AGENT_INSTALL_GUIDE_BLOB_URL}`);
|
|
61
|
+
if (input.dryRun) {
|
|
62
|
+
steps.unshift("这是 --dry-run,去掉该参数再运行才会真正安装。");
|
|
63
|
+
}
|
|
64
|
+
return steps;
|
|
65
|
+
}
|
|
66
|
+
async function runInstallWizard(flags, env = process.env, runner = (0, exec_1.createDefaultInstallRunner)(env, defaultSearchDirs())) {
|
|
67
|
+
runner.log("正在安装 Alphafox CLI…");
|
|
68
|
+
const installedVer = await readGloballyInstalledVersion(runner);
|
|
69
|
+
const latestVer = await readLatestVersion(runner);
|
|
70
|
+
const needsUpgrade = Boolean(installedVer) &&
|
|
71
|
+
Boolean(latestVer) &&
|
|
72
|
+
semverLessThan(installedVer, latestVer);
|
|
73
|
+
const cli = await stepInstallCli(flags, runner, {
|
|
74
|
+
installedVer,
|
|
75
|
+
latestVer,
|
|
76
|
+
needsUpgrade,
|
|
77
|
+
});
|
|
78
|
+
const skills = await stepInstallSkills(flags, runner);
|
|
79
|
+
const auth = await stepAuth(flags, runner);
|
|
80
|
+
return {
|
|
81
|
+
cli,
|
|
82
|
+
skills,
|
|
83
|
+
auth,
|
|
84
|
+
next: nextSteps({ auth, dryRun: flags.dryRun }),
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
function defaultSearchDirs() {
|
|
88
|
+
return [__dirname, process.cwd()];
|
|
89
|
+
}
|
|
90
|
+
function stripPrerelease(version) {
|
|
91
|
+
return version.replace(/-.*$/, "");
|
|
92
|
+
}
|
|
93
|
+
async function readGloballyInstalledVersion(runner) {
|
|
94
|
+
try {
|
|
95
|
+
const { stdout, stderr } = await runner.exec("npm", ["list", "-g", version_1.CLI_PACKAGE, "--depth=0"], { timeoutMs: 15_000 });
|
|
96
|
+
return parseNpmListVersion(`${stdout}\n${stderr}`);
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
async function readLatestVersion(runner) {
|
|
103
|
+
try {
|
|
104
|
+
const { stdout } = await runner.exec("npm", ["view", version_1.CLI_PACKAGE, "version"], {
|
|
105
|
+
timeoutMs: 15_000,
|
|
106
|
+
});
|
|
107
|
+
const ver = stdout.trim();
|
|
108
|
+
return /^\d+\.\d+\.\d+/.test(ver) ? ver : null;
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
return null;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
async function npmRootGlobal(runner) {
|
|
115
|
+
try {
|
|
116
|
+
const { stdout } = await runner.exec("npm", ["root", "-g"], {
|
|
117
|
+
timeoutMs: 15_000,
|
|
118
|
+
});
|
|
119
|
+
const root = stdout.trim();
|
|
120
|
+
return root.length > 0 ? root : null;
|
|
121
|
+
}
|
|
122
|
+
catch {
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
async function npmPrefixGlobal(runner) {
|
|
127
|
+
try {
|
|
128
|
+
const { stdout } = await runner.exec("npm", ["prefix", "-g"], {
|
|
129
|
+
timeoutMs: 15_000,
|
|
130
|
+
});
|
|
131
|
+
const prefix = stdout.trim();
|
|
132
|
+
return prefix.length > 0 ? prefix : null;
|
|
133
|
+
}
|
|
134
|
+
catch {
|
|
135
|
+
return null;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
async function stepInstallCli(flags, runner, versions) {
|
|
139
|
+
const { installedVer, latestVer, needsUpgrade } = versions;
|
|
140
|
+
if (installedVer && !needsUpgrade) {
|
|
141
|
+
runner.log(`已安装(${installedVer}),已跳过`);
|
|
142
|
+
return {
|
|
143
|
+
action: flags.dryRun ? "planned" : "skipped",
|
|
144
|
+
version: installedVer,
|
|
145
|
+
latestVersion: latestVer ?? undefined,
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
if (flags.dryRun) {
|
|
149
|
+
runner.log(needsUpgrade
|
|
150
|
+
? `将升级 ${version_1.CLI_PACKAGE}(${installedVer} → ${latestVer ?? "latest"})`
|
|
151
|
+
: `将全局安装 ${version_1.CLI_PACKAGE}`);
|
|
152
|
+
return {
|
|
153
|
+
action: "planned",
|
|
154
|
+
previousVersion: installedVer ?? undefined,
|
|
155
|
+
latestVersion: latestVer ?? undefined,
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
runner.log(needsUpgrade
|
|
159
|
+
? `正在升级 ${version_1.CLI_PACKAGE}(${installedVer} → ${latestVer})…`
|
|
160
|
+
: `正在全局安装 ${version_1.CLI_PACKAGE}…`);
|
|
161
|
+
try {
|
|
162
|
+
await runner.exec("npm", ["install", "-g", version_1.CLI_PACKAGE], {
|
|
163
|
+
timeoutMs: NPM_TIMEOUT_MS,
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
catch (err) {
|
|
167
|
+
throw new types_1.InstallError({
|
|
168
|
+
type: "install",
|
|
169
|
+
subtype: "npm_global_failed",
|
|
170
|
+
message: `全局安装 ${version_1.CLI_PACKAGE} 失败。`,
|
|
171
|
+
hint: `npm install -g ${version_1.CLI_PACKAGE}`,
|
|
172
|
+
details: err instanceof Error ? err.message : String(err),
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
const after = (await readGloballyInstalledVersion(runner)) ?? latestVer ?? version_1.CLI_VERSION;
|
|
176
|
+
runner.log(needsUpgrade ? `已升级到 ${after}` : "已全局安装");
|
|
177
|
+
return {
|
|
178
|
+
action: needsUpgrade ? "upgraded" : "installed",
|
|
179
|
+
version: after,
|
|
180
|
+
previousVersion: installedVer ?? undefined,
|
|
181
|
+
latestVersion: latestVer ?? undefined,
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
async function resolveSkillsSources(runner) {
|
|
185
|
+
const override = runner.env.ALPHAFOX_SKILLS_SOURCE?.trim();
|
|
186
|
+
if (override)
|
|
187
|
+
return [override];
|
|
188
|
+
const sources = [];
|
|
189
|
+
const npmRoot = await npmRootGlobal(runner);
|
|
190
|
+
if (npmRoot) {
|
|
191
|
+
const globalRoot = (0, package_root_1.globalPackageRoot)(npmRoot);
|
|
192
|
+
if ((0, package_root_1.packageHasSkills)(globalRoot))
|
|
193
|
+
sources.push(globalRoot);
|
|
194
|
+
}
|
|
195
|
+
const localRoot = (0, package_root_1.findAlphafoxPackageRoot)(runner.packageSearchDirs());
|
|
196
|
+
if (localRoot && !sources.includes(localRoot) && (0, package_root_1.packageHasSkills)(localRoot)) {
|
|
197
|
+
sources.push(localRoot);
|
|
198
|
+
}
|
|
199
|
+
sources.push(types_1.SKILLS_GITHUB_SOURCE);
|
|
200
|
+
return sources;
|
|
201
|
+
}
|
|
202
|
+
async function skillsAlreadyInstalled(runner) {
|
|
203
|
+
try {
|
|
204
|
+
const { stdout, stderr } = await runner.exec("npx", ["-y", "skills", "ls", "-g"], { timeoutMs: SKILLS_TIMEOUT_MS });
|
|
205
|
+
return skillsListHasAlphafox(`${stdout}\n${stderr}`);
|
|
206
|
+
}
|
|
207
|
+
catch {
|
|
208
|
+
return false;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
async function stepInstallSkills(flags, runner) {
|
|
212
|
+
const sources = await resolveSkillsSources(runner);
|
|
213
|
+
const already = flags.dryRun ? false : await skillsAlreadyInstalled(runner);
|
|
214
|
+
if (already) {
|
|
215
|
+
runner.log("Skills 已安装,已跳过");
|
|
216
|
+
return {
|
|
217
|
+
action: "skipped",
|
|
218
|
+
source: sources[0],
|
|
219
|
+
scope: "global",
|
|
220
|
+
alreadyPresent: true,
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
if (flags.dryRun) {
|
|
224
|
+
runner.log(`将从 ${sources[0] ?? types_1.SKILLS_GITHUB_SOURCE} 安装 Skills`);
|
|
225
|
+
return {
|
|
226
|
+
action: "planned",
|
|
227
|
+
source: sources[0] ?? types_1.SKILLS_GITHUB_SOURCE,
|
|
228
|
+
scope: "global",
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
runner.log("正在安装 AI Skills…");
|
|
232
|
+
let lastError;
|
|
233
|
+
for (const source of sources) {
|
|
234
|
+
try {
|
|
235
|
+
await runner.exec("npx", ["-y", "skills", "add", source, "-y", "-g"], { timeoutMs: SKILLS_TIMEOUT_MS });
|
|
236
|
+
runner.log(`Skills 已安装(${source})`);
|
|
237
|
+
return { action: "installed", source, scope: "global" };
|
|
238
|
+
}
|
|
239
|
+
catch (err) {
|
|
240
|
+
lastError = err;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
throw new types_1.InstallError({
|
|
244
|
+
type: "install",
|
|
245
|
+
subtype: "skills_add_failed",
|
|
246
|
+
message: "安装 Agent Skills 失败。",
|
|
247
|
+
hint: `npx skills add ${types_1.SKILLS_GITHUB_SOURCE} -y -g`,
|
|
248
|
+
details: lastError instanceof Error ? lastError.message : String(lastError),
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
async function resolveAlphafoxBin(runner) {
|
|
252
|
+
const prefix = await npmPrefixGlobal(runner);
|
|
253
|
+
if (prefix) {
|
|
254
|
+
const bin = (0, package_root_1.globalBinPath)(prefix);
|
|
255
|
+
if ((0, node_fs_1.existsSync)(bin))
|
|
256
|
+
return bin;
|
|
257
|
+
}
|
|
258
|
+
try {
|
|
259
|
+
const { stdout } = await runner.exec(process.platform === "win32" ? "where" : "which", ["alphafox"], { timeoutMs: 10_000 });
|
|
260
|
+
const first = stdout.split(/\r?\n/)[0]?.trim();
|
|
261
|
+
return first || null;
|
|
262
|
+
}
|
|
263
|
+
catch {
|
|
264
|
+
return null;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
async function stepAuth(flags, runner) {
|
|
268
|
+
if (flags.noAuth) {
|
|
269
|
+
return { action: "skipped", reason: "no-auth" };
|
|
270
|
+
}
|
|
271
|
+
if (flags.noInput || !runner.isTty()) {
|
|
272
|
+
if (flags.dryRun) {
|
|
273
|
+
return { action: "planned", reason: "non-interactive" };
|
|
274
|
+
}
|
|
275
|
+
runner.log("要完成安装,请运行:\n alphafox auth login --browser\n alphafox auth login --no-wait --format json --no-input");
|
|
276
|
+
return { action: "skipped", reason: "non-interactive" };
|
|
277
|
+
}
|
|
278
|
+
if (flags.dryRun) {
|
|
279
|
+
runner.log("将提示运行 alphafox auth login --browser");
|
|
280
|
+
return { action: "planned", reason: "tty" };
|
|
281
|
+
}
|
|
282
|
+
const yes = await runner.confirm("现在登录,以便 Agent 可以调用公开 Application API?");
|
|
283
|
+
if (!yes) {
|
|
284
|
+
runner.log("已跳过登录。之后可运行 alphafox auth login。");
|
|
285
|
+
return { action: "skipped", reason: "declined" };
|
|
286
|
+
}
|
|
287
|
+
const bin = await resolveAlphafoxBin(runner);
|
|
288
|
+
if (!bin) {
|
|
289
|
+
throw new types_1.InstallError({
|
|
290
|
+
type: "install",
|
|
291
|
+
subtype: "cli_bin_missing",
|
|
292
|
+
message: "安装完成后找不到 alphafox 可执行文件。",
|
|
293
|
+
hint: "请确认 npm 全局 bin 目录在 PATH 中,然后运行 alphafox auth login --browser。",
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
try {
|
|
297
|
+
await runner.execInherit(bin, ["auth", "login", "--browser"], {
|
|
298
|
+
timeoutMs: 10 * 60_000,
|
|
299
|
+
});
|
|
300
|
+
runner.log("登录完成");
|
|
301
|
+
return { action: "completed" };
|
|
302
|
+
}
|
|
303
|
+
catch (err) {
|
|
304
|
+
runner.log("登录失败。请运行 alphafox auth login --browser 重试。");
|
|
305
|
+
return {
|
|
306
|
+
action: "failed",
|
|
307
|
+
reason: err instanceof Error ? err.message : String(err),
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
function installHelpData() {
|
|
312
|
+
return {
|
|
313
|
+
name: "install",
|
|
314
|
+
usage: [
|
|
315
|
+
"npx @alphafox/cli@latest install",
|
|
316
|
+
"alphafox install",
|
|
317
|
+
"alphafox install --no-auth",
|
|
318
|
+
"alphafox install --dry-run",
|
|
319
|
+
],
|
|
320
|
+
description: "全局安装 @alphafox/cli,并通过 npx skills add 把同版本 Agent Skills 写入本机已检测到的 Agent(Cursor、Claude Code、Codex 等)的用户级目录。",
|
|
321
|
+
agentGuide: types_1.AGENT_INSTALL_GUIDE_BLOB_URL,
|
|
322
|
+
};
|
|
323
|
+
}
|
|
324
|
+
function resolveLocalSkillsDir(searchDirs) {
|
|
325
|
+
const root = (0, package_root_1.findAlphafoxPackageRoot)(searchDirs);
|
|
326
|
+
if (!root)
|
|
327
|
+
return null;
|
|
328
|
+
const skillsDir = (0, node_path_1.join)(root, "skills");
|
|
329
|
+
return (0, package_root_1.packageHasSkills)(root) ? skillsDir : null;
|
|
330
|
+
}
|
package/dist/version.d.ts
CHANGED
package/dist/version.js
CHANGED
|
@@ -3,6 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.CLI_CONTRACT_VERSION = exports.CLI_VERSION = exports.CLI_PACKAGE = exports.CLI_NAME = void 0;
|
|
4
4
|
exports.CLI_NAME = "alphafox";
|
|
5
5
|
exports.CLI_PACKAGE = "@alphafox/cli";
|
|
6
|
-
exports.CLI_VERSION = "0.
|
|
6
|
+
exports.CLI_VERSION = "0.3.3";
|
|
7
7
|
var operations_1 = require("./catalog/operations");
|
|
8
8
|
Object.defineProperty(exports, "CLI_CONTRACT_VERSION", { enumerable: true, get: function () { return operations_1.CATALOG_VERSION; } });
|
package/docs/.nojekyll
ADDED
|
File without changes
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# Alphafox CLI installation guide
|
|
2
|
+
|
|
3
|
+
The following steps are designed for AI Agents. Some steps require the user
|
|
4
|
+
to complete a browser or Device Flow approval. Always use
|
|
5
|
+
`--format json --no-input` when invoking the CLI. Never pass `--token`.
|
|
6
|
+
|
|
7
|
+
Raw copy of this file:
|
|
8
|
+
https://raw.githubusercontent.com/alphafoxai/alphafox-cli/main/docs/alphafox-cli-installation-guide.md
|
|
9
|
+
|
|
10
|
+
## Prerequisites
|
|
11
|
+
|
|
12
|
+
- Node.js 20+ (`npm` / `npx`)
|
|
13
|
+
|
|
14
|
+
## Step 1: Install the CLI and Agent Skills
|
|
15
|
+
|
|
16
|
+
Skills do **not** register with Cursor / Claude Code / Codex from
|
|
17
|
+
`npm install -g` alone. The second command is required.
|
|
18
|
+
|
|
19
|
+
```shell
|
|
20
|
+
# Install CLI
|
|
21
|
+
npm install -g @alphafox/cli
|
|
22
|
+
|
|
23
|
+
# Install CLI SKILL (required) — project-local, current workspace
|
|
24
|
+
npx -y skills add "$(npm root -g)/@alphafox/cli" -y
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
If the local package path fails (older tarball without `skills/`, or
|
|
28
|
+
`npm root -g` is wrong), fall back to the public GitHub source:
|
|
29
|
+
|
|
30
|
+
```shell
|
|
31
|
+
npx -y skills add alphafoxai/alphafox-cli -y
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
To install Skills for every project on this machine instead of the current
|
|
35
|
+
repo, add `-g`:
|
|
36
|
+
|
|
37
|
+
```shell
|
|
38
|
+
npx -y skills add "$(npm root -g)/@alphafox/cli" -y -g
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Do not invent a second catalog. Skills must stay co-versioned with the CLI
|
|
42
|
+
that was just installed.
|
|
43
|
+
|
|
44
|
+
## Step 2: Login
|
|
45
|
+
|
|
46
|
+
### Device Flow (headless / Agent)
|
|
47
|
+
|
|
48
|
+
1. Start login and extract `verification_uri` / `user_code` from the JSON
|
|
49
|
+
envelope. Send those to the user. Do not poll in a tight loop.
|
|
50
|
+
|
|
51
|
+
```shell
|
|
52
|
+
alphafox auth login --no-wait --format json --no-input
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
2. After the user approves, resume with the `device_code` from step 1:
|
|
56
|
+
|
|
57
|
+
```shell
|
|
58
|
+
alphafox auth login --device-code <device_code> --format json --no-input
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Browser loopback (human on this machine)
|
|
62
|
+
|
|
63
|
+
If the user is at a local desktop and can use a browser:
|
|
64
|
+
|
|
65
|
+
```shell
|
|
66
|
+
alphafox auth login --browser --format json --no-input
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
The CLI binds `127.0.0.1` and opens the system browser. If the browser
|
|
70
|
+
cannot open, the error includes a copyable `authorizeUrl` — send that to
|
|
71
|
+
the user. Do not retry as Device Flow unless the operator is headless.
|
|
72
|
+
|
|
73
|
+
Default profile is `production`. Use `--profile staging|local` only when
|
|
74
|
+
the user explicitly asks.
|
|
75
|
+
|
|
76
|
+
## Step 3: Verify
|
|
77
|
+
|
|
78
|
+
```shell
|
|
79
|
+
alphafox doctor --format json --no-input
|
|
80
|
+
alphafox auth status --verify --format json --no-input
|
|
81
|
+
alphafox whoami --format json --no-input
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Parse the JSON envelope: `ok === true` means success. Errors land on
|
|
85
|
+
**stderr**. A 401 / expired session means re-run Step 2 — do not pass
|
|
86
|
+
`--token` and do not reuse a token from another profile.
|
|
87
|
+
|
|
88
|
+
## Step 4: Tell the user to restart
|
|
89
|
+
|
|
90
|
+
Ask the user to **restart the AI tool** so the new Skills are loaded.
|
|
91
|
+
Then they can ask the Agent to use Alphafox (auth, catalog, trading,
|
|
92
|
+
engine-backtest, …).
|
|
93
|
+
|
|
94
|
+
## Human wizard (do not run this from an Agent)
|
|
95
|
+
|
|
96
|
+
Humans who prefer an interactive terminal should run this instead of
|
|
97
|
+
stepping through the commands above:
|
|
98
|
+
|
|
99
|
+
```shell
|
|
100
|
+
npx @alphafox/cli@latest install
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
That wizard installs the CLI globally, runs `npx skills add … -y -g`,
|
|
104
|
+
and may prompt for `alphafox auth login --browser`. It is TTY-oriented.
|
|
105
|
+
Agents must follow Steps 1–4 in this document rather than the wizard.
|
package/docs/favicon.svg
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
<svg width="880" height="1320" viewBox="560 400 880 1320" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<path d="M600 859.99V448.467C600 444.343 603.341 440.997 607.455 441.283C633.947 443.127 687.377 454.464 738.326 489.713C790.889 526.08 819.686 577.964 829.376 603.853C830.516 606.899 833.375 608.999 836.627 608.999H974.473C977.797 608.999 980.699 606.816 981.805 603.682C989.573 581.673 1012.28 537.164 1054.85 499.081C1097.95 460.53 1170.23 445.26 1207.73 441.629C1212.01 441.215 1215.61 444.632 1215.61 448.934V860.713C1215.61 864.837 1212.28 868.175 1208.15 868.278C1166.66 869.316 1082.4 878.881 1024.32 911.272C971.303 940.844 930.998 987.234 911.43 1015.2C907.935 1020.2 899.832 1019.72 896.775 1014.44C882.18 989.258 849.547 947.01 795.65 911.272C735.079 871.11 650.192 865.287 608.157 867.588C603.768 867.828 600 864.385 600 859.99Z" fill="#FF991F"/>
|
|
3
|
+
<path d="M600.58 1235.01L600.58 969.867C600.58 965.744 603.924 962.4 608.047 962.458C675.284 963.412 740.225 977.952 799.655 1043.32C866.429 1116.76 897.008 1187.09 1027.44 1187.09L1133.53 1187.09C1290.79 1187.09 1400 1305.96 1400 1452.22L1400 1676.91C1400 1684.08 1391.55 1686.6 1387.59 1680.62C1357.88 1635.76 1286.34 1537.49 1154.22 1537.49L897.008 1537.49C718.527 1537.49 600.58 1420.82 600.58 1235.01Z" fill="#FF991F"/>
|
|
4
|
+
</svg>
|