@alphafox/cli 0.3.4 → 0.3.6
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/LICENSE +1 -1
- package/README.md +27 -6
- package/dist/auth/loopback-callback.js +3 -3
- package/dist/commands/run.js +26 -2
- package/dist/index.d.ts +4 -0
- package/dist/index.js +20 -1
- package/dist/install/types.d.ts +8 -1
- package/dist/install/types.js +1 -0
- package/dist/install/wizard.js +91 -53
- package/dist/keychain/windows-credential.d.ts +1 -1
- package/dist/keychain/windows-credential.js +1 -1
- package/dist/skills/manager.d.ts +96 -0
- package/dist/skills/manager.js +445 -0
- package/dist/skills/run-command.d.ts +22 -0
- package/dist/skills/run-command.js +143 -0
- package/dist/skills-manifest.json +141 -0
- package/dist/update/notify.d.ts +24 -0
- package/dist/update/notify.js +109 -0
- package/dist/update/run-command.d.ts +41 -0
- package/dist/update/run-command.js +204 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/docs/agents/issue-tracker.md +2 -2
- package/docs/agents/triage-labels.md +1 -1
- package/docs/alphafox-cli-installation-guide.md +15 -16
- package/docs/index.html +11 -11
- package/docs/release-supply-chain.md +11 -6
- package/package.json +2 -2
- package/skills/account/SKILL.md +1 -1
- package/skills/admin/SKILL.md +1 -1
- package/skills/alphafox/SKILL.md +26 -4
- package/skills/alphafox-shared/SKILL.md +24 -4
- package/skills/auth/SKILL.md +2 -2
- package/skills/engine-backtest/SKILL.md +1 -1
- package/skills/exchange/SKILL.md +1 -1
- package/skills/market/SKILL.md +1 -1
- package/skills/notification/SKILL.md +1 -1
- package/skills/strategy/SKILL.md +1 -1
- package/skills/trading/SKILL.md +1 -1
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"packageName": "@alphafox/cli",
|
|
4
|
+
"packageVersion": "0.3.6",
|
|
5
|
+
"contractVersion": "2026-08-13",
|
|
6
|
+
"bundleHash": "1eb4c16a941eee4c125efc6bb64ed7bb0db1d12b71f71cae66e55e64f600cf9a",
|
|
7
|
+
"skills": [
|
|
8
|
+
{
|
|
9
|
+
"name": "alphafox",
|
|
10
|
+
"version": "0.3.6",
|
|
11
|
+
"files": [
|
|
12
|
+
{
|
|
13
|
+
"path": "SKILL.md",
|
|
14
|
+
"sha256": "a60f579e6321533d4f965c607f1158ddb50d1a89905d8793eca0b401b3f67fd2",
|
|
15
|
+
"size": 3055
|
|
16
|
+
}
|
|
17
|
+
],
|
|
18
|
+
"hash": "c47e6e2d6154e831a681b731e123053c2d20c6c77654191f0a78ae2137ce5304"
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"name": "alphafox-account",
|
|
22
|
+
"version": "0.3.6",
|
|
23
|
+
"files": [
|
|
24
|
+
{
|
|
25
|
+
"path": "SKILL.md",
|
|
26
|
+
"sha256": "c60baab539cca008ccc48d53f0262d7a019db82b3945402d16b5ac84624b475f",
|
|
27
|
+
"size": 783
|
|
28
|
+
}
|
|
29
|
+
],
|
|
30
|
+
"hash": "e828192ec19a24bc18ce64d07a583eaba498e6a0c356214dbe18ccae6e9f6a6d"
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"name": "alphafox-admin",
|
|
34
|
+
"version": "0.3.6",
|
|
35
|
+
"files": [
|
|
36
|
+
{
|
|
37
|
+
"path": "SKILL.md",
|
|
38
|
+
"sha256": "87bbc12b803be021d94ad8161293263ce69e1d6c50f887a245ebe5c0a285e4f6",
|
|
39
|
+
"size": 787
|
|
40
|
+
}
|
|
41
|
+
],
|
|
42
|
+
"hash": "2881be10858efaad4543ffbe94f3bf87a91d4b0a4f3d905c3e0a5b8463e8756b"
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
"name": "alphafox-auth",
|
|
46
|
+
"version": "0.3.6",
|
|
47
|
+
"files": [
|
|
48
|
+
{
|
|
49
|
+
"path": "SKILL.md",
|
|
50
|
+
"sha256": "99e954df23206b0deb32761ce39396897d5af2ee8852e3a8340ed1b9c2e88a46",
|
|
51
|
+
"size": 1919
|
|
52
|
+
}
|
|
53
|
+
],
|
|
54
|
+
"hash": "659ca92bdfa0b31bcd1d39d7af151c308f1f9e7cd541bd38cf89326a825a38b8"
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
"name": "alphafox-engine-backtest",
|
|
58
|
+
"version": "0.3.6",
|
|
59
|
+
"files": [
|
|
60
|
+
{
|
|
61
|
+
"path": "SKILL.md",
|
|
62
|
+
"sha256": "176c329a665709461403671d34e73dd5b58bf389a328010c8a32cec5b949a9c5",
|
|
63
|
+
"size": 7346
|
|
64
|
+
}
|
|
65
|
+
],
|
|
66
|
+
"hash": "23db5ab285f8600a43561ce3d4b7641ea45cd55c7c3b16d9f6fb7ff0c862b379"
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
"name": "alphafox-exchange",
|
|
70
|
+
"version": "0.3.6",
|
|
71
|
+
"files": [
|
|
72
|
+
{
|
|
73
|
+
"path": "SKILL.md",
|
|
74
|
+
"sha256": "089db4794cd55ba04278d4616cd6d5e92bc4c1d4c7c183001ea363bc4eeba578",
|
|
75
|
+
"size": 743
|
|
76
|
+
}
|
|
77
|
+
],
|
|
78
|
+
"hash": "d4b0fe876ced82185eb477a23420cb24a8990f3dcbb6d4d5e9412dfd4cd2c279"
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
"name": "alphafox-market",
|
|
82
|
+
"version": "0.3.6",
|
|
83
|
+
"files": [
|
|
84
|
+
{
|
|
85
|
+
"path": "SKILL.md",
|
|
86
|
+
"sha256": "79fd7431c119b9d9318566c0419e2820ad9b06f0fda2882fdf9d1d7f4c1b9566",
|
|
87
|
+
"size": 1801
|
|
88
|
+
}
|
|
89
|
+
],
|
|
90
|
+
"hash": "8814883b9b5bfb7eab4406fe1236091410dcb1130d4904dae8756e1302a02687"
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
"name": "alphafox-notification",
|
|
94
|
+
"version": "0.3.6",
|
|
95
|
+
"files": [
|
|
96
|
+
{
|
|
97
|
+
"path": "SKILL.md",
|
|
98
|
+
"sha256": "9a90360b83b72bb252349612cb052ffded40d00e07ca8568b76a6b13479252ac",
|
|
99
|
+
"size": 698
|
|
100
|
+
}
|
|
101
|
+
],
|
|
102
|
+
"hash": "99f8309b235b2b89734ed49d0a9e0e8981b5216025815fbe69f9101cf4f412cc"
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
"name": "alphafox-shared",
|
|
106
|
+
"version": "0.3.6",
|
|
107
|
+
"files": [
|
|
108
|
+
{
|
|
109
|
+
"path": "SKILL.md",
|
|
110
|
+
"sha256": "60051a6c9b789e306ec968d3c8762a75039c34a0db2470dfddd1063bf2a3553f",
|
|
111
|
+
"size": 5071
|
|
112
|
+
}
|
|
113
|
+
],
|
|
114
|
+
"hash": "20832738f9f15063291309871197b6274fd24f2630bd2525092ac017f7491b68"
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
"name": "alphafox-strategy",
|
|
118
|
+
"version": "0.3.6",
|
|
119
|
+
"files": [
|
|
120
|
+
{
|
|
121
|
+
"path": "SKILL.md",
|
|
122
|
+
"sha256": "e4188e115eca6610c482bbcdf11ab1eb455cb5b6f242af96d1d8090e6ce9ce9d",
|
|
123
|
+
"size": 1450
|
|
124
|
+
}
|
|
125
|
+
],
|
|
126
|
+
"hash": "878fd5c365eb33a431e91f6922a8cf45bcf94a7136b0105d50f3b487112c3573"
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
"name": "alphafox-trading",
|
|
130
|
+
"version": "0.3.6",
|
|
131
|
+
"files": [
|
|
132
|
+
{
|
|
133
|
+
"path": "SKILL.md",
|
|
134
|
+
"sha256": "098e0f975ae9f0169b0da696b76e74ffd3c6748e898e7c4f8c8f8a33aec47dc8",
|
|
135
|
+
"size": 1435
|
|
136
|
+
}
|
|
137
|
+
],
|
|
138
|
+
"hash": "99b72870808f871ddeffd69ee89872e8532f2847494a0e5ad83de48ad58c675a"
|
|
139
|
+
}
|
|
140
|
+
]
|
|
141
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export declare const UPDATE_CHECK_INTERVAL_MS: number;
|
|
2
|
+
export interface UpdateCheckState {
|
|
3
|
+
readonly schemaVersion: 1;
|
|
4
|
+
readonly checkedAt: string;
|
|
5
|
+
readonly currentVersion: string;
|
|
6
|
+
readonly latestVersion: string | null;
|
|
7
|
+
readonly updateAvailable: boolean;
|
|
8
|
+
}
|
|
9
|
+
export interface UpdateNoticeResult {
|
|
10
|
+
readonly checked: boolean;
|
|
11
|
+
readonly notified: boolean;
|
|
12
|
+
readonly latestVersion: string | null;
|
|
13
|
+
}
|
|
14
|
+
export interface UpdateNoticeDeps {
|
|
15
|
+
readonly env?: NodeJS.ProcessEnv;
|
|
16
|
+
readonly currentVersion?: string;
|
|
17
|
+
readonly now?: Date;
|
|
18
|
+
readonly fetchLatest?: () => Promise<string>;
|
|
19
|
+
readonly writeNotice?: (line: string) => void;
|
|
20
|
+
}
|
|
21
|
+
export declare function updateCheckStatePath(env?: NodeJS.ProcessEnv): string;
|
|
22
|
+
export declare function formatUpdateNotice(currentVersion: string, latestVersion: string): string;
|
|
23
|
+
export declare function shouldSkipUpdateCheck(command: string | undefined, env?: NodeJS.ProcessEnv): boolean;
|
|
24
|
+
export declare function maybeNotifyCliUpdate(deps?: UpdateNoticeDeps): Promise<UpdateNoticeResult>;
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.UPDATE_CHECK_INTERVAL_MS = void 0;
|
|
4
|
+
exports.updateCheckStatePath = updateCheckStatePath;
|
|
5
|
+
exports.formatUpdateNotice = formatUpdateNotice;
|
|
6
|
+
exports.shouldSkipUpdateCheck = shouldSkipUpdateCheck;
|
|
7
|
+
exports.maybeNotifyCliUpdate = maybeNotifyCliUpdate;
|
|
8
|
+
const node_fs_1 = require("node:fs");
|
|
9
|
+
const node_path_1 = require("node:path");
|
|
10
|
+
const profiles_1 = require("../config/profiles");
|
|
11
|
+
const exec_1 = require("../install/exec");
|
|
12
|
+
const wizard_1 = require("../install/wizard");
|
|
13
|
+
const version_1 = require("../version");
|
|
14
|
+
exports.UPDATE_CHECK_INTERVAL_MS = 24 * 60 * 60 * 1000;
|
|
15
|
+
const NPM_VIEW_TIMEOUT_MS = 4_000;
|
|
16
|
+
function updateCheckStatePath(env = process.env) {
|
|
17
|
+
return (0, node_path_1.join)((0, profiles_1.defaultConfigDir)(env), "update-check.json");
|
|
18
|
+
}
|
|
19
|
+
function formatUpdateNotice(currentVersion, latestVersion) {
|
|
20
|
+
return `[alphafox] update available: ${currentVersion} -> ${latestVersion}. After the user confirms, run: alphafox update --format json --no-input`;
|
|
21
|
+
}
|
|
22
|
+
function shouldSkipUpdateCheck(command, env = process.env) {
|
|
23
|
+
if (env.ALPHAFOX_SKIP_UPDATE_CHECK === "1")
|
|
24
|
+
return true;
|
|
25
|
+
return command === "update" || command === "install";
|
|
26
|
+
}
|
|
27
|
+
async function maybeNotifyCliUpdate(deps = {}) {
|
|
28
|
+
const env = deps.env ?? process.env;
|
|
29
|
+
const currentVersion = deps.currentVersion ?? version_1.CLI_VERSION;
|
|
30
|
+
const now = deps.now ?? new Date();
|
|
31
|
+
const writeNotice = deps.writeNotice ??
|
|
32
|
+
((line) => {
|
|
33
|
+
process.stderr.write(`${line}\n`);
|
|
34
|
+
});
|
|
35
|
+
const previous = loadUpdateCheckState(updateCheckStatePath(env));
|
|
36
|
+
if (previous &&
|
|
37
|
+
now.getTime() - Date.parse(previous.checkedAt) < exports.UPDATE_CHECK_INTERVAL_MS) {
|
|
38
|
+
return {
|
|
39
|
+
checked: false,
|
|
40
|
+
notified: false,
|
|
41
|
+
latestVersion: previous.latestVersion,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
let latestVersion = null;
|
|
45
|
+
try {
|
|
46
|
+
latestVersion = await (deps.fetchLatest ?? defaultFetchLatest)(env);
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
saveUpdateCheckState(updateCheckStatePath(env), {
|
|
50
|
+
schemaVersion: 1,
|
|
51
|
+
checkedAt: now.toISOString(),
|
|
52
|
+
currentVersion,
|
|
53
|
+
latestVersion: previous?.latestVersion ?? null,
|
|
54
|
+
updateAvailable: false,
|
|
55
|
+
});
|
|
56
|
+
return {
|
|
57
|
+
checked: true,
|
|
58
|
+
notified: false,
|
|
59
|
+
latestVersion: previous?.latestVersion ?? null,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
const updateAvailable = (0, wizard_1.semverLessThan)(currentVersion, latestVersion);
|
|
63
|
+
saveUpdateCheckState(updateCheckStatePath(env), {
|
|
64
|
+
schemaVersion: 1,
|
|
65
|
+
checkedAt: now.toISOString(),
|
|
66
|
+
currentVersion,
|
|
67
|
+
latestVersion,
|
|
68
|
+
updateAvailable,
|
|
69
|
+
});
|
|
70
|
+
if (updateAvailable) {
|
|
71
|
+
writeNotice(formatUpdateNotice(currentVersion, latestVersion));
|
|
72
|
+
}
|
|
73
|
+
return {
|
|
74
|
+
checked: true,
|
|
75
|
+
notified: updateAvailable,
|
|
76
|
+
latestVersion,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
function loadUpdateCheckState(path) {
|
|
80
|
+
if (!(0, node_fs_1.existsSync)(path))
|
|
81
|
+
return null;
|
|
82
|
+
try {
|
|
83
|
+
const parsed = JSON.parse((0, node_fs_1.readFileSync)(path, "utf8"));
|
|
84
|
+
if (parsed.schemaVersion !== 1 ||
|
|
85
|
+
typeof parsed.checkedAt !== "string" ||
|
|
86
|
+
Number.isNaN(Date.parse(parsed.checkedAt))) {
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
return parsed;
|
|
90
|
+
}
|
|
91
|
+
catch {
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
function saveUpdateCheckState(path, state) {
|
|
96
|
+
(0, node_fs_1.mkdirSync)((0, node_path_1.join)(path, ".."), { recursive: true });
|
|
97
|
+
(0, node_fs_1.writeFileSync)(path, `${JSON.stringify(state, null, 2)}\n`, { mode: 0o600 });
|
|
98
|
+
}
|
|
99
|
+
async function defaultFetchLatest(env) {
|
|
100
|
+
const runner = (0, exec_1.createDefaultInstallRunner)(env, []);
|
|
101
|
+
const { stdout } = await runner.exec("npm", ["view", version_1.CLI_PACKAGE, "version"], {
|
|
102
|
+
timeoutMs: NPM_VIEW_TIMEOUT_MS,
|
|
103
|
+
});
|
|
104
|
+
const version = stdout.trim();
|
|
105
|
+
if (!/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/.test(version)) {
|
|
106
|
+
throw new Error(`invalid npm version: ${version}`);
|
|
107
|
+
}
|
|
108
|
+
return version;
|
|
109
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { InstallRunner } from "../install/types";
|
|
2
|
+
import type { SkillsSyncResult } from "../skills/manager";
|
|
3
|
+
export interface UpdateArgs {
|
|
4
|
+
readonly check: boolean;
|
|
5
|
+
readonly help: boolean;
|
|
6
|
+
readonly version?: string;
|
|
7
|
+
}
|
|
8
|
+
export interface UpdateExecutionFlags {
|
|
9
|
+
readonly yes: boolean;
|
|
10
|
+
readonly dryRun: boolean;
|
|
11
|
+
}
|
|
12
|
+
export interface UpdateCliFlags extends UpdateExecutionFlags {
|
|
13
|
+
readonly format: "json" | "jsonl" | "text";
|
|
14
|
+
readonly noInput: boolean;
|
|
15
|
+
readonly jq?: string;
|
|
16
|
+
}
|
|
17
|
+
export interface UpdateDeps {
|
|
18
|
+
readonly runner?: InstallRunner;
|
|
19
|
+
readonly packageHasSkills?: (packageRoot: string) => boolean;
|
|
20
|
+
readonly sync?: (packageRoot: string, runner: InstallRunner) => Promise<SkillsSyncResult>;
|
|
21
|
+
}
|
|
22
|
+
export interface CliUpdateResult {
|
|
23
|
+
readonly currentVersion: string | null;
|
|
24
|
+
readonly targetVersion: string;
|
|
25
|
+
readonly updateAvailable: boolean;
|
|
26
|
+
readonly checkOnly: boolean;
|
|
27
|
+
readonly dryRun: boolean;
|
|
28
|
+
readonly cli: {
|
|
29
|
+
readonly action: "available" | "planned" | "updated" | "current";
|
|
30
|
+
readonly previousVersion: string | null;
|
|
31
|
+
readonly version: string;
|
|
32
|
+
};
|
|
33
|
+
readonly skills: SkillsSyncResult | {
|
|
34
|
+
readonly action: "not-run";
|
|
35
|
+
readonly reason: "check-only" | "dry-run";
|
|
36
|
+
};
|
|
37
|
+
readonly restartRequired: boolean;
|
|
38
|
+
}
|
|
39
|
+
export declare function parseUpdateArgs(args: readonly string[]): UpdateArgs;
|
|
40
|
+
export declare function executeCliUpdate(args: UpdateArgs, flags: UpdateExecutionFlags, env?: NodeJS.ProcessEnv, deps?: UpdateDeps): Promise<CliUpdateResult>;
|
|
41
|
+
export declare function cmdUpdate(args: string[], flags: UpdateCliFlags, env?: NodeJS.ProcessEnv, deps?: UpdateDeps): Promise<number>;
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseUpdateArgs = parseUpdateArgs;
|
|
4
|
+
exports.executeCliUpdate = executeCliUpdate;
|
|
5
|
+
exports.cmdUpdate = cmdUpdate;
|
|
6
|
+
const envelope_1 = require("../envelope");
|
|
7
|
+
const exec_1 = require("../install/exec");
|
|
8
|
+
const package_root_1 = require("../install/package-root");
|
|
9
|
+
const wizard_1 = require("../install/wizard");
|
|
10
|
+
const run_command_1 = require("../skills/run-command");
|
|
11
|
+
const version_1 = require("../version");
|
|
12
|
+
const NPM_TIMEOUT_MS = 120_000;
|
|
13
|
+
function parseUpdateArgs(args) {
|
|
14
|
+
let check = false;
|
|
15
|
+
let help = false;
|
|
16
|
+
let version;
|
|
17
|
+
for (let i = 0; i < args.length; i += 1) {
|
|
18
|
+
const arg = args[i];
|
|
19
|
+
if (arg === "--check") {
|
|
20
|
+
check = true;
|
|
21
|
+
}
|
|
22
|
+
else if (arg === "--version") {
|
|
23
|
+
version = args[++i];
|
|
24
|
+
if (!version)
|
|
25
|
+
throw updateUsage("--version requires a value");
|
|
26
|
+
}
|
|
27
|
+
else if (arg.startsWith("--version=")) {
|
|
28
|
+
version = arg.slice("--version=".length);
|
|
29
|
+
}
|
|
30
|
+
else if (arg === "--help" || arg === "-h" || arg === "help") {
|
|
31
|
+
help = true;
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
throw updateUsage(`Unknown update argument: ${arg}`);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
if (version && !/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/.test(version)) {
|
|
38
|
+
throw updateUsage(`Invalid version: ${version}`);
|
|
39
|
+
}
|
|
40
|
+
return { check, help, ...(version ? { version } : {}) };
|
|
41
|
+
}
|
|
42
|
+
async function executeCliUpdate(args, flags, env = process.env, deps = {}) {
|
|
43
|
+
const runner = deps.runner ??
|
|
44
|
+
(0, exec_1.createDefaultInstallRunner)(env, [__dirname, process.cwd()]);
|
|
45
|
+
const currentVersion = await readGlobalVersion(runner);
|
|
46
|
+
const targetVersion = await readTargetVersion(runner, args.version);
|
|
47
|
+
const updateAvailable = args.version
|
|
48
|
+
? currentVersion !== targetVersion
|
|
49
|
+
: currentVersion == null || (0, wizard_1.semverLessThan)(currentVersion, targetVersion);
|
|
50
|
+
const effectiveVersion = updateAvailable ? targetVersion : (currentVersion ?? targetVersion);
|
|
51
|
+
if (args.check) {
|
|
52
|
+
return {
|
|
53
|
+
currentVersion,
|
|
54
|
+
targetVersion,
|
|
55
|
+
updateAvailable,
|
|
56
|
+
checkOnly: true,
|
|
57
|
+
dryRun: false,
|
|
58
|
+
cli: {
|
|
59
|
+
action: updateAvailable ? "available" : "current",
|
|
60
|
+
previousVersion: currentVersion,
|
|
61
|
+
version: effectiveVersion,
|
|
62
|
+
},
|
|
63
|
+
skills: { action: "not-run", reason: "check-only" },
|
|
64
|
+
restartRequired: false,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
if (updateAvailable &&
|
|
68
|
+
args.version &&
|
|
69
|
+
currentVersion &&
|
|
70
|
+
(0, wizard_1.semverLessThan)(targetVersion, currentVersion) &&
|
|
71
|
+
!flags.yes) {
|
|
72
|
+
throw Object.assign(new Error(`Downgrading ${version_1.CLI_PACKAGE} from ${currentVersion} to ${targetVersion} requires --yes`), {
|
|
73
|
+
type: "confirmation",
|
|
74
|
+
subtype: "cli_downgrade_confirmation_required",
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
if (flags.dryRun) {
|
|
78
|
+
return {
|
|
79
|
+
currentVersion,
|
|
80
|
+
targetVersion,
|
|
81
|
+
updateAvailable,
|
|
82
|
+
checkOnly: false,
|
|
83
|
+
dryRun: true,
|
|
84
|
+
cli: {
|
|
85
|
+
action: updateAvailable ? "planned" : "current",
|
|
86
|
+
previousVersion: currentVersion,
|
|
87
|
+
version: effectiveVersion,
|
|
88
|
+
},
|
|
89
|
+
skills: { action: "not-run", reason: "dry-run" },
|
|
90
|
+
restartRequired: updateAvailable,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
if (updateAvailable) {
|
|
94
|
+
await runner.exec("npm", ["install", "-g", `${version_1.CLI_PACKAGE}@${targetVersion}`], { timeoutMs: NPM_TIMEOUT_MS });
|
|
95
|
+
const installedVersion = await readGlobalVersion(runner);
|
|
96
|
+
if (installedVersion !== targetVersion) {
|
|
97
|
+
throw Object.assign(new Error(`npm reported ${installedVersion ?? "no global install"} after updating to ${targetVersion}`), {
|
|
98
|
+
type: "install",
|
|
99
|
+
subtype: "cli_update_verify_failed",
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
const packageRoot = await resolveUpdatedPackageRoot(runner, deps.packageHasSkills ?? package_root_1.packageHasSkills, !updateAvailable);
|
|
104
|
+
const sync = deps.sync ??
|
|
105
|
+
(async (root, activeRunner) => await (0, run_command_1.syncCurrentSkills)({ force: false, dryRun: false }, env, { runner: activeRunner, packageRoot: root }));
|
|
106
|
+
const skills = await sync(packageRoot, runner);
|
|
107
|
+
return {
|
|
108
|
+
currentVersion,
|
|
109
|
+
targetVersion,
|
|
110
|
+
updateAvailable,
|
|
111
|
+
checkOnly: false,
|
|
112
|
+
dryRun: false,
|
|
113
|
+
cli: {
|
|
114
|
+
action: updateAvailable ? "updated" : "current",
|
|
115
|
+
previousVersion: currentVersion,
|
|
116
|
+
version: effectiveVersion,
|
|
117
|
+
},
|
|
118
|
+
skills,
|
|
119
|
+
restartRequired: updateAvailable || skills.restartRequired,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
async function cmdUpdate(args, flags, env = process.env, deps = {}) {
|
|
123
|
+
const parsed = parseUpdateArgs(args);
|
|
124
|
+
if (parsed.help) {
|
|
125
|
+
(0, envelope_1.writeSuccess)({
|
|
126
|
+
name: "update",
|
|
127
|
+
usage: [
|
|
128
|
+
"alphafox update --check",
|
|
129
|
+
"alphafox update [--dry-run]",
|
|
130
|
+
"alphafox update --version <version> [--yes]",
|
|
131
|
+
],
|
|
132
|
+
notes: [
|
|
133
|
+
"Updates @alphafox/cli through npm, then syncs the verified co-versioned Skills bundle",
|
|
134
|
+
"A downgrade requires --yes",
|
|
135
|
+
"No Skills are downloaded independently from GitHub",
|
|
136
|
+
],
|
|
137
|
+
}, { format: flags.format, jq: flags.jq });
|
|
138
|
+
return 0;
|
|
139
|
+
}
|
|
140
|
+
const result = await executeCliUpdate(parsed, flags, env, deps);
|
|
141
|
+
(0, envelope_1.writeSuccess)(result, { format: flags.format, jq: flags.jq });
|
|
142
|
+
return result.skills.action !== "not-run" &&
|
|
143
|
+
result.skills.blocked.length > 0
|
|
144
|
+
? 1
|
|
145
|
+
: 0;
|
|
146
|
+
}
|
|
147
|
+
async function readGlobalVersion(runner) {
|
|
148
|
+
try {
|
|
149
|
+
const { stdout, stderr } = await runner.exec("npm", ["list", "-g", version_1.CLI_PACKAGE, "--depth=0"], { timeoutMs: 15_000 });
|
|
150
|
+
return (0, wizard_1.parseNpmListVersion)(`${stdout}\n${stderr}`);
|
|
151
|
+
}
|
|
152
|
+
catch {
|
|
153
|
+
return null;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
async function readTargetVersion(runner, requested) {
|
|
157
|
+
const spec = requested ? `${version_1.CLI_PACKAGE}@${requested}` : version_1.CLI_PACKAGE;
|
|
158
|
+
const { stdout } = await runner.exec("npm", ["view", spec, "version"], {
|
|
159
|
+
timeoutMs: 15_000,
|
|
160
|
+
});
|
|
161
|
+
const version = stdout.trim();
|
|
162
|
+
if (!/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/.test(version)) {
|
|
163
|
+
throw Object.assign(new Error(`npm returned an invalid version for ${spec}`), {
|
|
164
|
+
type: "install",
|
|
165
|
+
subtype: "npm_version_invalid",
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
return version;
|
|
169
|
+
}
|
|
170
|
+
async function resolveUpdatedPackageRoot(runner, packageHasSkills, allowCurrentFallback) {
|
|
171
|
+
try {
|
|
172
|
+
const { stdout } = await runner.exec("npm", ["root", "-g"], {
|
|
173
|
+
timeoutMs: 15_000,
|
|
174
|
+
});
|
|
175
|
+
const root = (0, package_root_1.globalPackageRoot)(stdout.trim());
|
|
176
|
+
if (packageHasSkills(root))
|
|
177
|
+
return root;
|
|
178
|
+
}
|
|
179
|
+
catch {
|
|
180
|
+
// Fall back to the currently executing package for repair-only updates.
|
|
181
|
+
}
|
|
182
|
+
if (!allowCurrentFallback) {
|
|
183
|
+
throw Object.assign(new Error("Updated @alphafox/cli package does not contain Skills"), {
|
|
184
|
+
type: "install",
|
|
185
|
+
subtype: "updated_skills_missing",
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
const current = (0, run_command_1.resolveCurrentSkillsPackageRoot)(runner.packageSearchDirs().length > 0
|
|
189
|
+
? runner.packageSearchDirs()
|
|
190
|
+
: [__dirname, process.cwd()]);
|
|
191
|
+
if (packageHasSkills(current))
|
|
192
|
+
return current;
|
|
193
|
+
throw Object.assign(new Error("Updated @alphafox/cli package does not contain Skills"), {
|
|
194
|
+
type: "install",
|
|
195
|
+
subtype: "updated_skills_missing",
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
function updateUsage(message) {
|
|
199
|
+
return Object.assign(new Error(message), {
|
|
200
|
+
type: "usage",
|
|
201
|
+
subtype: "invalid_update_args",
|
|
202
|
+
status: 64,
|
|
203
|
+
});
|
|
204
|
+
}
|
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.3.
|
|
6
|
+
exports.CLI_VERSION = "0.3.6";
|
|
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; } });
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Issue tracker: Feishu Tasks
|
|
2
2
|
|
|
3
|
-
Issues and specs for this repo live as tasks in the **
|
|
3
|
+
Issues and specs for this repo live as tasks in the **AlphaFox-Issues** Feishu (Lark) tasklist. Use the `lark-cli` CLI ([`@larksuite/cli`](https://github.com/larksuite/cli)) for all operations, always with `--as user` — a task created by the bot identity is invisible in the human's task centre.
|
|
4
4
|
|
|
5
5
|
List: <https://applink.feishu.cn/client/todo/task_list?guid=6d628d79-cdfe-47cc-98f7-35561944494b>
|
|
6
6
|
|
|
@@ -46,7 +46,7 @@ Every other label is an option on the single-select `Type` field. Address an opt
|
|
|
46
46
|
## Conventions
|
|
47
47
|
|
|
48
48
|
- **Shared-list title** — prefix every issue/task title with `[alphafox-cli]` so the repository remains identifiable on the shared board.
|
|
49
|
-
- **Tracker boundary** — Matt Skills issues, specs, tickets, triage items, and wayfinder maps belong in `
|
|
49
|
+
- **Tracker boundary** — Matt Skills issues, specs, tickets, triage items, and wayfinder maps belong in `AlphaFox-Issues`, not a quarterly execution list. If quarterly planning initiated the work, link its absolute Feishu task URL instead of duplicating workflow state.
|
|
50
50
|
|
|
51
51
|
- **Create an issue** — one call sets body, section (triage role) and `Type`:
|
|
52
52
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Triage Labels
|
|
2
2
|
|
|
3
|
-
The skills speak in terms of five canonical triage roles. On this repo's tracker (Feishu Tasks) a role is not a label but a **section** of the
|
|
3
|
+
The skills speak in terms of five canonical triage roles. On this repo's tracker (Feishu Tasks) a role is not a label but a **section** of the AlphaFox-Issues tasklist — a task sits in exactly one, so the state machine can't be violated. `issue-tracker.md` holds the section GUIDs and the command that moves a task between them.
|
|
4
4
|
|
|
5
5
|
| Label in mattpocock/skills | Section in our tracker | Meaning |
|
|
6
6
|
| -------------------------- | ---------------------- | ---------------------------------------- |
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#
|
|
1
|
+
# AlphaFox CLI installation guide
|
|
2
2
|
|
|
3
3
|
The following steps are designed for AI Agents. Some steps require the user
|
|
4
4
|
to complete a browser or Device Flow approval. Always use
|
|
@@ -20,26 +20,25 @@ Skills do **not** register with Cursor / Claude Code / Codex from
|
|
|
20
20
|
# Install CLI
|
|
21
21
|
npm install -g @alphafox/cli
|
|
22
22
|
|
|
23
|
-
#
|
|
24
|
-
|
|
23
|
+
# Verify and globally sync the exact co-versioned Skills bundle
|
|
24
|
+
alphafox skills sync --format json --no-input
|
|
25
25
|
```
|
|
26
26
|
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
Do not install Skills from GitHub `main` as a fallback. The CLI verifies the
|
|
28
|
+
manifest and hashes inside the npm package before syncing. If sync fails, stop
|
|
29
|
+
and report the error rather than downloading a different Skills version.
|
|
29
30
|
|
|
30
|
-
|
|
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`:
|
|
31
|
+
For future updates:
|
|
36
32
|
|
|
37
33
|
```shell
|
|
38
|
-
|
|
34
|
+
alphafox update --check --format json --no-input
|
|
35
|
+
alphafox update --format json --no-input
|
|
39
36
|
```
|
|
40
37
|
|
|
41
|
-
|
|
42
|
-
|
|
38
|
+
`alphafox update` upgrades the npm CLI first, then syncs its bundled Skills.
|
|
39
|
+
Modified Skills are preserved and reported. Only use
|
|
40
|
+
`alphafox skills sync --force --yes` when the user explicitly wants to replace
|
|
41
|
+
them; a backup is created before replacement.
|
|
43
42
|
|
|
44
43
|
## Step 2: Login
|
|
45
44
|
|
|
@@ -88,7 +87,7 @@ Parse the JSON envelope: `ok === true` means success. Errors land on
|
|
|
88
87
|
## Step 4: Tell the user to restart
|
|
89
88
|
|
|
90
89
|
Ask the user to **restart the AI tool** so the new Skills are loaded.
|
|
91
|
-
Then they can ask the Agent to use
|
|
90
|
+
Then they can ask the Agent to use AlphaFox. The entry skill `alphafox` routes
|
|
92
91
|
to auth, market, engine-backtest, strategy, trading, and the rest.
|
|
93
92
|
|
|
94
93
|
## Human wizard (do not run this from an Agent)
|
|
@@ -100,6 +99,6 @@ stepping through the commands above:
|
|
|
100
99
|
npx @alphafox/cli@latest install
|
|
101
100
|
```
|
|
102
101
|
|
|
103
|
-
That wizard installs the CLI globally,
|
|
102
|
+
That wizard installs the CLI globally, verifies and syncs the packaged Skills,
|
|
104
103
|
and may prompt for `alphafox auth login --browser`. It is TTY-oriented.
|
|
105
104
|
Agents must follow Steps 1–4 in this document rather than the wizard.
|