@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
package/LICENSE
CHANGED
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# alphafox-cli
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
AlphaFox CLI (`alphafox`) — Agent and human entry for the versioned Public Application API on alphafox-web.
|
|
4
4
|
|
|
5
5
|
Homepage: https://alphafoxai.github.io/alphafox-cli/
|
|
6
6
|
|
|
@@ -25,16 +25,35 @@ load.
|
|
|
25
25
|
Copy and send this to Cursor / Claude Code / Codex / Trae:
|
|
26
26
|
|
|
27
27
|
```
|
|
28
|
-
帮我安装
|
|
28
|
+
帮我安装 AlphaFox CLI:https://github.com/alphafoxai/alphafox-cli/blob/main/docs/alphafox-cli-installation-guide.md
|
|
29
29
|
```
|
|
30
30
|
|
|
31
31
|
```
|
|
32
|
-
Help me install
|
|
32
|
+
Help me install AlphaFox CLI: https://github.com/alphafoxai/alphafox-cli/blob/main/docs/alphafox-cli-installation-guide.md
|
|
33
33
|
```
|
|
34
34
|
|
|
35
|
-
The Agent follows that guide (`npm install -g`, `
|
|
35
|
+
The Agent follows that guide (`npm install -g`, `alphafox skills sync`, login,
|
|
36
36
|
`doctor`). **Restart the AI tool** when it finishes.
|
|
37
37
|
|
|
38
|
+
## Update
|
|
39
|
+
|
|
40
|
+
CLI and Skills are one verified release unit:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
alphafox update --check
|
|
44
|
+
alphafox update
|
|
45
|
+
alphafox skills status
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Ordinary CLI commands check npm at most once every 24 hours and only print a
|
|
49
|
+
stderr notice when a newer version exists. They never auto-upgrade.
|
|
50
|
+
|
|
51
|
+
`alphafox update` upgrades the npm package and then syncs the exact Skills
|
|
52
|
+
bundle shipped inside it. It never updates Skills independently from GitHub.
|
|
53
|
+
Locally modified Skills are reported and preserved; use
|
|
54
|
+
`alphafox skills sync --force --yes` only when you intend to replace them.
|
|
55
|
+
Restart the AI tool after a sync.
|
|
56
|
+
|
|
38
57
|
## Quick start
|
|
39
58
|
|
|
40
59
|
After Method 1 or 2:
|
|
@@ -67,8 +86,10 @@ skills then use public `operationId`s; an explicit local-execution skill may
|
|
|
67
86
|
call its co-versioned built-in command.
|
|
68
87
|
|
|
69
88
|
`alphafox install` (and the [Agent install guide](docs/alphafox-cli-installation-guide.md))
|
|
70
|
-
|
|
71
|
-
(`.cursor/skills`, `.claude/skills`, `~/.agents/skills`, …).
|
|
89
|
+
verify the packaged Skills manifest and sync managed files into Agent skill
|
|
90
|
+
directories (`.cursor/skills`, `.claude/skills`, `~/.agents/skills`, …).
|
|
91
|
+
Use `alphafox skills status` to inspect missing, stale, or modified Skills and
|
|
92
|
+
`alphafox skills sync` to repair safe drift.
|
|
72
93
|
|
|
73
94
|
## Docs
|
|
74
95
|
|
|
@@ -13,15 +13,15 @@ const node_crypto_1 = require("node:crypto");
|
|
|
13
13
|
const node_http_1 = __importDefault(require("node:http"));
|
|
14
14
|
exports.LOOPBACK_CALLBACK_PATH = "/callback";
|
|
15
15
|
const SUCCESS_HTML = `<!DOCTYPE html>
|
|
16
|
-
<html lang="zh-CN"><head><meta charset="utf-8"><title>
|
|
16
|
+
<html lang="zh-CN"><head><meta charset="utf-8"><title>AlphaFox CLI</title></head>
|
|
17
17
|
<body><p>已登录。可以关闭此窗口,回到终端继续。</p></body></html>
|
|
18
18
|
`;
|
|
19
19
|
const FAILURE_HTML = `<!DOCTYPE html>
|
|
20
|
-
<html lang="zh-CN"><head><meta charset="utf-8"><title>
|
|
20
|
+
<html lang="zh-CN"><head><meta charset="utf-8"><title>AlphaFox CLI</title></head>
|
|
21
21
|
<body><p>授权失败。可以关闭此窗口,回到终端查看原因。</p></body></html>
|
|
22
22
|
`;
|
|
23
23
|
const DUPLICATE_HTML = `<!DOCTYPE html>
|
|
24
|
-
<html lang="zh-CN"><head><meta charset="utf-8"><title>
|
|
24
|
+
<html lang="zh-CN"><head><meta charset="utf-8"><title>AlphaFox CLI</title></head>
|
|
25
25
|
<body><p>此登录回调已使用过。可以关闭此窗口。</p></body></html>
|
|
26
26
|
`;
|
|
27
27
|
async function startLoopbackCallbackServer(options) {
|
package/dist/commands/run.js
CHANGED
|
@@ -15,6 +15,9 @@ const confirmation_1 = require("../safety/confirmation");
|
|
|
15
15
|
const version_1 = require("../version");
|
|
16
16
|
const run_command_1 = require("../engine-backtest/run-command");
|
|
17
17
|
const run_command_2 = require("../resolve-symbols/run-command");
|
|
18
|
+
const run_command_3 = require("../skills/run-command");
|
|
19
|
+
const notify_1 = require("../update/notify");
|
|
20
|
+
const run_command_4 = require("../update/run-command");
|
|
18
21
|
const validate_body_1 = require("../catalog/validate-body");
|
|
19
22
|
const types_1 = require("../install/types");
|
|
20
23
|
const wizard_1 = require("../install/wizard");
|
|
@@ -86,6 +89,8 @@ async function runCli(argv, env = process.env) {
|
|
|
86
89
|
"alphafox version",
|
|
87
90
|
"alphafox doctor",
|
|
88
91
|
"alphafox install [--no-auth|--dry-run]",
|
|
92
|
+
"alphafox update [--check|--version VERSION]",
|
|
93
|
+
"alphafox skills status|sync [--force --yes]",
|
|
89
94
|
"alphafox auth login [--no-wait|--device-code CODE|--browser]",
|
|
90
95
|
"alphafox auth status [--verify]",
|
|
91
96
|
"alphafox auth logout",
|
|
@@ -103,7 +108,18 @@ async function runCli(argv, env = process.env) {
|
|
|
103
108
|
return 0;
|
|
104
109
|
}
|
|
105
110
|
try {
|
|
106
|
-
if (
|
|
111
|
+
if (!(0, notify_1.shouldSkipUpdateCheck)(cmd, env)) {
|
|
112
|
+
try {
|
|
113
|
+
await (0, notify_1.maybeNotifyCliUpdate)({ env, currentVersion: version_1.CLI_VERSION });
|
|
114
|
+
}
|
|
115
|
+
catch {
|
|
116
|
+
// Update notices must never fail a command.
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
if (cmd !== "version" &&
|
|
120
|
+
cmd !== "install" &&
|
|
121
|
+
cmd !== "update" &&
|
|
122
|
+
cmd !== "skills") {
|
|
107
123
|
assertCatalogCompatible();
|
|
108
124
|
}
|
|
109
125
|
switch (cmd) {
|
|
@@ -111,6 +127,10 @@ async function runCli(argv, env = process.env) {
|
|
|
111
127
|
return cmdVersion(flags);
|
|
112
128
|
case "install":
|
|
113
129
|
return await cmdInstall(args, flags, env);
|
|
130
|
+
case "update":
|
|
131
|
+
return await (0, run_command_4.cmdUpdate)(args, flags, env);
|
|
132
|
+
case "skills":
|
|
133
|
+
return await (0, run_command_3.cmdSkills)(args, flags, env);
|
|
114
134
|
case "doctor":
|
|
115
135
|
return cmdDoctor(flags, env);
|
|
116
136
|
case "whoami":
|
|
@@ -200,7 +220,11 @@ async function cmdInstall(args, flags, env) {
|
|
|
200
220
|
help: false,
|
|
201
221
|
}, env);
|
|
202
222
|
(0, envelope_1.writeSuccess)(data, { format: flags.format, jq: flags.jq });
|
|
203
|
-
return data.auth.action === "failed"
|
|
223
|
+
return data.auth.action === "failed" ||
|
|
224
|
+
data.skills.action === "blocked" ||
|
|
225
|
+
(data.skills.blocked?.length ?? 0) > 0
|
|
226
|
+
? 1
|
|
227
|
+
: 0;
|
|
204
228
|
}
|
|
205
229
|
catch (err) {
|
|
206
230
|
if ((0, types_1.isInstallError)(err)) {
|
package/dist/index.d.ts
CHANGED
|
@@ -17,3 +17,7 @@ export { validateCatalogWriteBody } from "./catalog/validate-body";
|
|
|
17
17
|
export { parseRequestBodyFlags, loadJsonArg } from "./commands/request-body";
|
|
18
18
|
export { parseInstallArgs, runInstallWizard, semverLessThan, skillsListHasAlphafox, } from "./install/wizard";
|
|
19
19
|
export { AGENT_INSTALL_GUIDE_BLOB_URL, AGENT_INSTALL_GUIDE_URL, SKILLS_GITHUB_SOURCE, } from "./install/types";
|
|
20
|
+
export { buildSkillsManifest, inspectSkills, loadAndVerifySkillsManifest, loadSkillsState, syncSkills, writeSkillsManifest, } from "./skills/manager";
|
|
21
|
+
export { inspectCurrentSkills, installedSkillsRoot, skillsStatePath, syncCurrentSkills, } from "./skills/run-command";
|
|
22
|
+
export { executeCliUpdate, parseUpdateArgs, } from "./update/run-command";
|
|
23
|
+
export { formatUpdateNotice, maybeNotifyCliUpdate, shouldSkipUpdateCheck, } from "./update/notify";
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.validateCatalogWriteBody = exports.CLI_CONTRACT_VERSION = exports.CLI_PACKAGE = exports.CLI_VERSION = exports.checkGeneratedCatalogCompatibility = exports.buildCapabilityManifest = exports.getOperationSchemaDocument = exports.findCatalogOperationByRoute = exports.findCatalogOperation = exports.COMPATIBILITY_RANGE = exports.CATALOG_VERSION = exports.CATALOG_SOURCE = exports.CATALOG_OPERATIONS = exports.startLoopbackCallbackServer = exports.runBrowserPkceLogin = exports.accessTokenNeedsRefresh = exports.refreshStoredTokensOrNull = exports.refreshStoredTokens = exports.requiresHighRiskConfirmation = exports.inferRawApiRisk = exports.assertHighRiskConfirmation = exports.resolveTypedCommand = exports.checkCliCompatibility = exports.pathTemplateMatches = exports.normalizeApiPath = exports.isInternalDisallowedPath = exports.isFacadeAllowlistedPath = exports.WINDOWS_CRED_MAX_BYTES = exports.windowsCredentialTarget = exports.linuxSecretToolBin = exports.linuxSecretServiceArgs = exports.keychainPlatform = exports.probeOsKeychain = exports.getLastTokenSaveResult = exports.tokenFingerprint = exports.deleteTokens = exports.loadTokens = exports.saveTokens = exports.assertNoTokenFields = exports.saveConfigFile = exports.loadConfigFile = exports.resolveProfile = exports.applyJqFilter = exports.writeError = exports.writeSuccess = exports.parseJsonEnvelope = exports.errorEnvelope = exports.successEnvelope = exports.parseGlobalFlags = exports.runCli = void 0;
|
|
4
|
-
exports.SKILLS_GITHUB_SOURCE = exports.AGENT_INSTALL_GUIDE_URL = exports.AGENT_INSTALL_GUIDE_BLOB_URL = exports.skillsListHasAlphafox = exports.semverLessThan = exports.runInstallWizard = exports.parseInstallArgs = exports.loadJsonArg = exports.parseRequestBodyFlags = void 0;
|
|
4
|
+
exports.shouldSkipUpdateCheck = exports.maybeNotifyCliUpdate = exports.formatUpdateNotice = exports.parseUpdateArgs = exports.executeCliUpdate = exports.syncCurrentSkills = exports.skillsStatePath = exports.installedSkillsRoot = exports.inspectCurrentSkills = exports.writeSkillsManifest = exports.syncSkills = exports.loadSkillsState = exports.loadAndVerifySkillsManifest = exports.inspectSkills = exports.buildSkillsManifest = exports.SKILLS_GITHUB_SOURCE = exports.AGENT_INSTALL_GUIDE_URL = exports.AGENT_INSTALL_GUIDE_BLOB_URL = exports.skillsListHasAlphafox = exports.semverLessThan = exports.runInstallWizard = exports.parseInstallArgs = exports.loadJsonArg = exports.parseRequestBodyFlags = void 0;
|
|
5
5
|
var run_1 = require("./commands/run");
|
|
6
6
|
Object.defineProperty(exports, "runCli", { enumerable: true, get: function () { return run_1.runCli; } });
|
|
7
7
|
Object.defineProperty(exports, "parseGlobalFlags", { enumerable: true, get: function () { return run_1.parseGlobalFlags; } });
|
|
@@ -80,3 +80,22 @@ var types_1 = require("./install/types");
|
|
|
80
80
|
Object.defineProperty(exports, "AGENT_INSTALL_GUIDE_BLOB_URL", { enumerable: true, get: function () { return types_1.AGENT_INSTALL_GUIDE_BLOB_URL; } });
|
|
81
81
|
Object.defineProperty(exports, "AGENT_INSTALL_GUIDE_URL", { enumerable: true, get: function () { return types_1.AGENT_INSTALL_GUIDE_URL; } });
|
|
82
82
|
Object.defineProperty(exports, "SKILLS_GITHUB_SOURCE", { enumerable: true, get: function () { return types_1.SKILLS_GITHUB_SOURCE; } });
|
|
83
|
+
var manager_1 = require("./skills/manager");
|
|
84
|
+
Object.defineProperty(exports, "buildSkillsManifest", { enumerable: true, get: function () { return manager_1.buildSkillsManifest; } });
|
|
85
|
+
Object.defineProperty(exports, "inspectSkills", { enumerable: true, get: function () { return manager_1.inspectSkills; } });
|
|
86
|
+
Object.defineProperty(exports, "loadAndVerifySkillsManifest", { enumerable: true, get: function () { return manager_1.loadAndVerifySkillsManifest; } });
|
|
87
|
+
Object.defineProperty(exports, "loadSkillsState", { enumerable: true, get: function () { return manager_1.loadSkillsState; } });
|
|
88
|
+
Object.defineProperty(exports, "syncSkills", { enumerable: true, get: function () { return manager_1.syncSkills; } });
|
|
89
|
+
Object.defineProperty(exports, "writeSkillsManifest", { enumerable: true, get: function () { return manager_1.writeSkillsManifest; } });
|
|
90
|
+
var run_command_1 = require("./skills/run-command");
|
|
91
|
+
Object.defineProperty(exports, "inspectCurrentSkills", { enumerable: true, get: function () { return run_command_1.inspectCurrentSkills; } });
|
|
92
|
+
Object.defineProperty(exports, "installedSkillsRoot", { enumerable: true, get: function () { return run_command_1.installedSkillsRoot; } });
|
|
93
|
+
Object.defineProperty(exports, "skillsStatePath", { enumerable: true, get: function () { return run_command_1.skillsStatePath; } });
|
|
94
|
+
Object.defineProperty(exports, "syncCurrentSkills", { enumerable: true, get: function () { return run_command_1.syncCurrentSkills; } });
|
|
95
|
+
var run_command_2 = require("./update/run-command");
|
|
96
|
+
Object.defineProperty(exports, "executeCliUpdate", { enumerable: true, get: function () { return run_command_2.executeCliUpdate; } });
|
|
97
|
+
Object.defineProperty(exports, "parseUpdateArgs", { enumerable: true, get: function () { return run_command_2.parseUpdateArgs; } });
|
|
98
|
+
var notify_1 = require("./update/notify");
|
|
99
|
+
Object.defineProperty(exports, "formatUpdateNotice", { enumerable: true, get: function () { return notify_1.formatUpdateNotice; } });
|
|
100
|
+
Object.defineProperty(exports, "maybeNotifyCliUpdate", { enumerable: true, get: function () { return notify_1.maybeNotifyCliUpdate; } });
|
|
101
|
+
Object.defineProperty(exports, "shouldSkipUpdateCheck", { enumerable: true, get: function () { return notify_1.shouldSkipUpdateCheck; } });
|
package/dist/install/types.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
/** @deprecated AlphaFox Skills updates must use the verified npm package bundle. */
|
|
1
2
|
export declare const SKILLS_GITHUB_SOURCE = "alphafoxai/alphafox-cli";
|
|
2
3
|
export declare const SKILLS_NAME_PREFIX = "alphafox-";
|
|
3
4
|
export declare const AGENT_INSTALL_GUIDE_URL = "https://raw.githubusercontent.com/alphafoxai/alphafox-cli/main/docs/alphafox-cli-installation-guide.md";
|
|
4
5
|
export declare const AGENT_INSTALL_GUIDE_BLOB_URL = "https://github.com/alphafoxai/alphafox-cli/blob/main/docs/alphafox-cli-installation-guide.md";
|
|
5
6
|
export type InstallCliAction = "installed" | "upgraded" | "skipped" | "planned";
|
|
6
|
-
export type InstallSkillsAction = "installed" | "skipped" | "planned" | "failed";
|
|
7
|
+
export type InstallSkillsAction = "installed" | "updated" | "skipped" | "planned" | "failed" | "blocked";
|
|
7
8
|
export type InstallAuthAction = "completed" | "skipped" | "failed" | "planned";
|
|
8
9
|
export interface InstallCliStep {
|
|
9
10
|
readonly action: InstallCliAction;
|
|
@@ -16,6 +17,12 @@ export interface InstallSkillsStep {
|
|
|
16
17
|
readonly source?: string;
|
|
17
18
|
readonly scope: "global";
|
|
18
19
|
readonly alreadyPresent?: boolean;
|
|
20
|
+
readonly version?: string;
|
|
21
|
+
readonly updated?: readonly string[];
|
|
22
|
+
readonly removed?: readonly string[];
|
|
23
|
+
readonly blocked?: readonly string[];
|
|
24
|
+
readonly backupDir?: string;
|
|
25
|
+
readonly restartRequired?: boolean;
|
|
19
26
|
}
|
|
20
27
|
export interface InstallAuthStep {
|
|
21
28
|
readonly action: InstallAuthAction;
|
package/dist/install/types.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.InstallError = exports.AGENT_INSTALL_GUIDE_BLOB_URL = exports.AGENT_INSTALL_GUIDE_URL = exports.SKILLS_NAME_PREFIX = exports.SKILLS_GITHUB_SOURCE = void 0;
|
|
4
4
|
exports.isInstallError = isInstallError;
|
|
5
|
+
/** @deprecated AlphaFox Skills updates must use the verified npm package bundle. */
|
|
5
6
|
exports.SKILLS_GITHUB_SOURCE = "alphafoxai/alphafox-cli";
|
|
6
7
|
exports.SKILLS_NAME_PREFIX = "alphafox-";
|
|
7
8
|
exports.AGENT_INSTALL_GUIDE_URL = "https://raw.githubusercontent.com/alphafoxai/alphafox-cli/main/docs/alphafox-cli-installation-guide.md";
|
package/dist/install/wizard.js
CHANGED
|
@@ -11,6 +11,8 @@ exports.resolveLocalSkillsDir = resolveLocalSkillsDir;
|
|
|
11
11
|
const node_fs_1 = require("node:fs");
|
|
12
12
|
const node_path_1 = require("node:path");
|
|
13
13
|
const version_1 = require("../version");
|
|
14
|
+
const manager_1 = require("../skills/manager");
|
|
15
|
+
const run_command_1 = require("../skills/run-command");
|
|
14
16
|
const exec_1 = require("./exec");
|
|
15
17
|
const package_root_1 = require("./package-root");
|
|
16
18
|
const types_1 = require("./types");
|
|
@@ -63,7 +65,7 @@ function nextSteps(input) {
|
|
|
63
65
|
return steps;
|
|
64
66
|
}
|
|
65
67
|
async function runInstallWizard(flags, env = process.env, runner = (0, exec_1.createDefaultInstallRunner)(env, defaultSearchDirs())) {
|
|
66
|
-
runner.log("正在安装
|
|
68
|
+
runner.log("正在安装 AlphaFox CLI…");
|
|
67
69
|
const installedVer = await readGloballyInstalledVersion(runner);
|
|
68
70
|
const latestVer = await readLatestVersion(runner);
|
|
69
71
|
const needsUpgrade = Boolean(installedVer) &&
|
|
@@ -180,72 +182,108 @@ async function stepInstallCli(flags, runner, versions) {
|
|
|
180
182
|
latestVersion: latestVer ?? undefined,
|
|
181
183
|
};
|
|
182
184
|
}
|
|
183
|
-
async function
|
|
185
|
+
async function resolveSkillsSource(runner) {
|
|
184
186
|
const override = runner.env.ALPHAFOX_SKILLS_SOURCE?.trim();
|
|
185
|
-
if (override)
|
|
186
|
-
|
|
187
|
-
|
|
187
|
+
if (override) {
|
|
188
|
+
if ((0, package_root_1.packageHasSkills)(override))
|
|
189
|
+
return override;
|
|
190
|
+
throw new types_1.InstallError({
|
|
191
|
+
type: "install",
|
|
192
|
+
subtype: "skills_source_invalid",
|
|
193
|
+
message: "ALPHAFOX_SKILLS_SOURCE must point to a local @alphafox/cli package with bundled Skills.",
|
|
194
|
+
details: override,
|
|
195
|
+
});
|
|
196
|
+
}
|
|
188
197
|
const npmRoot = await npmRootGlobal(runner);
|
|
189
198
|
if (npmRoot) {
|
|
190
199
|
const globalRoot = (0, package_root_1.globalPackageRoot)(npmRoot);
|
|
191
200
|
if ((0, package_root_1.packageHasSkills)(globalRoot))
|
|
192
|
-
|
|
201
|
+
return globalRoot;
|
|
193
202
|
}
|
|
194
203
|
const localRoot = (0, package_root_1.findAlphafoxPackageRoot)(runner.packageSearchDirs());
|
|
195
|
-
if (localRoot &&
|
|
196
|
-
|
|
197
|
-
}
|
|
198
|
-
sources.push(types_1.SKILLS_GITHUB_SOURCE);
|
|
199
|
-
return sources;
|
|
200
|
-
}
|
|
201
|
-
async function skillsAlreadyInstalled(runner) {
|
|
202
|
-
try {
|
|
203
|
-
const { stdout, stderr } = await runner.exec("npx", ["-y", "skills", "ls", "-g"], { timeoutMs: SKILLS_TIMEOUT_MS });
|
|
204
|
-
return skillsListHasAlphafox(`${stdout}\n${stderr}`);
|
|
205
|
-
}
|
|
206
|
-
catch {
|
|
207
|
-
return false;
|
|
204
|
+
if (localRoot && (0, package_root_1.packageHasSkills)(localRoot)) {
|
|
205
|
+
return localRoot;
|
|
208
206
|
}
|
|
207
|
+
throw new types_1.InstallError({
|
|
208
|
+
type: "install",
|
|
209
|
+
subtype: "skills_package_missing",
|
|
210
|
+
message: "Could not locate the verified Skills bundle inside @alphafox/cli.",
|
|
211
|
+
hint: `npm install -g ${version_1.CLI_PACKAGE}`,
|
|
212
|
+
});
|
|
209
213
|
}
|
|
210
214
|
async function stepInstallSkills(flags, runner) {
|
|
211
|
-
const
|
|
212
|
-
const
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
215
|
+
const source = await resolveSkillsSource(runner);
|
|
216
|
+
const manifest = (0, manager_1.loadAndVerifySkillsManifest)(source);
|
|
217
|
+
runner.log(flags.dryRun
|
|
218
|
+
? `将同步 Skills ${manifest.packageVersion}(${source})`
|
|
219
|
+
: `正在同步 AI Skills ${manifest.packageVersion}…`);
|
|
220
|
+
try {
|
|
221
|
+
const result = await (0, manager_1.syncSkills)({
|
|
222
|
+
manifest,
|
|
223
|
+
packageRoot: source,
|
|
224
|
+
installedRoot: (0, run_command_1.installedSkillsRoot)(runner.env),
|
|
225
|
+
statePath: (0, run_command_1.skillsStatePath)(runner.env),
|
|
226
|
+
dryRun: flags.dryRun,
|
|
227
|
+
force: false,
|
|
228
|
+
}, {
|
|
229
|
+
install: async (names) => {
|
|
230
|
+
await runner.exec("npx", [
|
|
231
|
+
"-y",
|
|
232
|
+
"skills",
|
|
233
|
+
"add",
|
|
234
|
+
source,
|
|
235
|
+
"-y",
|
|
236
|
+
"-g",
|
|
237
|
+
"--skill",
|
|
238
|
+
...names,
|
|
239
|
+
], { timeoutMs: SKILLS_TIMEOUT_MS });
|
|
240
|
+
},
|
|
241
|
+
remove: async (names) => {
|
|
242
|
+
await runner.exec("npx", ["-y", "skills", "remove", ...names, "-y", "-g"], { timeoutMs: SKILLS_TIMEOUT_MS });
|
|
243
|
+
},
|
|
244
|
+
});
|
|
245
|
+
const action = result.blocked.length > 0
|
|
246
|
+
? "blocked"
|
|
247
|
+
: result.action === "planned"
|
|
248
|
+
? "planned"
|
|
249
|
+
: result.action === "skipped"
|
|
250
|
+
? "skipped"
|
|
251
|
+
: result.backupDir
|
|
252
|
+
? "updated"
|
|
253
|
+
: "installed";
|
|
254
|
+
runner.log(action === "skipped"
|
|
255
|
+
? "Skills 已是当前版本,已跳过"
|
|
256
|
+
: action === "blocked"
|
|
257
|
+
? `检测到本地修改,未覆盖:${result.blocked.join(", ")}`
|
|
258
|
+
: flags.dryRun
|
|
259
|
+
? `将同步 ${result.updated.length} 个 Skills`
|
|
260
|
+
: `Skills 已同步(${source})`);
|
|
224
261
|
return {
|
|
225
|
-
action
|
|
226
|
-
source
|
|
262
|
+
action,
|
|
263
|
+
source,
|
|
227
264
|
scope: "global",
|
|
265
|
+
alreadyPresent: result.status.summary.current > 0,
|
|
266
|
+
version: manifest.packageVersion,
|
|
267
|
+
updated: result.updated,
|
|
268
|
+
removed: result.removed,
|
|
269
|
+
blocked: result.blocked,
|
|
270
|
+
backupDir: result.backupDir,
|
|
271
|
+
restartRequired: result.restartRequired,
|
|
228
272
|
};
|
|
229
273
|
}
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
274
|
+
catch (err) {
|
|
275
|
+
if (err instanceof types_1.InstallError)
|
|
276
|
+
throw err;
|
|
277
|
+
throw new types_1.InstallError({
|
|
278
|
+
type: "install",
|
|
279
|
+
subtype: err && typeof err === "object" && "subtype" in err
|
|
280
|
+
? String(err.subtype)
|
|
281
|
+
: "skills_sync_failed",
|
|
282
|
+
message: "同步 Agent Skills 失败。",
|
|
283
|
+
hint: `alphafox skills sync --format json --no-input`,
|
|
284
|
+
details: err instanceof Error ? err.message : String(err),
|
|
285
|
+
});
|
|
241
286
|
}
|
|
242
|
-
throw new types_1.InstallError({
|
|
243
|
-
type: "install",
|
|
244
|
-
subtype: "skills_add_failed",
|
|
245
|
-
message: "安装 Agent Skills 失败。",
|
|
246
|
-
hint: `npx skills add ${types_1.SKILLS_GITHUB_SOURCE} -y -g`,
|
|
247
|
-
details: lastError instanceof Error ? lastError.message : String(lastError),
|
|
248
|
-
});
|
|
249
287
|
}
|
|
250
288
|
async function resolveAlphafoxBin(runner) {
|
|
251
289
|
const prefix = await npmPrefixGlobal(runner);
|
|
@@ -316,7 +354,7 @@ function installHelpData() {
|
|
|
316
354
|
"alphafox install --no-auth",
|
|
317
355
|
"alphafox install --dry-run",
|
|
318
356
|
],
|
|
319
|
-
description: "全局安装 @alphafox/cli
|
|
357
|
+
description: "全局安装 @alphafox/cli,校验包内 Skills manifest,并把同版本 Agent Skills 同步到本机已检测到的 Agent(Cursor、Claude Code、Codex 等)的用户级目录。",
|
|
320
358
|
agentGuide: types_1.AGENT_INSTALL_GUIDE_BLOB_URL,
|
|
321
359
|
};
|
|
322
360
|
}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
/** CRED_MAX_CREDENTIAL_BLOB_SIZE is 5*512 = 2560. */
|
|
6
6
|
export declare const WINDOWS_CRED_MAX_BYTES = 2560;
|
|
7
|
-
export declare const WINDOWS_CRED_PS1 = "#
|
|
7
|
+
export declare const WINDOWS_CRED_PS1 = "# AlphaFox CLI \u2014 Windows Credential Manager helper (t101360)\nparam(\n [Parameter(Mandatory = $true)][ValidateSet('write','read','delete')][string]$Action,\n [Parameter(Mandatory = $true)][string]$Target\n)\n$ErrorActionPreference = 'Stop'\nAdd-Type -TypeDefinition @\"\nusing System;\nusing System.Runtime.InteropServices;\nnamespace AlphafoxCred {\n [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]\n public struct CREDENTIAL {\n public uint Flags;\n public uint Type;\n public string TargetName;\n public string Comment;\n public System.Runtime.InteropServices.ComTypes.FILETIME LastWritten;\n public uint CredentialBlobSize;\n public IntPtr CredentialBlob;\n public uint Persist;\n public uint AttributeCount;\n public IntPtr Attributes;\n public string TargetAlias;\n public string UserName;\n }\n public static class Native {\n [DllImport(\"advapi32.dll\", CharSet = CharSet.Unicode, SetLastError = true)]\n public static extern bool CredWrite(ref CREDENTIAL credential, uint flags);\n [DllImport(\"advapi32.dll\", CharSet = CharSet.Unicode, SetLastError = true)]\n public static extern bool CredRead(string target, uint type, uint flags, out IntPtr credentialPtr);\n [DllImport(\"advapi32.dll\", CharSet = CharSet.Unicode, SetLastError = true)]\n public static extern bool CredDelete(string target, uint type, uint flags);\n [DllImport(\"advapi32.dll\", SetLastError = true)]\n public static extern void CredFree(IntPtr credential);\n }\n}\n\"@\n$CredTypeGeneric = 1\n$PersistLocalMachine = 2\nswitch ($Action) {\n 'write' {\n $payload = [Console]::In.ReadToEnd()\n $bytes = [Text.Encoding]::UTF8.GetBytes($payload)\n if ($bytes.Length -gt 2560) { throw \"credential blob too large\" }\n $blob = [Runtime.InteropServices.Marshal]::AllocHGlobal($bytes.Length)\n try {\n [Runtime.InteropServices.Marshal]::Copy($bytes, 0, $blob, $bytes.Length)\n $cred = New-Object AlphafoxCred.CREDENTIAL\n $cred.Type = $CredTypeGeneric\n $cred.TargetName = $Target\n $cred.UserName = \"alphafox-cli\"\n $cred.CredentialBlobSize = [uint32]$bytes.Length\n $cred.CredentialBlob = $blob\n $cred.Persist = $PersistLocalMachine\n $ok = [AlphafoxCred.Native]::CredWrite([ref]$cred, 0)\n if (-not $ok) {\n throw \"CredWrite failed Win32=$([Runtime.InteropServices.Marshal]::GetLastWin32Error())\"\n }\n } finally {\n [Runtime.InteropServices.Marshal]::FreeHGlobal($blob)\n }\n }\n 'read' {\n $ptr = [IntPtr]::Zero\n $ok = [AlphafoxCred.Native]::CredRead($Target, $CredTypeGeneric, 0, [ref]$ptr)\n if (-not $ok) { exit 2 }\n try {\n $cred = [Runtime.InteropServices.Marshal]::PtrToStructure($ptr, [type][AlphafoxCred.CREDENTIAL])\n $size = [int]$cred.CredentialBlobSize\n $bytes = New-Object byte[] $size\n [Runtime.InteropServices.Marshal]::Copy($cred.CredentialBlob, $bytes, 0, $size)\n [Console]::Out.Write([Text.Encoding]::UTF8.GetString($bytes))\n } finally {\n [AlphafoxCred.Native]::CredFree($ptr)\n }\n }\n 'delete' {\n [void][AlphafoxCred.Native]::CredDelete($Target, $CredTypeGeneric, 0)\n }\n}\n";
|
|
8
8
|
export declare function windowsCredentialTarget(profile: string): string;
|
|
9
9
|
export declare function windowsPowershellBin(env?: NodeJS.ProcessEnv): string;
|
|
10
10
|
export declare function windowsCredentialWrite(profile: string, payload: string, env?: NodeJS.ProcessEnv): boolean;
|
|
@@ -17,7 +17,7 @@ const node_os_1 = require("node:os");
|
|
|
17
17
|
const node_path_1 = require("node:path");
|
|
18
18
|
/** CRED_MAX_CREDENTIAL_BLOB_SIZE is 5*512 = 2560. */
|
|
19
19
|
exports.WINDOWS_CRED_MAX_BYTES = 2560;
|
|
20
|
-
exports.WINDOWS_CRED_PS1 = `#
|
|
20
|
+
exports.WINDOWS_CRED_PS1 = `# AlphaFox CLI — Windows Credential Manager helper (t101360)
|
|
21
21
|
param(
|
|
22
22
|
[Parameter(Mandatory = $true)][ValidateSet('write','read','delete')][string]$Action,
|
|
23
23
|
[Parameter(Mandatory = $true)][string]$Target
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
export interface SkillManifestFile {
|
|
2
|
+
readonly path: string;
|
|
3
|
+
readonly sha256: string;
|
|
4
|
+
readonly size: number;
|
|
5
|
+
}
|
|
6
|
+
export interface SkillManifestEntry {
|
|
7
|
+
readonly name: string;
|
|
8
|
+
readonly version: string;
|
|
9
|
+
readonly hash: string;
|
|
10
|
+
readonly files: readonly SkillManifestFile[];
|
|
11
|
+
}
|
|
12
|
+
export interface SkillsBundleManifest {
|
|
13
|
+
readonly schemaVersion: 1;
|
|
14
|
+
readonly packageName: "@alphafox/cli";
|
|
15
|
+
readonly packageVersion: string;
|
|
16
|
+
readonly contractVersion: string;
|
|
17
|
+
readonly bundleHash: string;
|
|
18
|
+
readonly skills: readonly SkillManifestEntry[];
|
|
19
|
+
}
|
|
20
|
+
export interface InstalledSkillState {
|
|
21
|
+
readonly version: string;
|
|
22
|
+
readonly hash: string;
|
|
23
|
+
}
|
|
24
|
+
export interface SkillsInstallState {
|
|
25
|
+
readonly schemaVersion: 1;
|
|
26
|
+
readonly packageVersion: string;
|
|
27
|
+
readonly contractVersion: string;
|
|
28
|
+
readonly bundleHash: string;
|
|
29
|
+
readonly syncedAt: string;
|
|
30
|
+
readonly skills: Readonly<Record<string, InstalledSkillState>>;
|
|
31
|
+
}
|
|
32
|
+
export type SkillStatus = "current" | "missing" | "stale" | "modified";
|
|
33
|
+
export interface InspectedSkill {
|
|
34
|
+
readonly name: string;
|
|
35
|
+
readonly expectedVersion: string;
|
|
36
|
+
readonly installedVersion: string | null;
|
|
37
|
+
readonly expectedHash: string;
|
|
38
|
+
readonly installedHash: string | null;
|
|
39
|
+
readonly status: SkillStatus;
|
|
40
|
+
readonly managed: boolean;
|
|
41
|
+
}
|
|
42
|
+
export interface SkillsStatus {
|
|
43
|
+
readonly bundleVersion: string;
|
|
44
|
+
readonly contractVersion: string;
|
|
45
|
+
readonly bundleHash: string;
|
|
46
|
+
readonly installedRoot: string;
|
|
47
|
+
readonly skills: readonly InspectedSkill[];
|
|
48
|
+
readonly orphans: readonly {
|
|
49
|
+
readonly name: string;
|
|
50
|
+
readonly installedHash: string;
|
|
51
|
+
readonly recordedHash: string;
|
|
52
|
+
readonly modified: boolean;
|
|
53
|
+
}[];
|
|
54
|
+
readonly summary: Readonly<Record<SkillStatus, number>>;
|
|
55
|
+
readonly restartRequired: boolean;
|
|
56
|
+
}
|
|
57
|
+
export interface SkillsSyncResult {
|
|
58
|
+
readonly action: "synced" | "planned" | "skipped";
|
|
59
|
+
readonly updated: readonly string[];
|
|
60
|
+
readonly removed: readonly string[];
|
|
61
|
+
readonly blocked: readonly string[];
|
|
62
|
+
readonly backupDir?: string;
|
|
63
|
+
readonly status: SkillsStatus;
|
|
64
|
+
readonly restartRequired: boolean;
|
|
65
|
+
}
|
|
66
|
+
export interface SkillsSyncDeps {
|
|
67
|
+
readonly install: (names: readonly string[]) => Promise<void>;
|
|
68
|
+
readonly remove?: (names: readonly string[]) => Promise<void>;
|
|
69
|
+
readonly now?: () => Date;
|
|
70
|
+
}
|
|
71
|
+
export declare function buildSkillsManifest(packageRoot: string, versions: {
|
|
72
|
+
readonly packageVersion: string;
|
|
73
|
+
readonly contractVersion: string;
|
|
74
|
+
}): SkillsBundleManifest;
|
|
75
|
+
export declare function writeSkillsManifest(packageRoot: string, outputPath: string, versions: {
|
|
76
|
+
readonly packageVersion: string;
|
|
77
|
+
readonly contractVersion: string;
|
|
78
|
+
}): SkillsBundleManifest;
|
|
79
|
+
export declare function loadAndVerifySkillsManifest(packageRoot: string, manifestPath?: string): SkillsBundleManifest;
|
|
80
|
+
export declare function inspectSkills(input: {
|
|
81
|
+
readonly manifest: SkillsBundleManifest;
|
|
82
|
+
readonly installedRoot: string;
|
|
83
|
+
readonly state: SkillsInstallState | null;
|
|
84
|
+
}): SkillsStatus;
|
|
85
|
+
export declare function syncSkills(input: {
|
|
86
|
+
readonly manifest: SkillsBundleManifest;
|
|
87
|
+
readonly packageRoot: string;
|
|
88
|
+
readonly installedRoot: string;
|
|
89
|
+
readonly statePath: string;
|
|
90
|
+
readonly dryRun: boolean;
|
|
91
|
+
readonly force: boolean;
|
|
92
|
+
}, deps: SkillsSyncDeps): Promise<SkillsSyncResult>;
|
|
93
|
+
export declare function loadSkillsState(path: string): SkillsInstallState | null;
|
|
94
|
+
export declare function hashSkillDirectory(skillRoot: string): string;
|
|
95
|
+
export declare function readSkillVersion(skillPath: string): string | null;
|
|
96
|
+
export declare function readSkillName(skillPath: string): string | null;
|