@springbrand/cli 0.1.0
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 +167 -0
- package/dist/commands/auth.d.ts +4 -0
- package/dist/commands/auth.d.ts.map +1 -0
- package/dist/commands/auth.js +241 -0
- package/dist/commands/auth.js.map +1 -0
- package/dist/commands/check-version.d.ts +3 -0
- package/dist/commands/check-version.d.ts.map +1 -0
- package/dist/commands/check-version.js +112 -0
- package/dist/commands/check-version.js.map +1 -0
- package/dist/commands/config-claude.d.ts +4 -0
- package/dist/commands/config-claude.d.ts.map +1 -0
- package/dist/commands/config-claude.js +78 -0
- package/dist/commands/config-claude.js.map +1 -0
- package/dist/commands/connect.d.ts +41 -0
- package/dist/commands/connect.d.ts.map +1 -0
- package/dist/commands/connect.js +901 -0
- package/dist/commands/connect.js.map +1 -0
- package/dist/commands/doctor.d.ts +6 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +124 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/upgrade.d.ts +9 -0
- package/dist/commands/upgrade.d.ts.map +1 -0
- package/dist/commands/upgrade.js +133 -0
- package/dist/commands/upgrade.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/agent-detect.d.ts +33 -0
- package/dist/lib/agent-detect.d.ts.map +1 -0
- package/dist/lib/agent-detect.js +81 -0
- package/dist/lib/agent-detect.js.map +1 -0
- package/dist/lib/agent-launcher.d.ts +22 -0
- package/dist/lib/agent-launcher.d.ts.map +1 -0
- package/dist/lib/agent-launcher.js +67 -0
- package/dist/lib/agent-launcher.js.map +1 -0
- package/dist/lib/auth.d.ts +90 -0
- package/dist/lib/auth.d.ts.map +1 -0
- package/dist/lib/auth.js +327 -0
- package/dist/lib/auth.js.map +1 -0
- package/dist/lib/bundled-skill.d.ts +5 -0
- package/dist/lib/bundled-skill.d.ts.map +1 -0
- package/dist/lib/bundled-skill.js +13 -0
- package/dist/lib/bundled-skill.js.map +1 -0
- package/dist/lib/claude-config.d.ts +19 -0
- package/dist/lib/claude-config.d.ts.map +1 -0
- package/dist/lib/claude-config.js +202 -0
- package/dist/lib/claude-config.js.map +1 -0
- package/dist/lib/cli-install.d.ts +40 -0
- package/dist/lib/cli-install.d.ts.map +1 -0
- package/dist/lib/cli-install.js +42 -0
- package/dist/lib/cli-install.js.map +1 -0
- package/dist/lib/command-code-config.d.ts +5 -0
- package/dist/lib/command-code-config.d.ts.map +1 -0
- package/dist/lib/command-code-config.js +16 -0
- package/dist/lib/command-code-config.js.map +1 -0
- package/dist/lib/connect-all-auth.d.ts +21 -0
- package/dist/lib/connect-all-auth.d.ts.map +1 -0
- package/dist/lib/connect-all-auth.js +113 -0
- package/dist/lib/connect-all-auth.js.map +1 -0
- package/dist/lib/connect-all-summary.d.ts +10 -0
- package/dist/lib/connect-all-summary.d.ts.map +1 -0
- package/dist/lib/connect-all-summary.js +153 -0
- package/dist/lib/connect-all-summary.js.map +1 -0
- package/dist/lib/connect-all-uninstall.d.ts +7 -0
- package/dist/lib/connect-all-uninstall.d.ts.map +1 -0
- package/dist/lib/connect-all-uninstall.js +249 -0
- package/dist/lib/connect-all-uninstall.js.map +1 -0
- package/dist/lib/connect-all.d.ts +42 -0
- package/dist/lib/connect-all.d.ts.map +1 -0
- package/dist/lib/connect-all.js +438 -0
- package/dist/lib/connect-all.js.map +1 -0
- package/dist/lib/connect-auth.d.ts +7 -0
- package/dist/lib/connect-auth.d.ts.map +1 -0
- package/dist/lib/connect-auth.js +50 -0
- package/dist/lib/connect-auth.js.map +1 -0
- package/dist/lib/connect-clients.d.ts +108 -0
- package/dist/lib/connect-clients.d.ts.map +1 -0
- package/dist/lib/connect-clients.js +358 -0
- package/dist/lib/connect-clients.js.map +1 -0
- package/dist/lib/connect-fallback.d.ts +27 -0
- package/dist/lib/connect-fallback.d.ts.map +1 -0
- package/dist/lib/connect-fallback.js +166 -0
- package/dist/lib/connect-fallback.js.map +1 -0
- package/dist/lib/connect-picker.d.ts +19 -0
- package/dist/lib/connect-picker.d.ts.map +1 -0
- package/dist/lib/connect-picker.js +155 -0
- package/dist/lib/connect-picker.js.map +1 -0
- package/dist/lib/connect-preflight.d.ts +17 -0
- package/dist/lib/connect-preflight.d.ts.map +1 -0
- package/dist/lib/connect-preflight.js +81 -0
- package/dist/lib/connect-preflight.js.map +1 -0
- package/dist/lib/connect-runtime.d.ts +109 -0
- package/dist/lib/connect-runtime.d.ts.map +1 -0
- package/dist/lib/connect-runtime.js +360 -0
- package/dist/lib/connect-runtime.js.map +1 -0
- package/dist/lib/constants.d.ts +23 -0
- package/dist/lib/constants.d.ts.map +1 -0
- package/dist/lib/constants.js +87 -0
- package/dist/lib/constants.js.map +1 -0
- package/dist/lib/cursor-config.d.ts +16 -0
- package/dist/lib/cursor-config.d.ts.map +1 -0
- package/dist/lib/cursor-config.js +34 -0
- package/dist/lib/cursor-config.js.map +1 -0
- package/dist/lib/doctor-checks.d.ts +21 -0
- package/dist/lib/doctor-checks.d.ts.map +1 -0
- package/dist/lib/doctor-checks.js +312 -0
- package/dist/lib/doctor-checks.js.map +1 -0
- package/dist/lib/doctor-repairs.d.ts +11 -0
- package/dist/lib/doctor-repairs.d.ts.map +1 -0
- package/dist/lib/doctor-repairs.js +130 -0
- package/dist/lib/doctor-repairs.js.map +1 -0
- package/dist/lib/doctor-report.d.ts +195 -0
- package/dist/lib/doctor-report.d.ts.map +1 -0
- package/dist/lib/doctor-report.js +102 -0
- package/dist/lib/doctor-report.js.map +1 -0
- package/dist/lib/doctor-telemetry.d.ts +9 -0
- package/dist/lib/doctor-telemetry.d.ts.map +1 -0
- package/dist/lib/doctor-telemetry.js +63 -0
- package/dist/lib/doctor-telemetry.js.map +1 -0
- package/dist/lib/harness-detect.d.ts +33 -0
- package/dist/lib/harness-detect.d.ts.map +1 -0
- package/dist/lib/harness-detect.js +70 -0
- package/dist/lib/harness-detect.js.map +1 -0
- package/dist/lib/harness-spec.d.ts +285 -0
- package/dist/lib/harness-spec.d.ts.map +1 -0
- package/dist/lib/harness-spec.js +268 -0
- package/dist/lib/harness-spec.js.map +1 -0
- package/dist/lib/harness.d.ts +27 -0
- package/dist/lib/harness.d.ts.map +1 -0
- package/dist/lib/harness.js +125 -0
- package/dist/lib/harness.js.map +1 -0
- package/dist/lib/hermes-config.d.ts +22 -0
- package/dist/lib/hermes-config.d.ts.map +1 -0
- package/dist/lib/hermes-config.js +76 -0
- package/dist/lib/hermes-config.js.map +1 -0
- package/dist/lib/hermes-env.d.ts +19 -0
- package/dist/lib/hermes-env.d.ts.map +1 -0
- package/dist/lib/hermes-env.js +169 -0
- package/dist/lib/hermes-env.js.map +1 -0
- package/dist/lib/hermes-plugin.d.ts +40 -0
- package/dist/lib/hermes-plugin.d.ts.map +1 -0
- package/dist/lib/hermes-plugin.js +168 -0
- package/dist/lib/hermes-plugin.js.map +1 -0
- package/dist/lib/install-root.d.ts +18 -0
- package/dist/lib/install-root.d.ts.map +1 -0
- package/dist/lib/install-root.js +55 -0
- package/dist/lib/install-root.js.map +1 -0
- package/dist/lib/mcp-config.d.ts +36 -0
- package/dist/lib/mcp-config.d.ts.map +1 -0
- package/dist/lib/mcp-config.js +90 -0
- package/dist/lib/mcp-config.js.map +1 -0
- package/dist/lib/mcp-endpoint.d.ts +16 -0
- package/dist/lib/mcp-endpoint.d.ts.map +1 -0
- package/dist/lib/mcp-endpoint.js +41 -0
- package/dist/lib/mcp-endpoint.js.map +1 -0
- package/dist/lib/mcp-json-config.d.ts +43 -0
- package/dist/lib/mcp-json-config.d.ts.map +1 -0
- package/dist/lib/mcp-json-config.js +164 -0
- package/dist/lib/mcp-json-config.js.map +1 -0
- package/dist/lib/notice.d.ts +13 -0
- package/dist/lib/notice.d.ts.map +1 -0
- package/dist/lib/notice.js +73 -0
- package/dist/lib/notice.js.map +1 -0
- package/dist/lib/omp-config.d.ts +18 -0
- package/dist/lib/omp-config.d.ts.map +1 -0
- package/dist/lib/omp-config.js +73 -0
- package/dist/lib/omp-config.js.map +1 -0
- package/dist/lib/output.d.ts +22 -0
- package/dist/lib/output.d.ts.map +1 -0
- package/dist/lib/output.js +92 -0
- package/dist/lib/output.js.map +1 -0
- package/dist/lib/pi-config.d.ts +27 -0
- package/dist/lib/pi-config.d.ts.map +1 -0
- package/dist/lib/pi-config.js +113 -0
- package/dist/lib/pi-config.js.map +1 -0
- package/dist/lib/registration-detect.d.ts +28 -0
- package/dist/lib/registration-detect.d.ts.map +1 -0
- package/dist/lib/registration-detect.js +563 -0
- package/dist/lib/registration-detect.js.map +1 -0
- package/dist/lib/setup-telemetry.d.ts +273 -0
- package/dist/lib/setup-telemetry.d.ts.map +1 -0
- package/dist/lib/setup-telemetry.js +309 -0
- package/dist/lib/setup-telemetry.js.map +1 -0
- package/dist/lib/signals.d.ts +14 -0
- package/dist/lib/signals.d.ts.map +1 -0
- package/dist/lib/signals.js +29 -0
- package/dist/lib/signals.js.map +1 -0
- package/dist/lib/skill-install.d.ts +10 -0
- package/dist/lib/skill-install.d.ts.map +1 -0
- package/dist/lib/skill-install.js +94 -0
- package/dist/lib/skill-install.js.map +1 -0
- package/dist/lib/skill-paths.d.ts +7 -0
- package/dist/lib/skill-paths.d.ts.map +1 -0
- package/dist/lib/skill-paths.js +37 -0
- package/dist/lib/skill-paths.js.map +1 -0
- package/dist/lib/skill-vendor.d.ts +20 -0
- package/dist/lib/skill-vendor.d.ts.map +1 -0
- package/dist/lib/skill-vendor.js +215 -0
- package/dist/lib/skill-vendor.js.map +1 -0
- package/dist/lib/skill.d.ts +14 -0
- package/dist/lib/skill.d.ts.map +1 -0
- package/dist/lib/skill.js +87 -0
- package/dist/lib/skill.js.map +1 -0
- package/dist/lib/verify.d.ts +35 -0
- package/dist/lib/verify.d.ts.map +1 -0
- package/dist/lib/verify.js +169 -0
- package/dist/lib/verify.js.map +1 -0
- package/dist/program.d.ts +8 -0
- package/dist/program.d.ts.map +1 -0
- package/dist/program.js +54 -0
- package/dist/program.js.map +1 -0
- package/package.json +55 -0
- package/skill/springbrand-action-api/SKILL.md +49 -0
- package/skill/springbrand-action-api/references/action-aliases.md +156 -0
- package/skill/springbrand-action-api/references/action-discovery.md +95 -0
- package/skill/springbrand-connector/SKILL.md +49 -0
- package/skill/springbrand-gtm/SKILL.md +34 -0
- package/skill/springbrand-platform/SKILL.md +55 -0
- package/skill/springbrand-platform/references/plugin-discovery.md +94 -0
- package/skill/use-springbrand/SKILL.md +70 -0
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** 复刻自 tiny-fish CLI 编译产物:skill-install.d.ts + skill-install.impl.js */
|
|
2
|
+
import type { InstallOptions } from './cli-install.js';
|
|
3
|
+
import type { SkillAgent } from './connect-clients.js';
|
|
4
|
+
export declare function installWebSkill(client: {
|
|
5
|
+
skillAgent?: SkillAgent;
|
|
6
|
+
displayName: string;
|
|
7
|
+
}, { verbose }: Pick<InstallOptions, 'verbose'>): void;
|
|
8
|
+
/** Rewrite the vendored skill where connect recorded installs; true iff bytes changed. */
|
|
9
|
+
export declare function updateWebSkill({ verbose }: InstallOptions): boolean;
|
|
10
|
+
//# sourceMappingURL=skill-install.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill-install.d.ts","sourceRoot":"","sources":["../../src/lib/skill-install.ts"],"names":[],"mappings":"AAAA,wEAAwE;AAExE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAYvD,wBAAgB,eAAe,CAAC,MAAM,EAAE;IACpC,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;CACvB,EAAE,EAAE,OAAO,EAAE,EAAE,IAAI,CAAC,cAAc,EAAE,SAAS,CAAC,GAAG,IAAI,CAMrD;AAUD,0FAA0F;AAC1F,wBAAgB,cAAc,CAAC,EAAE,OAAO,EAAE,EAAE,cAAc,GAAG,OAAO,CAyBnE"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/** 复刻自 tiny-fish CLI 编译产物:skill-install.d.ts + skill-install.impl.js */
|
|
2
|
+
import * as fs from 'node:fs';
|
|
3
|
+
import * as path from 'node:path';
|
|
4
|
+
import spawn from 'cross-spawn';
|
|
5
|
+
import { loadConfig } from './auth.js';
|
|
6
|
+
import { captureStdio, capturedOutput, replay } from './cli-install.js';
|
|
7
|
+
import { CURSOR_SKILL_TARGET, NATIVE_MCP_CLIENTS, OPENCLAW, openclawSkillInstallArgs, } from './connect-clients.js';
|
|
8
|
+
import { ConnectInterruptedError, ConnectStepError, probeSupportVariant, throwIfInterrupted, } from './connect-runtime.js';
|
|
9
|
+
import { BUNDLED_SKILL_NAMES } from './constants.js';
|
|
10
|
+
import { installedPackageDir, installRoot } from './install-root.js';
|
|
11
|
+
import { errLine } from './output.js';
|
|
12
|
+
import { clearSkillLockEntry, writeWebSkills } from './skill-vendor.js';
|
|
13
|
+
export function installWebSkill(client, { verbose }) {
|
|
14
|
+
if (!client.skillAgent)
|
|
15
|
+
return;
|
|
16
|
+
errLine(`Installing the SpringBrand web skill in ${client.displayName}...`);
|
|
17
|
+
writeWebSkills([client.skillAgent]);
|
|
18
|
+
clearSkillLockEntry({ verbose });
|
|
19
|
+
}
|
|
20
|
+
// The running process predates the install it just ran, so its own bundle is stale.
|
|
21
|
+
function freshBundleDir() {
|
|
22
|
+
const root = installRoot();
|
|
23
|
+
if (!root)
|
|
24
|
+
return undefined;
|
|
25
|
+
const dir = path.join(installedPackageDir(root.nodeModules), 'skill');
|
|
26
|
+
// A failed or pre-bundle install has none; fall back to our own copy.
|
|
27
|
+
return BUNDLED_SKILL_NAMES.every(name => fs.existsSync(path.join(dir, name, 'SKILL.md'))) ? dir : undefined;
|
|
28
|
+
}
|
|
29
|
+
/** Rewrite the vendored skill where connect recorded installs; true iff bytes changed. */
|
|
30
|
+
export function updateWebSkill({ verbose }) {
|
|
31
|
+
// One entry per `sp connect <client>`, persisted by PF-3169.
|
|
32
|
+
const connected = loadConfig().connect ?? {};
|
|
33
|
+
const skillAgents = [
|
|
34
|
+
...NATIVE_MCP_CLIENTS.filter((client) => connected[client.connectClient]).map((client) => client.skillAgent),
|
|
35
|
+
// Cursor is not a NativeMcpClient — it writes its own MCP config.
|
|
36
|
+
...(connected['cursor'] ? [CURSOR_SKILL_TARGET.skillAgent] : []),
|
|
37
|
+
].filter((agent) => agent !== undefined);
|
|
38
|
+
const hasOpenClaw = Boolean(connected['openclaw']);
|
|
39
|
+
// No recorded skill install means no target dirs; connect is the install path.
|
|
40
|
+
if (skillAgents.length === 0 && !hasOpenClaw) {
|
|
41
|
+
errLine('No use-springbrand skill to refresh. Run `sp connect <client>` to install it.');
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
let refreshed = false;
|
|
45
|
+
if (skillAgents.length > 0) {
|
|
46
|
+
if (verbose)
|
|
47
|
+
errLine(`Refreshing the SpringBrand web skill for ${skillAgents.join(', ')}...`);
|
|
48
|
+
refreshed = writeWebSkills(skillAgents, { sourceDir: freshBundleDir() });
|
|
49
|
+
clearSkillLockEntry({ verbose });
|
|
50
|
+
}
|
|
51
|
+
// OpenClaw keeps its skill under its own CLI, so it needs its own refresh.
|
|
52
|
+
if (hasOpenClaw)
|
|
53
|
+
refreshed = reinstallOpenClawSkill(verbose) || refreshed;
|
|
54
|
+
return refreshed;
|
|
55
|
+
}
|
|
56
|
+
/** OpenClaw rejects an unknown ack flag, so never guess. */
|
|
57
|
+
function openclawAckFlag() {
|
|
58
|
+
try {
|
|
59
|
+
return { ok: true, flag: probeSupportVariant(OPENCLAW) };
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
// Ctrl+C during the probe must still abort the upgrade, not skip a step.
|
|
63
|
+
if (error instanceof ConnectInterruptedError)
|
|
64
|
+
throw error;
|
|
65
|
+
// A stale context entry must not fail an otherwise successful upgrade.
|
|
66
|
+
if (error instanceof ConnectStepError) {
|
|
67
|
+
const detail = error.failureReason === 'harness_not_installed'
|
|
68
|
+
? 'OpenClaw is not on PATH.'
|
|
69
|
+
: error.message;
|
|
70
|
+
return { ok: false, reason: `${detail} Its SpringBrand skill was left unchanged.` };
|
|
71
|
+
}
|
|
72
|
+
return {
|
|
73
|
+
ok: false,
|
|
74
|
+
reason: "Could not read OpenClaw's skill installer options, so its SpringBrand skill was left unchanged.",
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
function reinstallOpenClawSkill(verbose) {
|
|
79
|
+
if (verbose)
|
|
80
|
+
errLine('Refreshing the SpringBrand skill in OpenClaw...');
|
|
81
|
+
const ack = openclawAckFlag();
|
|
82
|
+
if (!ack.ok) {
|
|
83
|
+
errLine(ack.reason ?? 'Could not refresh the SpringBrand skill in OpenClaw.');
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
const result = spawn.sync('openclaw', openclawSkillInstallArgs(ack.flag), captureStdio(verbose));
|
|
87
|
+
if (result.error || result.status !== 0) {
|
|
88
|
+
throwIfInterrupted(result);
|
|
89
|
+
replay(capturedOutput(result));
|
|
90
|
+
throw new Error('Could not refresh the SpringBrand skill in OpenClaw', { cause: result.error });
|
|
91
|
+
}
|
|
92
|
+
return true;
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=skill-install.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill-install.js","sourceRoot":"","sources":["../../src/lib/skill-install.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/** 复刻自 tiny-fish CLI 编译产物:skill-paths.d.ts + skill-paths.impl.js */
|
|
2
|
+
import type { SkillAgent } from './harness-spec.js';
|
|
3
|
+
/** The skill's own dir under where skills@1.5.15 wrote for this agent. */
|
|
4
|
+
export declare function skillTargetDir(agent: SkillAgent, name?: string): string;
|
|
5
|
+
/** Mirrors skills@1.5.15 getSkillLockPath(); missing the XDG branch strands entries. */
|
|
6
|
+
export declare function skillLockPath(): string;
|
|
7
|
+
//# sourceMappingURL=skill-paths.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill-paths.d.ts","sourceRoot":"","sources":["../../src/lib/skill-paths.ts"],"names":[],"mappings":"AAAA,oEAAoE;AAEpE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAyBpD,0EAA0E;AAC1E,wBAAgB,cAAc,CAAC,KAAK,EAAE,UAAU,EAAE,IAAI,GAAE,MAAuB,GAAG,MAAM,CAEvF;AACD,wFAAwF;AACxF,wBAAgB,aAAa,IAAI,MAAM,CAKtC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/** 复刻自 tiny-fish CLI 编译产物:skill-paths.d.ts + skill-paths.impl.js */
|
|
2
|
+
import * as os from 'node:os';
|
|
3
|
+
import * as path from 'node:path';
|
|
4
|
+
import { WEB_SKILL_NAME } from './constants.js';
|
|
5
|
+
// Mirrors skills@1.5.15 exactly: it trims and falls back on empty values.
|
|
6
|
+
function agentHome(override, fallback) {
|
|
7
|
+
return process.env[override]?.trim() || path.join(os.homedir(), fallback); // nosemgrep: path-join-resolve-traversal -- fixed dir names under os.homedir()
|
|
8
|
+
}
|
|
9
|
+
// `skills` writes here for the universal agents, whose own config dirs it never touches.
|
|
10
|
+
function canonicalSkillsDir() {
|
|
11
|
+
return path.join(os.homedir(), '.agents', 'skills'); // nosemgrep: path-join-resolve-traversal -- fixed dir names under os.homedir()
|
|
12
|
+
}
|
|
13
|
+
// Where the harness reads. Both of the modes `add` picks land the skill here.
|
|
14
|
+
const SKILL_DIR_BY_AGENT = {
|
|
15
|
+
'claude-code': () => path.join(agentHome('CLAUDE_CONFIG_DIR', '.claude'), 'skills'),
|
|
16
|
+
// The env value, not resolveHermesHome(): skills@1.5.15 reads $HERMES_HOME directly.
|
|
17
|
+
'hermes-agent': () => path.join(agentHome('HERMES_HOME', '.hermes'), 'skills'),
|
|
18
|
+
codex: canonicalSkillsDir,
|
|
19
|
+
// Not the canonical dir: `skills` writes this one under the harness's own config dir.
|
|
20
|
+
'command-code': () => path.join(os.homedir(), '.commandcode', 'skills'), // nosemgrep: path-join-resolve-traversal -- fixed dir names under os.homedir()
|
|
21
|
+
cursor: canonicalSkillsDir,
|
|
22
|
+
opencode: canonicalSkillsDir,
|
|
23
|
+
// `skills` writes pi's here whatever PI_CODING_AGENT_DIR says.
|
|
24
|
+
pi: () => path.join(os.homedir(), '.pi', 'agent', 'skills'), // nosemgrep: path-join-resolve-traversal -- fixed dir names under os.homedir()
|
|
25
|
+
};
|
|
26
|
+
/** The skill's own dir under where skills@1.5.15 wrote for this agent. */
|
|
27
|
+
export function skillTargetDir(agent, name = WEB_SKILL_NAME) {
|
|
28
|
+
return path.join(SKILL_DIR_BY_AGENT[agent](), name);
|
|
29
|
+
}
|
|
30
|
+
/** Mirrors skills@1.5.15 getSkillLockPath(); missing the XDG branch strands entries. */
|
|
31
|
+
export function skillLockPath() {
|
|
32
|
+
const xdgStateHome = process.env.XDG_STATE_HOME?.trim();
|
|
33
|
+
if (xdgStateHome)
|
|
34
|
+
return path.join(xdgStateHome, 'skills', '.skill-lock.json');
|
|
35
|
+
return path.join(os.homedir(), '.agents', '.skill-lock.json');
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=skill-paths.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill-paths.js","sourceRoot":"","sources":["../../src/lib/skill-paths.ts"],"names":[],"mappings":"AAAA,oEAAoE;AAGpE,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,0EAA0E;AAC1E,SAAS,SAAS,CAAC,QAAgB,EAAE,QAAgB;IACjD,OAAO,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,IAAI,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,QAAQ,CAAC,CAAC,CAAC,+EAA+E;AAC9J,CAAC;AACD,yFAAyF;AACzF,SAAS,kBAAkB;IACvB,OAAO,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC,CAAC,+EAA+E;AACxI,CAAC;AACD,8EAA8E;AAC9E,MAAM,kBAAkB,GAAG;IACvB,aAAa,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,mBAAmB,EAAE,SAAS,CAAC,EAAE,QAAQ,CAAC;IACnF,qFAAqF;IACrF,cAAc,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,aAAa,EAAE,SAAS,CAAC,EAAE,QAAQ,CAAC;IAC9E,KAAK,EAAE,kBAAkB;IACzB,sFAAsF;IACtF,cAAc,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,cAAc,EAAE,QAAQ,CAAC,EAAE,+EAA+E;IACxJ,MAAM,EAAE,kBAAkB;IAC1B,QAAQ,EAAE,kBAAkB;IAC5B,+DAA+D;IAC/D,EAAE,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,+EAA+E;CAC/I,CAAC;AACF,0EAA0E;AAC1E,MAAM,UAAU,cAAc,CAAC,KAAiB,EAAE,OAAe,cAAc;IAC3E,OAAO,IAAI,CAAC,IAAI,CAAC,kBAAkB,CAAC,KAAK,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;AACxD,CAAC;AACD,wFAAwF;AACxF,MAAM,UAAU,aAAa;IACzB,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE,IAAI,EAAE,CAAC;IACxD,IAAI,YAAY;QACZ,OAAO,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,QAAQ,EAAE,kBAAkB,CAAC,CAAC;IACjE,OAAO,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,kBAAkB,CAAC,CAAC;AAClE,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/** 复刻自 tiny-fish CLI 编译产物:skill-vendor.d.ts + skill-vendor.impl.js */
|
|
2
|
+
import type { SkillAgent } from './harness-spec.js';
|
|
3
|
+
/**
|
|
4
|
+
* Writes the bundled skill where each agent reads it; true iff bytes changed.
|
|
5
|
+
*
|
|
6
|
+
* Synchronous on purpose: connect flows are sync, a new await breaks them.
|
|
7
|
+
*/
|
|
8
|
+
export declare function writeWebSkill(agents: SkillAgent[], opts?: {
|
|
9
|
+
sourceDir?: string;
|
|
10
|
+
}): boolean;
|
|
11
|
+
/** Writes the complete CLI Skill set while preserving each target's atomic swap. */
|
|
12
|
+
export declare function writeWebSkills(agents: SkillAgent[], opts?: {
|
|
13
|
+
sourceDir?: string;
|
|
14
|
+
skillNames?: readonly string[];
|
|
15
|
+
}): boolean;
|
|
16
|
+
/** Best effort: a lock cleanup failure must never fail an install. */
|
|
17
|
+
export declare function clearSkillLockEntry(opts?: {
|
|
18
|
+
verbose?: boolean;
|
|
19
|
+
}): void;
|
|
20
|
+
//# sourceMappingURL=skill-vendor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill-vendor.d.ts","sourceRoot":"","sources":["../../src/lib/skill-vendor.ts"],"names":[],"mappings":"AAAA,sEAAsE;AAEtE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAYpD;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,UAAU,EAAE,EAAE,IAAI,CAAC,EAAE;IACvD,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB,GAAG,OAAO,CAEV;AAED,oFAAoF;AACpF,wBAAgB,cAAc,CAAC,MAAM,EAAE,UAAU,EAAE,EAAE,IAAI,CAAC,EAAE;IACxD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAClC,GAAG,OAAO,CAkBV;AA8JD,sEAAsE;AACtE,wBAAgB,mBAAmB,CAAC,IAAI,CAAC,EAAE;IACvC,OAAO,CAAC,EAAE,OAAO,CAAC;CACrB,GAAG,IAAI,CAeP"}
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
/** 复刻自 tiny-fish CLI 编译产物:skill-vendor.d.ts + skill-vendor.impl.js */
|
|
2
|
+
import * as fs from 'node:fs';
|
|
3
|
+
import * as path from 'node:path';
|
|
4
|
+
import { bundledSkillDir, bundledSkillNames } from './bundled-skill.js';
|
|
5
|
+
import { BUNDLED_SKILL_NAMES, WEB_SKILL_NAME } from './constants.js';
|
|
6
|
+
import { ConnectStepError } from './connect-runtime.js';
|
|
7
|
+
import { errLine } from './output.js';
|
|
8
|
+
import { skillLockPath, skillTargetDir } from './skill-paths.js';
|
|
9
|
+
// A younger staging dir may belong to a live concurrent connect.
|
|
10
|
+
const STAGING_SWEEP_MIN_AGE_MS = 5 * 60_000;
|
|
11
|
+
// Under the route's 500-char tail-slice; margin for caller prefixes.
|
|
12
|
+
const FAILURE_DETAIL_MAX_CHARS = 425;
|
|
13
|
+
/**
|
|
14
|
+
* Writes the bundled skill where each agent reads it; true iff bytes changed.
|
|
15
|
+
*
|
|
16
|
+
* Synchronous on purpose: connect flows are sync, a new await breaks them.
|
|
17
|
+
*/
|
|
18
|
+
export function writeWebSkill(agents, opts) {
|
|
19
|
+
return writeWebSkills(agents, opts);
|
|
20
|
+
}
|
|
21
|
+
/** Writes the complete CLI Skill set while preserving each target's atomic swap. */
|
|
22
|
+
export function writeWebSkills(agents, opts) {
|
|
23
|
+
const sourceRoot = opts?.sourceDir ?? path.dirname(bundledSkillDir());
|
|
24
|
+
const skillNames = opts?.skillNames ?? bundledSkillNames();
|
|
25
|
+
const targetDirs = [...new Set(agents.map(agent => path.dirname(skillTargetDir(agent))))];
|
|
26
|
+
let changed = false;
|
|
27
|
+
for (const baseDir of targetDirs) {
|
|
28
|
+
for (const skillName of skillNames) {
|
|
29
|
+
const sourceDir = path.join(sourceRoot, skillName);
|
|
30
|
+
const targetDir = path.join(baseDir, skillName);
|
|
31
|
+
try {
|
|
32
|
+
changed = writeSkillDir(sourceDir, targetDir) || changed;
|
|
33
|
+
}
|
|
34
|
+
catch (error) {
|
|
35
|
+
throw skillWriteError(error, targetDir);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return changed;
|
|
40
|
+
}
|
|
41
|
+
function writeSkillDir(sourceDir, targetDir) {
|
|
42
|
+
const parent = path.dirname(targetDir);
|
|
43
|
+
fs.mkdirSync(parent, { recursive: true });
|
|
44
|
+
sweepStaleStaging(parent);
|
|
45
|
+
if (matchesSource(sourceDir, targetDir))
|
|
46
|
+
return false;
|
|
47
|
+
// Stage-then-swap: an early rm would strand the user skill-less on failure.
|
|
48
|
+
const stagingDir = path.join(parent, `${WEB_SKILL_NAME}.tmp-${process.pid}`);
|
|
49
|
+
fs.rmSync(stagingDir, { recursive: true, force: true });
|
|
50
|
+
fs.mkdirSync(stagingDir);
|
|
51
|
+
for (const name of fs.readdirSync(sourceDir)) {
|
|
52
|
+
fs.cpSync(path.join(sourceDir, name), path.join(stagingDir, name), { recursive: true });
|
|
53
|
+
}
|
|
54
|
+
swapIntoPlace(stagingDir, targetDir, sourceDir);
|
|
55
|
+
return true;
|
|
56
|
+
}
|
|
57
|
+
// The old copy survives as a sibling backup until the new dir lands.
|
|
58
|
+
function swapIntoPlace(stagingDir, targetDir, sourceDir) {
|
|
59
|
+
const backupDir = moveAsideExisting(targetDir);
|
|
60
|
+
try {
|
|
61
|
+
try {
|
|
62
|
+
fs.renameSync(stagingDir, targetDir);
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
// A concurrent connect can recreate the target mid-swap.
|
|
66
|
+
if (!isErrnoCode(error, 'ENOTEMPTY') && !isErrnoCode(error, 'EEXIST'))
|
|
67
|
+
throw error;
|
|
68
|
+
if (matchesSource(sourceDir, targetDir)) {
|
|
69
|
+
// The concurrent writer already landed these bytes; ours can go.
|
|
70
|
+
fs.rmSync(stagingDir, { recursive: true, force: true });
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
removeExistingEntry(targetDir);
|
|
74
|
+
fs.renameSync(stagingDir, targetDir);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
catch (error) {
|
|
79
|
+
fs.rmSync(stagingDir, { recursive: true, force: true });
|
|
80
|
+
restoreBackup(backupDir, targetDir);
|
|
81
|
+
throw error;
|
|
82
|
+
}
|
|
83
|
+
if (backupDir)
|
|
84
|
+
removeExistingEntry(backupDir);
|
|
85
|
+
}
|
|
86
|
+
// Sweep-prefixed name, so an orphaned backup is eventually cleaned.
|
|
87
|
+
function moveAsideExisting(targetDir) {
|
|
88
|
+
try {
|
|
89
|
+
fs.lstatSync(targetDir);
|
|
90
|
+
}
|
|
91
|
+
catch {
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
const backupDir = `${targetDir}.tmp-${process.pid}-prev`;
|
|
95
|
+
removeExistingEntry(backupDir);
|
|
96
|
+
fs.renameSync(targetDir, backupDir);
|
|
97
|
+
return backupDir;
|
|
98
|
+
}
|
|
99
|
+
function restoreBackup(backupDir, targetDir) {
|
|
100
|
+
if (!backupDir)
|
|
101
|
+
return;
|
|
102
|
+
try {
|
|
103
|
+
fs.renameSync(backupDir, targetDir);
|
|
104
|
+
}
|
|
105
|
+
catch {
|
|
106
|
+
// A concurrent writer owns the target now; leave its copy in place.
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
/** Only a real dir with the bundle's exact file set and bytes skips. */
|
|
110
|
+
function matchesSource(sourceDir, targetDir) {
|
|
111
|
+
let stat;
|
|
112
|
+
try {
|
|
113
|
+
stat = fs.lstatSync(targetDir);
|
|
114
|
+
}
|
|
115
|
+
catch {
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
if (!stat.isDirectory())
|
|
119
|
+
return false;
|
|
120
|
+
const sourceFiles = relativeFiles(sourceDir);
|
|
121
|
+
const targetFiles = relativeFiles(targetDir);
|
|
122
|
+
if (sourceFiles.join('\n') !== targetFiles.join('\n'))
|
|
123
|
+
return false;
|
|
124
|
+
return sourceFiles.every((name) => fs.readFileSync(path.join(sourceDir, name)).equals(fs.readFileSync(path.join(targetDir, name))));
|
|
125
|
+
}
|
|
126
|
+
function relativeFiles(root) {
|
|
127
|
+
const files = [];
|
|
128
|
+
function visit(current, prefix) {
|
|
129
|
+
for (const entry of fs.readdirSync(current, { withFileTypes: true })) {
|
|
130
|
+
const relative = path.join(prefix, entry.name);
|
|
131
|
+
const full = path.join(current, entry.name);
|
|
132
|
+
if (entry.isDirectory())
|
|
133
|
+
visit(full, relative);
|
|
134
|
+
else
|
|
135
|
+
files.push(relative);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
visit(root, '');
|
|
139
|
+
return files.sort();
|
|
140
|
+
}
|
|
141
|
+
/** lstat first: a skills-CLI symlink must be unlinked, never followed. */
|
|
142
|
+
function removeExistingEntry(targetDir) {
|
|
143
|
+
let stat;
|
|
144
|
+
try {
|
|
145
|
+
stat = fs.lstatSync(targetDir);
|
|
146
|
+
}
|
|
147
|
+
catch {
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
if (stat.isDirectory()) {
|
|
151
|
+
fs.rmSync(targetDir, { recursive: true });
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
try {
|
|
155
|
+
fs.unlinkSync(targetDir);
|
|
156
|
+
}
|
|
157
|
+
catch (error) {
|
|
158
|
+
// Windows junctions: unlink is EPERM there, rmdir removes the link.
|
|
159
|
+
if (isErrnoCode(error, 'EPERM') || isErrnoCode(error, 'EISDIR'))
|
|
160
|
+
fs.rmdirSync(targetDir);
|
|
161
|
+
else
|
|
162
|
+
throw error;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
function sweepStaleStaging(parent) {
|
|
166
|
+
let entries;
|
|
167
|
+
try {
|
|
168
|
+
entries = fs.readdirSync(parent);
|
|
169
|
+
}
|
|
170
|
+
catch {
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
for (const name of entries) {
|
|
174
|
+
if (!name.startsWith(`${WEB_SKILL_NAME}.tmp-`))
|
|
175
|
+
continue;
|
|
176
|
+
try {
|
|
177
|
+
const staged = path.join(parent, name);
|
|
178
|
+
if (Date.now() - fs.lstatSync(staged).mtimeMs < STAGING_SWEEP_MIN_AGE_MS)
|
|
179
|
+
continue;
|
|
180
|
+
fs.rmSync(staged, { recursive: true, force: true });
|
|
181
|
+
}
|
|
182
|
+
catch {
|
|
183
|
+
// Best effort; a sweep failure must never fail the install.
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
// Reason stays in the closed enum; the errno rides failure_detail instead.
|
|
188
|
+
function skillWriteError(error, targetDir) {
|
|
189
|
+
const code = error.code ?? 'unknown';
|
|
190
|
+
return new ConnectStepError('Could not write the SpringBrand web skill', 'unexpected_error', {
|
|
191
|
+
cause: error,
|
|
192
|
+
failureDetail: `skill_write_failed ${code} ${targetDir}`.slice(0, FAILURE_DETAIL_MAX_CHARS),
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
function isErrnoCode(error, code) {
|
|
196
|
+
return error.code === code;
|
|
197
|
+
}
|
|
198
|
+
/** Best effort: a lock cleanup failure must never fail an install. */
|
|
199
|
+
export function clearSkillLockEntry(opts) {
|
|
200
|
+
const lockPath = skillLockPath();
|
|
201
|
+
try {
|
|
202
|
+
const lock = JSON.parse(fs.readFileSync(lockPath, 'utf8'));
|
|
203
|
+
if (!lock.skills)
|
|
204
|
+
return;
|
|
205
|
+
for (const skillName of BUNDLED_SKILL_NAMES) {
|
|
206
|
+
delete lock.skills[skillName];
|
|
207
|
+
}
|
|
208
|
+
fs.writeFileSync(lockPath, `${JSON.stringify(lock, null, 2)}\n`);
|
|
209
|
+
}
|
|
210
|
+
catch {
|
|
211
|
+
if (opts?.verbose)
|
|
212
|
+
errLine('Skipped cleaning the skills lock file.');
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
//# sourceMappingURL=skill-vendor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill-vendor.js","sourceRoot":"","sources":["../../src/lib/skill-vendor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type AgentType } from './agent-detect';
|
|
2
|
+
/**
|
|
3
|
+
* Install skill to agent's skill directory
|
|
4
|
+
*/
|
|
5
|
+
export declare function installSkill(agentType: AgentType): void;
|
|
6
|
+
/**
|
|
7
|
+
* Check if skill is already installed
|
|
8
|
+
*/
|
|
9
|
+
export declare function isSkillInstalled(agentType: AgentType): boolean;
|
|
10
|
+
/**
|
|
11
|
+
* Remove skill from agent
|
|
12
|
+
*/
|
|
13
|
+
export declare function removeSkill(agentType: AgentType): void;
|
|
14
|
+
//# sourceMappingURL=skill.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill.d.ts","sourceRoot":"","sources":["../../src/lib/skill.ts"],"names":[],"mappings":"AAEA,OAAO,EAAkB,KAAK,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAsChE;;GAEG;AACH,wBAAgB,YAAY,CAAC,SAAS,EAAE,SAAS,GAAG,IAAI,CAyBvD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAI9D;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,SAAS,EAAE,SAAS,GAAG,IAAI,CAatD"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { writeFileSync, mkdirSync, existsSync } from 'fs';
|
|
2
|
+
import { getAgentConfig } from './agent-detect';
|
|
3
|
+
/**
|
|
4
|
+
* Skill installation - mirrors SpringBrand's stage-then-swap pattern
|
|
5
|
+
*/
|
|
6
|
+
const SKILL_TEMPLATE = `---
|
|
7
|
+
name: use-mcp-gateway
|
|
8
|
+
description: Connect to SpringBrand MCP Gateway for unified tool access
|
|
9
|
+
version: 1.0.0
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# MCP Gateway Integration
|
|
13
|
+
|
|
14
|
+
This skill enables access to SpringBrand MCP Gateway, providing unified access to multiple MCP tools through a single authenticated connection.
|
|
15
|
+
|
|
16
|
+
## Usage
|
|
17
|
+
|
|
18
|
+
The gateway is automatically available when configured. Use it to:
|
|
19
|
+
- Search and discover tools across multiple MCP servers
|
|
20
|
+
- Execute tools with automatic connection management
|
|
21
|
+
- View execution history and manage connections
|
|
22
|
+
|
|
23
|
+
## Commands
|
|
24
|
+
|
|
25
|
+
\`\`\`
|
|
26
|
+
mcpg tools search <query> # Search for tools
|
|
27
|
+
mcpg tools describe <name> # View tool details
|
|
28
|
+
mcpg tools execute <name> # Execute a tool
|
|
29
|
+
mcpg connections list # List active connections
|
|
30
|
+
mcpg executions list # View execution history
|
|
31
|
+
\`\`\`
|
|
32
|
+
|
|
33
|
+
## Authentication
|
|
34
|
+
|
|
35
|
+
Authentication is handled automatically through OAuth 2.0. Run \`mcpg auth login\` if needed.
|
|
36
|
+
`;
|
|
37
|
+
/**
|
|
38
|
+
* Install skill to agent's skill directory
|
|
39
|
+
*/
|
|
40
|
+
export function installSkill(agentType) {
|
|
41
|
+
const config = getAgentConfig(agentType);
|
|
42
|
+
const skillPath = config.skillPath;
|
|
43
|
+
const skillFile = `${skillPath}/SKILL.md`;
|
|
44
|
+
try {
|
|
45
|
+
// Ensure directory exists
|
|
46
|
+
if (!existsSync(skillPath)) {
|
|
47
|
+
mkdirSync(skillPath, { recursive: true, mode: 0o755 });
|
|
48
|
+
}
|
|
49
|
+
// Write skill file (stage-then-swap pattern)
|
|
50
|
+
const tmpPath = `${skillFile}.tmp`;
|
|
51
|
+
writeFileSync(tmpPath, SKILL_TEMPLATE, { encoding: 'utf-8', mode: 0o644 });
|
|
52
|
+
// Atomic swap
|
|
53
|
+
writeFileSync(skillFile, SKILL_TEMPLATE, { encoding: 'utf-8', mode: 0o644 });
|
|
54
|
+
// Clean up temp
|
|
55
|
+
if (existsSync(tmpPath)) {
|
|
56
|
+
require('fs').unlinkSync(tmpPath);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
catch (error) {
|
|
60
|
+
throw new Error(`Failed to install skill to ${skillPath}: ${error}`);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Check if skill is already installed
|
|
65
|
+
*/
|
|
66
|
+
export function isSkillInstalled(agentType) {
|
|
67
|
+
const config = getAgentConfig(agentType);
|
|
68
|
+
const skillFile = `${config.skillPath}/SKILL.md`;
|
|
69
|
+
return existsSync(skillFile);
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Remove skill from agent
|
|
73
|
+
*/
|
|
74
|
+
export function removeSkill(agentType) {
|
|
75
|
+
const config = getAgentConfig(agentType);
|
|
76
|
+
const skillPath = config.skillPath;
|
|
77
|
+
if (!existsSync(skillPath)) {
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
try {
|
|
81
|
+
require('fs').rmSync(skillPath, { recursive: true, force: true });
|
|
82
|
+
}
|
|
83
|
+
catch (error) {
|
|
84
|
+
throw new Error(`Failed to remove skill from ${skillPath}: ${error}`);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=skill.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill.js","sourceRoot":"","sources":["../../src/lib/skill.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAE1D,OAAO,EAAE,cAAc,EAAkB,MAAM,gBAAgB,CAAC;AAEhE;;GAEG;AAEH,MAAM,cAAc,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA8BtB,CAAC;AAEF;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,SAAoB;IAC/C,MAAM,MAAM,GAAG,cAAc,CAAC,SAAS,CAAC,CAAC;IACzC,MAAM,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC;IACnC,MAAM,SAAS,GAAG,GAAG,SAAS,WAAW,CAAC;IAE1C,IAAI,CAAC;QACH,0BAA0B;QAC1B,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YAC3B,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QACzD,CAAC;QAED,6CAA6C;QAC7C,MAAM,OAAO,GAAG,GAAG,SAAS,MAAM,CAAC;QACnC,aAAa,CAAC,OAAO,EAAE,cAAc,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QAE3E,cAAc;QACd,aAAa,CAAC,SAAS,EAAE,cAAc,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QAE7E,gBAAgB;QAChB,IAAI,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;YACxB,OAAO,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;QACpC,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,8BAA8B,SAAS,KAAK,KAAK,EAAE,CAAC,CAAC;IACvE,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,SAAoB;IACnD,MAAM,MAAM,GAAG,cAAc,CAAC,SAAS,CAAC,CAAC;IACzC,MAAM,SAAS,GAAG,GAAG,MAAM,CAAC,SAAS,WAAW,CAAC;IACjD,OAAO,UAAU,CAAC,SAAS,CAAC,CAAC;AAC/B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,SAAoB;IAC9C,MAAM,MAAM,GAAG,cAAc,CAAC,SAAS,CAAC,CAAC;IACzC,MAAM,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC;IAEnC,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC3B,OAAO;IACT,CAAC;IAED,IAAI,CAAC;QACH,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACpE,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,+BAA+B,SAAS,KAAK,KAAK,EAAE,CAAC,CAAC;IACxE,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/** 复刻自 tiny-fish CLI 编译产物:verify.d.ts + verify.impl.js */
|
|
2
|
+
/** Reachability check. Verify failure is a warning, never install failure. */
|
|
3
|
+
export declare function verifyMcpHealth(mcpUrl: string): Promise<VerifyResult>;
|
|
4
|
+
/** Authenticated check — where the CLI holds the key (Cursor, OpenClaw, Hermes). */
|
|
5
|
+
export declare function verifyMcpAuth(apiKey: string, apiBaseUrl?: string): Promise<VerifyResult>;
|
|
6
|
+
export type VerifyDepth = 'health' | 'health+auth';
|
|
7
|
+
/**
|
|
8
|
+
* `credential_rejected` is the only kind that blames the key. `retryable` covers rate limits,
|
|
9
|
+
* verification outages and network faults: those keep the credential and are worth another try,
|
|
10
|
+
* so they must never block an install.
|
|
11
|
+
*/
|
|
12
|
+
export type VerifyFailureKind = 'credential_rejected' | 'retryable';
|
|
13
|
+
export interface KeyIdentityHeaders {
|
|
14
|
+
accountId: string;
|
|
15
|
+
keyId: string;
|
|
16
|
+
environment: string;
|
|
17
|
+
}
|
|
18
|
+
export interface VerifyResult {
|
|
19
|
+
depth: VerifyDepth;
|
|
20
|
+
ok: boolean;
|
|
21
|
+
reason?: string;
|
|
22
|
+
/** Authored summary of `reason`, safe to publish. Additive: `connect` still prints `reason`. */
|
|
23
|
+
code?: string;
|
|
24
|
+
/** The Gateway's stable error code, when it sent a recognised one. */
|
|
25
|
+
errorCode?: string;
|
|
26
|
+
/** Absent on success; callers branch on this rather than on the status. */
|
|
27
|
+
kind?: VerifyFailureKind;
|
|
28
|
+
/** Lets doctor tell 401 from 403 without matching prose. */
|
|
29
|
+
status?: number;
|
|
30
|
+
/** Seconds, bounded — only ever set alongside a 429. */
|
|
31
|
+
retryAfter?: number;
|
|
32
|
+
/** From the identity headers of an accepted request; proves the key, not the host. */
|
|
33
|
+
identity?: KeyIdentityHeaders;
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=verify.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verify.d.ts","sourceRoot":"","sources":["../../src/lib/verify.ts"],"names":[],"mappings":"AAAA,0DAA0D;AA0G1D,8EAA8E;AAC9E,wBAAsB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CA2B3E;AACD,oFAAoF;AACpF,wBAAsB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAgC9F;AAGD,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,aAAa,CAAC;AAEnD;;;;GAIG;AACH,MAAM,MAAM,iBAAiB,GAAG,qBAAqB,GAAG,WAAW,CAAC;AAEpE,MAAM,WAAW,kBAAkB;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,YAAY;IACzB,KAAK,EAAE,WAAW,CAAC;IACnB,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gGAAgG;IAChG,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,sEAAsE;IACtE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2EAA2E;IAC3E,IAAI,CAAC,EAAE,iBAAiB,CAAC;IACzB,4DAA4D;IAC5D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,wDAAwD;IACxD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,sFAAsF;IACtF,QAAQ,CAAC,EAAE,kBAAkB,CAAC;CACjC"}
|