@cleocode/caamp 2026.9.19 → 2026.9.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-CHPNPLOK.js → chunk-UIXTFV35.js} +245 -18
- package/dist/chunk-UIXTFV35.js.map +1 -0
- package/dist/{chunk-IBHW6GEI.js → chunk-UYVHBBJE.js} +3355 -2802
- package/dist/chunk-UYVHBBJE.js.map +1 -0
- package/dist/cli.js +205 -711
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +683 -5
- package/dist/index.js +31 -3
- package/dist/index.js.map +1 -1
- package/dist/{injector-ZUPRC2HS.js → injector-KSFK5LF2.js} +4 -2
- package/package.json +7 -7
- package/dist/chunk-CHPNPLOK.js.map +0 -1
- package/dist/chunk-IBHW6GEI.js.map +0 -1
- /package/dist/{injector-ZUPRC2HS.js.map → injector-KSFK5LF2.js.map} +0 -0
package/dist/cli.js
CHANGED
|
@@ -1,36 +1,42 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
|
+
ErrorCategories,
|
|
4
|
+
ErrorCodes,
|
|
3
5
|
MarketplaceClient,
|
|
4
6
|
PiHarness,
|
|
5
7
|
RECOMMENDATION_ERROR_CODES,
|
|
8
|
+
SkillInstallError,
|
|
9
|
+
buildEnvelope,
|
|
6
10
|
checkSkillUpdate,
|
|
11
|
+
cloneGitLabRepo,
|
|
12
|
+
cloneRepo,
|
|
7
13
|
detectAllProviders,
|
|
8
14
|
detectMcpInstallations,
|
|
9
15
|
detectProjectProviders,
|
|
10
|
-
discoverSkill,
|
|
11
16
|
discoverSkillsMulti,
|
|
12
|
-
dispatchInstallSkillAcrossProviders,
|
|
13
17
|
dispatchRemoveSkillAcrossProviders,
|
|
18
|
+
emitError,
|
|
19
|
+
emitJsonError,
|
|
14
20
|
fetchWithTimeout,
|
|
15
21
|
formatNetworkError,
|
|
16
22
|
formatSkillRecommendations,
|
|
17
23
|
getHarnessFor,
|
|
18
24
|
getInstalledProviders,
|
|
19
|
-
getSkill,
|
|
20
25
|
getSkillDir,
|
|
21
26
|
getTrackedSkills,
|
|
27
|
+
handleFormatError,
|
|
22
28
|
installBatchWithRollback,
|
|
23
29
|
installMcpServer,
|
|
30
|
+
installResolvedSkill,
|
|
31
|
+
installSkillFromSource,
|
|
24
32
|
isCatalogAvailable,
|
|
25
33
|
isHuman,
|
|
26
|
-
isMarketplaceScoped,
|
|
27
|
-
isQuiet,
|
|
28
34
|
isVerbose,
|
|
29
35
|
listAllMcpServers,
|
|
30
36
|
listCanonicalSkills,
|
|
31
37
|
listMcpServers,
|
|
32
38
|
listProfiles,
|
|
33
|
-
|
|
39
|
+
outputSuccess,
|
|
34
40
|
parseSource,
|
|
35
41
|
readConfig,
|
|
36
42
|
readLockFile,
|
|
@@ -40,6 +46,7 @@ import {
|
|
|
40
46
|
removeMcpServerFromAll,
|
|
41
47
|
removeSkillFromLock,
|
|
42
48
|
resolveDefaultTargetProviders,
|
|
49
|
+
resolveFormat,
|
|
43
50
|
resolveProfile,
|
|
44
51
|
scanDirectory,
|
|
45
52
|
scanFile,
|
|
@@ -52,7 +59,7 @@ import {
|
|
|
52
59
|
tokenizeCriteriaValue,
|
|
53
60
|
updateInstructionsSingleOperation,
|
|
54
61
|
validateSkill
|
|
55
|
-
} from "./chunk-
|
|
62
|
+
} from "./chunk-UYVHBBJE.js";
|
|
56
63
|
import {
|
|
57
64
|
buildSkillsMap,
|
|
58
65
|
checkAllInjections,
|
|
@@ -65,7 +72,7 @@ import {
|
|
|
65
72
|
groupByInstructFile,
|
|
66
73
|
injectAll,
|
|
67
74
|
providerSupports
|
|
68
|
-
} from "./chunk-
|
|
75
|
+
} from "./chunk-UIXTFV35.js";
|
|
69
76
|
import {
|
|
70
77
|
CANONICAL_HOOK_EVENTS,
|
|
71
78
|
buildHookMatrix,
|
|
@@ -76,7 +83,6 @@ import {
|
|
|
76
83
|
translateToAll
|
|
77
84
|
} from "./chunk-YCAANESR.js";
|
|
78
85
|
import {
|
|
79
|
-
buildSkillSubPathCandidates,
|
|
80
86
|
resolveProviderConfigPath,
|
|
81
87
|
resolveProviderSkillsDir
|
|
82
88
|
} from "./chunk-HDZYZTR2.js";
|
|
@@ -153,7 +159,7 @@ function emitSuccess(operation, result, mvi = "standard") {
|
|
|
153
159
|
};
|
|
154
160
|
console.log(JSON.stringify(envelope, null, 2));
|
|
155
161
|
}
|
|
156
|
-
function
|
|
162
|
+
function emitError2(operation, error, mvi = "standard") {
|
|
157
163
|
let envelope;
|
|
158
164
|
if (error instanceof LAFSCommandError) {
|
|
159
165
|
envelope = {
|
|
@@ -204,7 +210,7 @@ async function runLafsCommand(command, mvi, action) {
|
|
|
204
210
|
const result = await action();
|
|
205
211
|
emitSuccess(command, result, mvi);
|
|
206
212
|
} catch (error) {
|
|
207
|
-
|
|
213
|
+
emitError2(command, error, mvi);
|
|
208
214
|
process.exit(1);
|
|
209
215
|
}
|
|
210
216
|
}
|
|
@@ -499,121 +505,6 @@ function registerAdvancedCommands(program2) {
|
|
|
499
505
|
// src/commands/config.ts
|
|
500
506
|
import { existsSync } from "fs";
|
|
501
507
|
import pc from "picocolors";
|
|
502
|
-
|
|
503
|
-
// src/core/lafs.ts
|
|
504
|
-
import { randomUUID as randomUUID2 } from "crypto";
|
|
505
|
-
import { resolveOutputFormat } from "@cleocode/lafs";
|
|
506
|
-
function resolveFormat(options) {
|
|
507
|
-
return resolveOutputFormat({
|
|
508
|
-
jsonFlag: options.jsonFlag ?? false,
|
|
509
|
-
humanFlag: (options.humanFlag ?? false) || isHuman(),
|
|
510
|
-
projectDefault: options.projectDefault ?? "json"
|
|
511
|
-
}).format;
|
|
512
|
-
}
|
|
513
|
-
function buildEnvelope(operation, mvi, result, error, page = null, sessionId, warnings) {
|
|
514
|
-
return {
|
|
515
|
-
$schema: "https://lafs.dev/schemas/v1/envelope.schema.json",
|
|
516
|
-
_meta: {
|
|
517
|
-
specVersion: "1.0.0",
|
|
518
|
-
schemaVersion: "1.0.0",
|
|
519
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
520
|
-
operation,
|
|
521
|
-
requestId: randomUUID2(),
|
|
522
|
-
transport: "cli",
|
|
523
|
-
strict: true,
|
|
524
|
-
mvi,
|
|
525
|
-
contextVersion: 0,
|
|
526
|
-
...sessionId && { sessionId },
|
|
527
|
-
...warnings && warnings.length > 0 && { warnings }
|
|
528
|
-
},
|
|
529
|
-
success: error === null,
|
|
530
|
-
result,
|
|
531
|
-
error,
|
|
532
|
-
page
|
|
533
|
-
};
|
|
534
|
-
}
|
|
535
|
-
function emitError2(operation, mvi, code, message, category, details = {}, exitCode = 1) {
|
|
536
|
-
const envelope = buildEnvelope(operation, mvi, null, {
|
|
537
|
-
code,
|
|
538
|
-
message,
|
|
539
|
-
category,
|
|
540
|
-
retryable: category === "TRANSIENT" || category === "RATE_LIMIT",
|
|
541
|
-
retryAfterMs: null,
|
|
542
|
-
details
|
|
543
|
-
});
|
|
544
|
-
console.error(JSON.stringify(envelope, null, 2));
|
|
545
|
-
process.exit(exitCode);
|
|
546
|
-
}
|
|
547
|
-
function emitJsonError(operation, mvi, code, message, category, details = {}) {
|
|
548
|
-
const envelope = buildEnvelope(operation, mvi, null, {
|
|
549
|
-
code,
|
|
550
|
-
message,
|
|
551
|
-
category,
|
|
552
|
-
retryable: category === "TRANSIENT" || category === "RATE_LIMIT",
|
|
553
|
-
retryAfterMs: null,
|
|
554
|
-
details
|
|
555
|
-
});
|
|
556
|
-
console.error(JSON.stringify(envelope, null, 2));
|
|
557
|
-
}
|
|
558
|
-
function outputSuccess(operation, mvi, result, page, sessionId, warnings) {
|
|
559
|
-
const envelope = buildEnvelope(operation, mvi, result, null, page ?? null, sessionId, warnings);
|
|
560
|
-
if (isQuiet() && !envelope.error) {
|
|
561
|
-
return;
|
|
562
|
-
}
|
|
563
|
-
console.log(JSON.stringify(envelope, null, 2));
|
|
564
|
-
}
|
|
565
|
-
function handleFormatError(error, operation, mvi, jsonFlag) {
|
|
566
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
567
|
-
if (jsonFlag) {
|
|
568
|
-
emitJsonError(operation, mvi, "E_FORMAT_CONFLICT", message, "VALIDATION");
|
|
569
|
-
} else {
|
|
570
|
-
console.error(message);
|
|
571
|
-
}
|
|
572
|
-
process.exit(1);
|
|
573
|
-
}
|
|
574
|
-
var ErrorCategories = {
|
|
575
|
-
VALIDATION: "VALIDATION",
|
|
576
|
-
AUTH: "AUTH",
|
|
577
|
-
PERMISSION: "PERMISSION",
|
|
578
|
-
NOT_FOUND: "NOT_FOUND",
|
|
579
|
-
CONFLICT: "CONFLICT",
|
|
580
|
-
RATE_LIMIT: "RATE_LIMIT",
|
|
581
|
-
TRANSIENT: "TRANSIENT",
|
|
582
|
-
INTERNAL: "INTERNAL",
|
|
583
|
-
CONTRACT: "CONTRACT",
|
|
584
|
-
MIGRATION: "MIGRATION"
|
|
585
|
-
};
|
|
586
|
-
var ErrorCodes = {
|
|
587
|
-
// Format errors
|
|
588
|
-
FORMAT_CONFLICT: "E_FORMAT_CONFLICT",
|
|
589
|
-
INVALID_JSON: "E_INVALID_JSON",
|
|
590
|
-
// Not found errors
|
|
591
|
-
SKILL_NOT_FOUND: "E_SKILL_NOT_FOUND",
|
|
592
|
-
PROVIDER_NOT_FOUND: "E_PROVIDER_NOT_FOUND",
|
|
593
|
-
MCP_SERVER_NOT_FOUND: "E_MCP_SERVER_NOT_FOUND",
|
|
594
|
-
FILE_NOT_FOUND: "E_FILE_NOT_FOUND",
|
|
595
|
-
// Validation errors
|
|
596
|
-
INVALID_INPUT: "E_INVALID_INPUT",
|
|
597
|
-
INVALID_CONSTRAINT: "E_INVALID_CONSTRAINT",
|
|
598
|
-
INVALID_FORMAT: "E_INVALID_FORMAT",
|
|
599
|
-
// Operation errors
|
|
600
|
-
INSTALL_FAILED: "E_INSTALL_FAILED",
|
|
601
|
-
// Skills federation gates (T9564 — Sphere B)
|
|
602
|
-
SKILL_TRUST_GATE_BLOCKED: "E_SKILL_TRUST_GATE_BLOCKED",
|
|
603
|
-
FEDERATION_UNKNOWN_SOURCE_INTERACTIVE_REQUIRED: "E_FEDERATION_UNKNOWN_SOURCE_INTERACTIVE_REQUIRED",
|
|
604
|
-
FEDERATION_CHECKSUM_MISMATCH: "E_FEDERATION_CHECKSUM_MISMATCH",
|
|
605
|
-
REMOVE_FAILED: "E_REMOVE_FAILED",
|
|
606
|
-
UPDATE_FAILED: "E_UPDATE_FAILED",
|
|
607
|
-
VALIDATION_FAILED: "E_VALIDATION_FAILED",
|
|
608
|
-
AUDIT_FAILED: "E_AUDIT_FAILED",
|
|
609
|
-
// System errors
|
|
610
|
-
NETWORK_ERROR: "E_NETWORK_ERROR",
|
|
611
|
-
FILE_SYSTEM_ERROR: "E_FILE_SYSTEM_ERROR",
|
|
612
|
-
PERMISSION_DENIED: "E_PERMISSION_DENIED",
|
|
613
|
-
INTERNAL_ERROR: "E_INTERNAL_ERROR"
|
|
614
|
-
};
|
|
615
|
-
|
|
616
|
-
// src/commands/config.ts
|
|
617
508
|
function registerConfigCommand(program2) {
|
|
618
509
|
const config = program2.command("config").description("View provider configuration");
|
|
619
510
|
config.command("show").description("Show provider configuration").argument("<provider>", "Provider ID or alias").option("-g, --global", "Show global config").option("--json", "Output as JSON (default)").option("--human", "Output in human-readable format").action(
|
|
@@ -1950,60 +1841,9 @@ function registerMcpCommands(program2) {
|
|
|
1950
1841
|
// src/commands/pi/cant.ts
|
|
1951
1842
|
import { existsSync as existsSync4 } from "fs";
|
|
1952
1843
|
import { writeFile } from "fs/promises";
|
|
1953
|
-
import { tmpdir as tmpdir3 } from "os";
|
|
1954
|
-
import { isAbsolute, join as join5 } from "path";
|
|
1955
|
-
|
|
1956
|
-
// src/core/sources/github.ts
|
|
1957
|
-
import { mkdtemp, rm } from "fs/promises";
|
|
1958
1844
|
import { tmpdir } from "os";
|
|
1959
|
-
import { join as join3 } from "path";
|
|
1960
|
-
import {
|
|
1961
|
-
async function cloneRepo(owner, repo, ref, subPath) {
|
|
1962
|
-
const tmpDir = await mkdtemp(join3(tmpdir(), "caamp-"));
|
|
1963
|
-
const repoUrl = `https://github.com/${owner}/${repo}.git`;
|
|
1964
|
-
const git = simpleGit();
|
|
1965
|
-
const cloneOptions = ["--depth", "1"];
|
|
1966
|
-
if (ref) {
|
|
1967
|
-
cloneOptions.push("--branch", ref);
|
|
1968
|
-
}
|
|
1969
|
-
await git.clone(repoUrl, tmpDir, cloneOptions);
|
|
1970
|
-
const localPath = subPath ? join3(tmpDir, subPath) : tmpDir;
|
|
1971
|
-
return {
|
|
1972
|
-
localPath,
|
|
1973
|
-
cleanup: async () => {
|
|
1974
|
-
try {
|
|
1975
|
-
await rm(tmpDir, { recursive: true });
|
|
1976
|
-
} catch {
|
|
1977
|
-
}
|
|
1978
|
-
}
|
|
1979
|
-
};
|
|
1980
|
-
}
|
|
1981
|
-
|
|
1982
|
-
// src/core/sources/gitlab.ts
|
|
1983
|
-
import { mkdtemp as mkdtemp2, rm as rm2 } from "fs/promises";
|
|
1984
|
-
import { tmpdir as tmpdir2 } from "os";
|
|
1985
|
-
import { join as join4 } from "path";
|
|
1986
|
-
import { simpleGit as simpleGit2 } from "simple-git";
|
|
1987
|
-
async function cloneGitLabRepo(owner, repo, ref, subPath) {
|
|
1988
|
-
const tmpDir = await mkdtemp2(join4(tmpdir2(), "caamp-gl-"));
|
|
1989
|
-
const repoUrl = `https://gitlab.com/${owner}/${repo}.git`;
|
|
1990
|
-
const git = simpleGit2();
|
|
1991
|
-
const cloneOptions = ["--depth", "1"];
|
|
1992
|
-
if (ref) {
|
|
1993
|
-
cloneOptions.push("--branch", ref);
|
|
1994
|
-
}
|
|
1995
|
-
await git.clone(repoUrl, tmpDir, cloneOptions);
|
|
1996
|
-
const localPath = subPath ? join4(tmpDir, subPath) : tmpDir;
|
|
1997
|
-
return {
|
|
1998
|
-
localPath,
|
|
1999
|
-
cleanup: async () => {
|
|
2000
|
-
try {
|
|
2001
|
-
await rm2(tmpDir, { recursive: true });
|
|
2002
|
-
} catch {
|
|
2003
|
-
}
|
|
2004
|
-
}
|
|
2005
|
-
};
|
|
2006
|
-
}
|
|
1845
|
+
import { isAbsolute, join as join3 } from "path";
|
|
1846
|
+
import { expandTildePath } from "@cleocode/paths";
|
|
2007
1847
|
|
|
2008
1848
|
// src/commands/pi/common.ts
|
|
2009
1849
|
var PI_ERROR_CODES = {
|
|
@@ -2066,7 +1906,7 @@ function resolveProjectDir2(tier, explicit) {
|
|
|
2066
1906
|
// src/commands/pi/cant.ts
|
|
2067
1907
|
async function resolveCantSource(source) {
|
|
2068
1908
|
if (isAbsolute(source) || source.startsWith("./") || source.startsWith("../") || source.startsWith("~")) {
|
|
2069
|
-
const expanded =
|
|
1909
|
+
const expanded = expandTildePath(source);
|
|
2070
1910
|
if (!existsSync4(expanded)) {
|
|
2071
1911
|
throw new LAFSCommandError(
|
|
2072
1912
|
PI_ERROR_CODES.NOT_FOUND,
|
|
@@ -2086,7 +1926,7 @@ async function resolveCantSource(source) {
|
|
|
2086
1926
|
const parsed2 = parseSource(source);
|
|
2087
1927
|
if (parsed2.type === "github" && parsed2.owner !== void 0 && parsed2.repo !== void 0) {
|
|
2088
1928
|
const cloneResult = await cloneRepo(parsed2.owner, parsed2.repo, parsed2.ref);
|
|
2089
|
-
const filePath = parsed2.path !== void 0 ?
|
|
1929
|
+
const filePath = parsed2.path !== void 0 ? join3(cloneResult.localPath, parsed2.path) : cloneResult.localPath;
|
|
2090
1930
|
if (!existsSync4(filePath)) {
|
|
2091
1931
|
await cloneResult.cleanup();
|
|
2092
1932
|
throw new LAFSCommandError(
|
|
@@ -2104,7 +1944,7 @@ async function resolveCantSource(source) {
|
|
|
2104
1944
|
}
|
|
2105
1945
|
if (parsed2.type === "gitlab" && parsed2.owner !== void 0 && parsed2.repo !== void 0) {
|
|
2106
1946
|
const cloneResult = await cloneGitLabRepo(parsed2.owner, parsed2.repo, parsed2.ref);
|
|
2107
|
-
const filePath = parsed2.path !== void 0 ?
|
|
1947
|
+
const filePath = parsed2.path !== void 0 ? join3(cloneResult.localPath, parsed2.path) : cloneResult.localPath;
|
|
2108
1948
|
if (!existsSync4(filePath)) {
|
|
2109
1949
|
await cloneResult.cleanup();
|
|
2110
1950
|
throw new LAFSCommandError(
|
|
@@ -2131,7 +1971,7 @@ async function resolveCantSource(source) {
|
|
|
2131
1971
|
}
|
|
2132
1972
|
const body = await resp.text();
|
|
2133
1973
|
const baseName = inferNameFromUrl(source);
|
|
2134
|
-
const tmp =
|
|
1974
|
+
const tmp = join3(tmpdir(), `caamp-pi-cant-${process.pid}-${Date.now()}-${baseName}.cant`);
|
|
2135
1975
|
await writeFile(tmp, body, "utf8");
|
|
2136
1976
|
return {
|
|
2137
1977
|
localPath: tmp,
|
|
@@ -2147,7 +1987,7 @@ async function resolveCantSource(source) {
|
|
|
2147
1987
|
const parsed = parseSource(source);
|
|
2148
1988
|
if (parsed.type === "github" && parsed.owner !== void 0 && parsed.repo !== void 0) {
|
|
2149
1989
|
const cloneResult = await cloneRepo(parsed.owner, parsed.repo, parsed.ref);
|
|
2150
|
-
const filePath = parsed.path !== void 0 ?
|
|
1990
|
+
const filePath = parsed.path !== void 0 ? join3(cloneResult.localPath, parsed.path) : cloneResult.localPath;
|
|
2151
1991
|
if (!existsSync4(filePath)) {
|
|
2152
1992
|
await cloneResult.cleanup();
|
|
2153
1993
|
throw new LAFSCommandError(
|
|
@@ -2311,11 +2151,12 @@ function registerPiCantCommands(parent) {
|
|
|
2311
2151
|
// src/commands/pi/extensions.ts
|
|
2312
2152
|
import { existsSync as existsSync5 } from "fs";
|
|
2313
2153
|
import { writeFile as writeFile2 } from "fs/promises";
|
|
2314
|
-
import { tmpdir as
|
|
2315
|
-
import { isAbsolute as isAbsolute2, join as
|
|
2154
|
+
import { tmpdir as tmpdir2 } from "os";
|
|
2155
|
+
import { isAbsolute as isAbsolute2, join as join4 } from "path";
|
|
2156
|
+
import { expandTildePath as expandTildePath2 } from "@cleocode/paths";
|
|
2316
2157
|
async function resolveExtensionSource(source) {
|
|
2317
2158
|
if (isAbsolute2(source) || source.startsWith("./") || source.startsWith("../") || source.startsWith("~")) {
|
|
2318
|
-
const expanded =
|
|
2159
|
+
const expanded = expandTildePath2(source);
|
|
2319
2160
|
if (!existsSync5(expanded)) {
|
|
2320
2161
|
throw new LAFSCommandError(
|
|
2321
2162
|
PI_ERROR_CODES.NOT_FOUND,
|
|
@@ -2336,7 +2177,7 @@ async function resolveExtensionSource(source) {
|
|
|
2336
2177
|
const parsed2 = parseSource(source);
|
|
2337
2178
|
if (parsed2.type === "github" && parsed2.owner !== void 0 && parsed2.repo !== void 0) {
|
|
2338
2179
|
const cloneResult = await cloneRepo(parsed2.owner, parsed2.repo, parsed2.ref);
|
|
2339
|
-
const filePath = parsed2.path !== void 0 ?
|
|
2180
|
+
const filePath = parsed2.path !== void 0 ? join4(cloneResult.localPath, parsed2.path) : cloneResult.localPath;
|
|
2340
2181
|
if (!existsSync5(filePath)) {
|
|
2341
2182
|
await cloneResult.cleanup();
|
|
2342
2183
|
throw new LAFSCommandError(
|
|
@@ -2354,7 +2195,7 @@ async function resolveExtensionSource(source) {
|
|
|
2354
2195
|
}
|
|
2355
2196
|
if (parsed2.type === "gitlab" && parsed2.owner !== void 0 && parsed2.repo !== void 0) {
|
|
2356
2197
|
const cloneResult = await cloneGitLabRepo(parsed2.owner, parsed2.repo, parsed2.ref);
|
|
2357
|
-
const filePath = parsed2.path !== void 0 ?
|
|
2198
|
+
const filePath = parsed2.path !== void 0 ? join4(cloneResult.localPath, parsed2.path) : cloneResult.localPath;
|
|
2358
2199
|
if (!existsSync5(filePath)) {
|
|
2359
2200
|
await cloneResult.cleanup();
|
|
2360
2201
|
throw new LAFSCommandError(
|
|
@@ -2381,7 +2222,7 @@ async function resolveExtensionSource(source) {
|
|
|
2381
2222
|
}
|
|
2382
2223
|
const body = await resp.text();
|
|
2383
2224
|
const baseName = inferNameFromUrl2(source);
|
|
2384
|
-
const tmp =
|
|
2225
|
+
const tmp = join4(tmpdir2(), `caamp-pi-ext-${process.pid}-${Date.now()}-${baseName}.ts`);
|
|
2385
2226
|
await writeFile2(tmp, body, "utf8");
|
|
2386
2227
|
return {
|
|
2387
2228
|
localPath: tmp,
|
|
@@ -2397,7 +2238,7 @@ async function resolveExtensionSource(source) {
|
|
|
2397
2238
|
const parsed = parseSource(source);
|
|
2398
2239
|
if (parsed.type === "github" && parsed.owner !== void 0 && parsed.repo !== void 0) {
|
|
2399
2240
|
const cloneResult = await cloneRepo(parsed.owner, parsed.repo, parsed.ref);
|
|
2400
|
-
const filePath = parsed.path !== void 0 ?
|
|
2241
|
+
const filePath = parsed.path !== void 0 ? join4(cloneResult.localPath, parsed.path) : cloneResult.localPath;
|
|
2401
2242
|
if (!existsSync5(filePath)) {
|
|
2402
2243
|
await cloneResult.cleanup();
|
|
2403
2244
|
throw new LAFSCommandError(
|
|
@@ -2666,7 +2507,7 @@ function registerPiModelsCommands(parent) {
|
|
|
2666
2507
|
|
|
2667
2508
|
// src/commands/pi/prompts.ts
|
|
2668
2509
|
import { existsSync as existsSync6 } from "fs";
|
|
2669
|
-
import { join as
|
|
2510
|
+
import { join as join5, resolve } from "path";
|
|
2670
2511
|
function inferPromptName(sourceDir) {
|
|
2671
2512
|
const normalized = resolve(sourceDir).replace(/[\\/]+$/, "");
|
|
2672
2513
|
const base = normalized.split(/[\\/]/).pop();
|
|
@@ -2696,7 +2537,7 @@ function registerPiPromptsCommands(parent) {
|
|
|
2696
2537
|
false
|
|
2697
2538
|
);
|
|
2698
2539
|
}
|
|
2699
|
-
if (!existsSync6(
|
|
2540
|
+
if (!existsSync6(join5(absSource, "prompt.md"))) {
|
|
2700
2541
|
throw new LAFSCommandError(
|
|
2701
2542
|
PI_ERROR_CODES.VALIDATION,
|
|
2702
2543
|
`Source directory is missing prompt.md: ${absSource}`,
|
|
@@ -3013,8 +2854,8 @@ function registerPiCommands(program2) {
|
|
|
3013
2854
|
}
|
|
3014
2855
|
|
|
3015
2856
|
// src/commands/providers.ts
|
|
3016
|
-
import { randomUUID as
|
|
3017
|
-
import { resolveOutputFormat
|
|
2857
|
+
import { randomUUID as randomUUID2 } from "crypto";
|
|
2858
|
+
import { resolveOutputFormat } from "@cleocode/lafs";
|
|
3018
2859
|
import pc6 from "picocolors";
|
|
3019
2860
|
function registerProvidersCommand(program2) {
|
|
3020
2861
|
const providers = program2.command("providers").description("Manage AI agent providers");
|
|
@@ -3023,7 +2864,7 @@ function registerProvidersCommand(program2) {
|
|
|
3023
2864
|
const mvi = "standard";
|
|
3024
2865
|
let format;
|
|
3025
2866
|
try {
|
|
3026
|
-
format =
|
|
2867
|
+
format = resolveOutputFormat({
|
|
3027
2868
|
jsonFlag: opts.json ?? false,
|
|
3028
2869
|
humanFlag: (opts.human ?? false) || isHuman(),
|
|
3029
2870
|
projectDefault: "json"
|
|
@@ -3073,7 +2914,7 @@ CAMP Provider Registry v${getRegistryVersion()}`));
|
|
|
3073
2914
|
const mvi = "standard";
|
|
3074
2915
|
let format;
|
|
3075
2916
|
try {
|
|
3076
|
-
format =
|
|
2917
|
+
format = resolveOutputFormat({
|
|
3077
2918
|
jsonFlag: opts.json ?? false,
|
|
3078
2919
|
humanFlag: (opts.human ?? false) || isHuman(),
|
|
3079
2920
|
projectDefault: "json"
|
|
@@ -3129,7 +2970,7 @@ Detected ${installed.length} installed providers:
|
|
|
3129
2970
|
const mvi = "standard";
|
|
3130
2971
|
let format;
|
|
3131
2972
|
try {
|
|
3132
|
-
format =
|
|
2973
|
+
format = resolveOutputFormat({
|
|
3133
2974
|
jsonFlag: opts.json ?? false,
|
|
3134
2975
|
humanFlag: (opts.human ?? false) || isHuman(),
|
|
3135
2976
|
projectDefault: "json"
|
|
@@ -3202,7 +3043,7 @@ ${provider.toolName}`));
|
|
|
3202
3043
|
const mvi = "standard";
|
|
3203
3044
|
let format;
|
|
3204
3045
|
try {
|
|
3205
|
-
format =
|
|
3046
|
+
format = resolveOutputFormat({
|
|
3206
3047
|
jsonFlag: opts.json ?? false,
|
|
3207
3048
|
humanFlag: (opts.human ?? false) || isHuman(),
|
|
3208
3049
|
projectDefault: "json"
|
|
@@ -3260,7 +3101,7 @@ ${provider.toolName}`));
|
|
|
3260
3101
|
const mvi = "standard";
|
|
3261
3102
|
let format;
|
|
3262
3103
|
try {
|
|
3263
|
-
format =
|
|
3104
|
+
format = resolveOutputFormat({
|
|
3264
3105
|
jsonFlag: opts.json ?? false,
|
|
3265
3106
|
humanFlag: (opts.human ?? false) || isHuman(),
|
|
3266
3107
|
projectDefault: "json"
|
|
@@ -3328,7 +3169,7 @@ CAMP Hook Support (mappings v${getHookMappingsVersion()})
|
|
|
3328
3169
|
const mvi = "standard";
|
|
3329
3170
|
let format;
|
|
3330
3171
|
try {
|
|
3331
|
-
format =
|
|
3172
|
+
format = resolveOutputFormat({
|
|
3332
3173
|
jsonFlag: opts.json ?? false,
|
|
3333
3174
|
humanFlag: (opts.human ?? false) || isHuman(),
|
|
3334
3175
|
projectDefault: "json"
|
|
@@ -3375,7 +3216,7 @@ CAMP Hook Support (mappings v${getHookMappingsVersion()})
|
|
|
3375
3216
|
const mvi = "standard";
|
|
3376
3217
|
let format;
|
|
3377
3218
|
try {
|
|
3378
|
-
format =
|
|
3219
|
+
format = resolveOutputFormat({
|
|
3379
3220
|
jsonFlag: opts.json ?? false,
|
|
3380
3221
|
humanFlag: (opts.human ?? false) || isHuman(),
|
|
3381
3222
|
projectDefault: "json"
|
|
@@ -3506,7 +3347,7 @@ CAMP Hook Support (mappings v${getHookMappingsVersion()})
|
|
|
3506
3347
|
const mvi = "standard";
|
|
3507
3348
|
let format;
|
|
3508
3349
|
try {
|
|
3509
|
-
format =
|
|
3350
|
+
format = resolveOutputFormat({
|
|
3510
3351
|
jsonFlag: opts.json ?? false,
|
|
3511
3352
|
humanFlag: (opts.human ?? false) || isHuman(),
|
|
3512
3353
|
projectDefault: "json"
|
|
@@ -3576,7 +3417,7 @@ function buildEnvelope2(operation, mvi, result, error) {
|
|
|
3576
3417
|
schemaVersion: "1.0.0",
|
|
3577
3418
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3578
3419
|
operation,
|
|
3579
|
-
requestId:
|
|
3420
|
+
requestId: randomUUID2(),
|
|
3580
3421
|
transport: "cli",
|
|
3581
3422
|
strict: true,
|
|
3582
3423
|
mvi,
|
|
@@ -3892,8 +3733,8 @@ function registerSkillsCheck(parent) {
|
|
|
3892
3733
|
}
|
|
3893
3734
|
|
|
3894
3735
|
// src/commands/skills/find.ts
|
|
3895
|
-
import { randomUUID as
|
|
3896
|
-
import { resolveOutputFormat as
|
|
3736
|
+
import { randomUUID as randomUUID3 } from "crypto";
|
|
3737
|
+
import { resolveOutputFormat as resolveOutputFormat2 } from "@cleocode/lafs";
|
|
3897
3738
|
import pc9 from "picocolors";
|
|
3898
3739
|
var SkillsFindValidationError = class extends Error {
|
|
3899
3740
|
code;
|
|
@@ -3925,7 +3766,7 @@ function registerSkillsFind(parent) {
|
|
|
3925
3766
|
const mvi = details ? "full" : "standard";
|
|
3926
3767
|
let format;
|
|
3927
3768
|
try {
|
|
3928
|
-
format =
|
|
3769
|
+
format = resolveOutputFormat2({
|
|
3929
3770
|
jsonFlag: opts.json ?? false,
|
|
3930
3771
|
humanFlag: (opts.human ?? false) || isHuman(),
|
|
3931
3772
|
projectDefault: "json"
|
|
@@ -4154,7 +3995,7 @@ function buildEnvelope3(operation, mvi, result, error) {
|
|
|
4154
3995
|
schemaVersion: "1.0.0",
|
|
4155
3996
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4156
3997
|
operation,
|
|
4157
|
-
requestId:
|
|
3998
|
+
requestId: randomUUID3(),
|
|
4158
3999
|
transport: "cli",
|
|
4159
4000
|
strict: true,
|
|
4160
4001
|
mvi,
|
|
@@ -4181,7 +4022,7 @@ function emitJsonError3(operation, mvi, code, message, category, details = {}) {
|
|
|
4181
4022
|
// src/commands/skills/init.ts
|
|
4182
4023
|
import { existsSync as existsSync10 } from "fs";
|
|
4183
4024
|
import { mkdir, writeFile as writeFile3 } from "fs/promises";
|
|
4184
|
-
import { join as
|
|
4025
|
+
import { join as join6 } from "path";
|
|
4185
4026
|
import pc10 from "picocolors";
|
|
4186
4027
|
function registerSkillsInit(parent) {
|
|
4187
4028
|
parent.command("init").description("Create a new SKILL.md template").argument("[name]", "Skill name").option("-d, --dir <path>", "Output directory", ".").option("--json", "Output as JSON (default)").option("--human", "Output in human-readable format").action(
|
|
@@ -4207,7 +4048,7 @@ function registerSkillsInit(parent) {
|
|
|
4207
4048
|
process.exit(1);
|
|
4208
4049
|
}
|
|
4209
4050
|
const skillName = name ?? "my-skill";
|
|
4210
|
-
const skillDir =
|
|
4051
|
+
const skillDir = join6(opts.dir, skillName);
|
|
4211
4052
|
if (existsSync10(skillDir)) {
|
|
4212
4053
|
const message = `Directory already exists: ${skillDir}`;
|
|
4213
4054
|
if (format === "json") {
|
|
@@ -4250,7 +4091,7 @@ Provide detailed instructions for the AI agent here.
|
|
|
4250
4091
|
|
|
4251
4092
|
Show example inputs and expected outputs.
|
|
4252
4093
|
`;
|
|
4253
|
-
await writeFile3(
|
|
4094
|
+
await writeFile3(join6(skillDir, "SKILL.md"), template, "utf-8");
|
|
4254
4095
|
const result = {
|
|
4255
4096
|
name: skillName,
|
|
4256
4097
|
directory: skillDir,
|
|
@@ -4264,95 +4105,88 @@ Show example inputs and expected outputs.
|
|
|
4264
4105
|
console.log(pc10.green(`\u2713 Created skill template: ${skillDir}/SKILL.md`));
|
|
4265
4106
|
console.log(pc10.dim("\nNext steps:"));
|
|
4266
4107
|
console.log(pc10.dim(" 1. Edit SKILL.md with your instructions"));
|
|
4267
|
-
console.log(pc10.dim(` 2. Validate: caamp skills validate ${
|
|
4108
|
+
console.log(pc10.dim(` 2. Validate: caamp skills validate ${join6(skillDir, "SKILL.md")}`));
|
|
4268
4109
|
console.log(pc10.dim(` 3. Install: caamp skills install ${skillDir}`));
|
|
4269
4110
|
}
|
|
4270
4111
|
);
|
|
4271
4112
|
}
|
|
4272
4113
|
|
|
4273
4114
|
// src/commands/skills/install.ts
|
|
4274
|
-
import { existsSync as existsSync11 } from "fs";
|
|
4275
|
-
import { createRequire } from "module";
|
|
4276
|
-
import { pushWarning } from "@cleocode/lafs";
|
|
4277
4115
|
import pc11 from "picocolors";
|
|
4278
|
-
|
|
4279
|
-
|
|
4280
|
-
|
|
4281
|
-
|
|
4282
|
-
|
|
4283
|
-
|
|
4284
|
-
|
|
4285
|
-
|
|
4286
|
-
|
|
4287
|
-
|
|
4288
|
-
|
|
4289
|
-
|
|
4290
|
-
|
|
4291
|
-
pushWarning({
|
|
4292
|
-
code: "W_CORE_UNAVAILABLE",
|
|
4293
|
-
severity: "warn",
|
|
4294
|
-
message: "caamp running without @cleocode/core \u2014 trust gate skipped (skill installs not security-checked)",
|
|
4295
|
-
context: {
|
|
4296
|
-
error: err instanceof Error ? err.message : String(err)
|
|
4297
|
-
}
|
|
4298
|
-
});
|
|
4116
|
+
function renderProgress(event) {
|
|
4117
|
+
switch (event.kind) {
|
|
4118
|
+
case "marketplace-search":
|
|
4119
|
+
console.log(pc11.dim(`Searching marketplace for ${event.source}...`));
|
|
4120
|
+
return;
|
|
4121
|
+
case "marketplace-found":
|
|
4122
|
+
console.log(` Found: ${pc11.bold(event.name)} by ${event.author} (${pc11.dim(event.repo)})`);
|
|
4123
|
+
return;
|
|
4124
|
+
case "catalog-found":
|
|
4125
|
+
console.log(
|
|
4126
|
+
` Found in catalog: ${pc11.bold(event.name)} v${event.version} (${pc11.dim(event.category)})`
|
|
4127
|
+
);
|
|
4128
|
+
return;
|
|
4299
4129
|
}
|
|
4300
|
-
return cachedCore;
|
|
4301
4130
|
}
|
|
4302
|
-
|
|
4303
|
-
|
|
4304
|
-
|
|
4305
|
-
|
|
4306
|
-
|
|
4307
|
-
|
|
4308
|
-
|
|
4309
|
-
|
|
4310
|
-
|
|
4311
|
-
|
|
4312
|
-
verdict: "safe",
|
|
4313
|
-
findings: [],
|
|
4314
|
-
scannedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4315
|
-
summary: "core-unavailable"
|
|
4316
|
-
}
|
|
4317
|
-
};
|
|
4131
|
+
function categoryFor(err) {
|
|
4132
|
+
switch (err.code) {
|
|
4133
|
+
case ErrorCodes.NETWORK_ERROR:
|
|
4134
|
+
return ErrorCategories.TRANSIENT;
|
|
4135
|
+
case ErrorCodes.SKILL_NOT_FOUND:
|
|
4136
|
+
return ErrorCategories.NOT_FOUND;
|
|
4137
|
+
case ErrorCodes.SKILL_GATE_UNAVAILABLE:
|
|
4138
|
+
return ErrorCategories.INTERNAL;
|
|
4139
|
+
default:
|
|
4140
|
+
return ErrorCategories.VALIDATION;
|
|
4318
4141
|
}
|
|
4319
|
-
const scan = core.scanSkill(localPath, source);
|
|
4320
|
-
const gate = core.shouldAllowInstall(scan, force);
|
|
4321
|
-
return { decision: gate.decision, reason: gate.reason, scan };
|
|
4322
4142
|
}
|
|
4323
|
-
|
|
4324
|
-
const
|
|
4325
|
-
if (
|
|
4326
|
-
|
|
4327
|
-
|
|
4328
|
-
|
|
4329
|
-
|
|
4330
|
-
|
|
4331
|
-
|
|
4332
|
-
|
|
4333
|
-
|
|
4143
|
+
function reportRefusal(err, format, operation, mvi) {
|
|
4144
|
+
const scan = err.details.scan;
|
|
4145
|
+
if (format === "json") {
|
|
4146
|
+
if (scan && err.code === ErrorCodes.SKILL_TRUST_GATE_BLOCKED) {
|
|
4147
|
+
const envelope = buildEnvelope(
|
|
4148
|
+
operation,
|
|
4149
|
+
mvi,
|
|
4150
|
+
{ scan },
|
|
4151
|
+
{
|
|
4152
|
+
code: err.code,
|
|
4153
|
+
message: err.message,
|
|
4154
|
+
category: categoryFor(err),
|
|
4155
|
+
retryable: false,
|
|
4156
|
+
retryAfterMs: null,
|
|
4157
|
+
details: {
|
|
4158
|
+
verdict: scan.verdict,
|
|
4159
|
+
trustLevel: scan.trustLevel,
|
|
4160
|
+
findingsCount: scan.findings.length
|
|
4161
|
+
}
|
|
4162
|
+
}
|
|
4163
|
+
);
|
|
4164
|
+
console.error(JSON.stringify(envelope, null, 2));
|
|
4165
|
+
} else {
|
|
4166
|
+
const details = {};
|
|
4167
|
+
if (err.details.availableSkills) details.availableSkills = err.details.availableSkills;
|
|
4168
|
+
if (err.details.federation) {
|
|
4169
|
+
details.expectedChecksum = err.details.federation.expectedChecksum;
|
|
4170
|
+
details.computedChecksum = err.details.federation.computedChecksum;
|
|
4171
|
+
details.peer = err.details.federation.peer?.url ?? null;
|
|
4172
|
+
}
|
|
4173
|
+
if (err.details.cause) details.cause = err.details.cause;
|
|
4174
|
+
emitJsonError(operation, mvi, err.code, err.message, categoryFor(err), details);
|
|
4175
|
+
}
|
|
4334
4176
|
}
|
|
4335
|
-
|
|
4336
|
-
|
|
4337
|
-
|
|
4338
|
-
|
|
4339
|
-
|
|
4340
|
-
|
|
4341
|
-
}
|
|
4342
|
-
|
|
4343
|
-
const core = await resolveCore();
|
|
4344
|
-
if (!core) return;
|
|
4345
|
-
try {
|
|
4346
|
-
core.recordTrustBypass(scan, reason);
|
|
4347
|
-
} catch (err) {
|
|
4348
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
4349
|
-
pushWarning({
|
|
4350
|
-
code: "W_AUDIT_LOG_FAILED",
|
|
4351
|
-
severity: "warn",
|
|
4352
|
-
message: "trust-bypass audit record failed",
|
|
4353
|
-
context: { error: msg }
|
|
4354
|
-
});
|
|
4177
|
+
console.error(pc11.red(err.message));
|
|
4178
|
+
if (scan && err.code === ErrorCodes.SKILL_TRUST_GATE_BLOCKED && format === "human") {
|
|
4179
|
+
for (const f of scan.findings.slice(0, 5)) {
|
|
4180
|
+
console.error(
|
|
4181
|
+
pc11.dim(` [${f.severity}] ${f.category} ${f.file}:${f.line} \u2014 ${f.description}`)
|
|
4182
|
+
);
|
|
4183
|
+
}
|
|
4184
|
+
console.error(pc11.yellow(" Use --force to override (audited)."));
|
|
4355
4185
|
}
|
|
4186
|
+
if (err.details.availableSkills && format === "human") {
|
|
4187
|
+
console.log(pc11.dim(`Available skills: ${err.details.availableSkills.join(", ")}`));
|
|
4188
|
+
}
|
|
4189
|
+
process.exit(1);
|
|
4356
4190
|
}
|
|
4357
4191
|
function registerSkillsInstall(parent) {
|
|
4358
4192
|
parent.command("install").description("Install a skill from GitHub, URL, marketplace, or registered skill library").argument("[source]", "Skill source (GitHub URL, owner/repo, @author/name, skill-name)").option(
|
|
@@ -4402,7 +4236,7 @@ function registerSkillsInstall(parent) {
|
|
|
4402
4236
|
if (providers.length === 0) {
|
|
4403
4237
|
const message = "No target providers found. Use --agent or --all.";
|
|
4404
4238
|
if (format === "json") {
|
|
4405
|
-
|
|
4239
|
+
emitError(
|
|
4406
4240
|
operation,
|
|
4407
4241
|
mvi,
|
|
4408
4242
|
ErrorCodes.PROVIDER_NOT_FOUND,
|
|
@@ -4427,7 +4261,7 @@ function registerSkillsInstall(parent) {
|
|
|
4427
4261
|
if (!source) {
|
|
4428
4262
|
const message = "Missing required argument: source";
|
|
4429
4263
|
if (format === "json") {
|
|
4430
|
-
|
|
4264
|
+
emitError(
|
|
4431
4265
|
operation,
|
|
4432
4266
|
mvi,
|
|
4433
4267
|
ErrorCodes.INVALID_INPUT,
|
|
@@ -4444,335 +4278,74 @@ function registerSkillsInstall(parent) {
|
|
|
4444
4278
|
if (format === "human") {
|
|
4445
4279
|
console.log(pc11.dim(`Installing to ${providers.length} provider(s)...`));
|
|
4446
4280
|
}
|
|
4447
|
-
let
|
|
4448
|
-
|
|
4449
|
-
|
|
4450
|
-
let sourceValue;
|
|
4451
|
-
let sourceType;
|
|
4452
|
-
if (isMarketplaceScoped(source)) {
|
|
4453
|
-
const sourceResult = await handleMarketplaceSource(
|
|
4454
|
-
source,
|
|
4281
|
+
let result;
|
|
4282
|
+
try {
|
|
4283
|
+
result = await installSkillFromSource(source, {
|
|
4455
4284
|
providers,
|
|
4456
|
-
opts.global ?? false,
|
|
4457
|
-
|
|
4458
|
-
|
|
4459
|
-
|
|
4460
|
-
|
|
4461
|
-
|
|
4462
|
-
|
|
4463
|
-
|
|
4464
|
-
|
|
4465
|
-
sourceValue = sourceResult.sourceValue;
|
|
4466
|
-
sourceType = sourceResult.sourceType;
|
|
4467
|
-
} else {
|
|
4468
|
-
process.exit(1);
|
|
4469
|
-
}
|
|
4470
|
-
} else {
|
|
4471
|
-
const parsed = parseSource(source);
|
|
4472
|
-
skillName = parsed.inferredName;
|
|
4473
|
-
sourceValue = parsed.value;
|
|
4474
|
-
sourceType = parsed.type;
|
|
4475
|
-
if (parsed.type === "github" && parsed.owner && parsed.repo) {
|
|
4476
|
-
try {
|
|
4477
|
-
const result = await cloneRepo(parsed.owner, parsed.repo, parsed.ref, parsed.path);
|
|
4478
|
-
localPath = result.localPath;
|
|
4479
|
-
cleanup = result.cleanup;
|
|
4480
|
-
} catch (error) {
|
|
4481
|
-
const message = `Failed to clone GitHub repository: ${formatNetworkError(error)}`;
|
|
4482
|
-
if (format === "json") {
|
|
4483
|
-
emitJsonError(
|
|
4484
|
-
operation,
|
|
4485
|
-
mvi,
|
|
4486
|
-
ErrorCodes.NETWORK_ERROR,
|
|
4487
|
-
message,
|
|
4488
|
-
ErrorCategories.TRANSIENT
|
|
4489
|
-
);
|
|
4490
|
-
}
|
|
4491
|
-
console.error(pc11.red(message));
|
|
4492
|
-
process.exit(1);
|
|
4493
|
-
}
|
|
4494
|
-
} else if (parsed.type === "gitlab" && parsed.owner && parsed.repo) {
|
|
4495
|
-
try {
|
|
4496
|
-
const result = await cloneGitLabRepo(
|
|
4497
|
-
parsed.owner,
|
|
4498
|
-
parsed.repo,
|
|
4499
|
-
parsed.ref,
|
|
4500
|
-
parsed.path
|
|
4501
|
-
);
|
|
4502
|
-
localPath = result.localPath;
|
|
4503
|
-
cleanup = result.cleanup;
|
|
4504
|
-
} catch (error) {
|
|
4505
|
-
const message = `Failed to clone GitLab repository: ${formatNetworkError(error)}`;
|
|
4506
|
-
if (format === "json") {
|
|
4507
|
-
emitJsonError(
|
|
4508
|
-
operation,
|
|
4509
|
-
mvi,
|
|
4510
|
-
ErrorCodes.NETWORK_ERROR,
|
|
4511
|
-
message,
|
|
4512
|
-
ErrorCategories.TRANSIENT
|
|
4513
|
-
);
|
|
4514
|
-
}
|
|
4515
|
-
console.error(pc11.red(message));
|
|
4516
|
-
process.exit(1);
|
|
4517
|
-
}
|
|
4518
|
-
} else if (parsed.type === "local") {
|
|
4519
|
-
localPath = parsed.value;
|
|
4520
|
-
const discovered = await discoverSkill(localPath);
|
|
4521
|
-
if (discovered) {
|
|
4522
|
-
skillName = discovered.name;
|
|
4523
|
-
}
|
|
4524
|
-
} else if (parsed.type === "package") {
|
|
4525
|
-
if (!isCatalogAvailable()) {
|
|
4526
|
-
const message = "No skill library registered. Register one with registerSkillLibraryFromPath() or set CAAMP_SKILL_LIBRARY env var.";
|
|
4527
|
-
if (format === "json") {
|
|
4528
|
-
emitJsonError(
|
|
4529
|
-
operation,
|
|
4530
|
-
mvi,
|
|
4531
|
-
ErrorCodes.INVALID_INPUT,
|
|
4532
|
-
message,
|
|
4533
|
-
ErrorCategories.VALIDATION
|
|
4534
|
-
);
|
|
4535
|
-
}
|
|
4536
|
-
console.error(pc11.red(message));
|
|
4537
|
-
process.exit(1);
|
|
4538
|
-
}
|
|
4539
|
-
const catalogSkill = getSkill(parsed.inferredName);
|
|
4540
|
-
if (catalogSkill) {
|
|
4541
|
-
localPath = getSkillDir(catalogSkill.name);
|
|
4542
|
-
skillName = catalogSkill.name;
|
|
4543
|
-
sourceValue = `library:${catalogSkill.name}`;
|
|
4544
|
-
sourceType = "library";
|
|
4545
|
-
if (format === "human") {
|
|
4546
|
-
console.log(
|
|
4547
|
-
` Found in catalog: ${pc11.bold(catalogSkill.name)} v${catalogSkill.version} (${pc11.dim(catalogSkill.category)})`
|
|
4548
|
-
);
|
|
4549
|
-
}
|
|
4550
|
-
} else {
|
|
4551
|
-
const message = `Skill not found in catalog: ${parsed.inferredName}`;
|
|
4552
|
-
if (format === "json") {
|
|
4553
|
-
emitJsonError(
|
|
4554
|
-
operation,
|
|
4555
|
-
mvi,
|
|
4556
|
-
ErrorCodes.SKILL_NOT_FOUND,
|
|
4557
|
-
message,
|
|
4558
|
-
ErrorCategories.NOT_FOUND,
|
|
4559
|
-
{
|
|
4560
|
-
availableSkills: listSkills()
|
|
4561
|
-
}
|
|
4562
|
-
);
|
|
4563
|
-
}
|
|
4564
|
-
console.error(pc11.red(message));
|
|
4565
|
-
console.log(pc11.dim("Available skills: " + listSkills().join(", ")));
|
|
4566
|
-
process.exit(1);
|
|
4567
|
-
}
|
|
4568
|
-
} else {
|
|
4569
|
-
const message = `Unsupported source type: ${parsed.type}`;
|
|
4570
|
-
if (format === "json") {
|
|
4571
|
-
emitJsonError(
|
|
4572
|
-
operation,
|
|
4573
|
-
mvi,
|
|
4574
|
-
ErrorCodes.INVALID_FORMAT,
|
|
4575
|
-
message,
|
|
4576
|
-
ErrorCategories.VALIDATION
|
|
4577
|
-
);
|
|
4578
|
-
}
|
|
4579
|
-
console.error(pc11.red(message));
|
|
4580
|
-
process.exit(1);
|
|
4285
|
+
isGlobal: opts.global ?? false,
|
|
4286
|
+
force: opts.force ?? false,
|
|
4287
|
+
allowNewSource: opts.allowNewSource === true,
|
|
4288
|
+
recordLock: true,
|
|
4289
|
+
onProgress: format === "human" ? renderProgress : void 0
|
|
4290
|
+
});
|
|
4291
|
+
} catch (error) {
|
|
4292
|
+
if (error instanceof SkillInstallError) {
|
|
4293
|
+
reportRefusal(error, format, operation, mvi);
|
|
4581
4294
|
}
|
|
4295
|
+
throw error;
|
|
4582
4296
|
}
|
|
4583
|
-
|
|
4584
|
-
|
|
4585
|
-
|
|
4586
|
-
|
|
4587
|
-
|
|
4588
|
-
|
|
4589
|
-
|
|
4590
|
-
|
|
4591
|
-
|
|
4592
|
-
|
|
4593
|
-
|
|
4594
|
-
|
|
4595
|
-
|
|
4596
|
-
|
|
4597
|
-
}
|
|
4598
|
-
if (sourceType !== "library" && sourceType !== "package") {
|
|
4599
|
-
const fedGate = await evaluateFederationGate(sourceValue, {
|
|
4600
|
-
artefactPath: localPath,
|
|
4601
|
-
approveNewSource: opts.allowNewSource === true
|
|
4602
|
-
});
|
|
4603
|
-
if (fedGate.decision === "block-checksum") {
|
|
4604
|
-
const message = `Federation install blocked: ${fedGate.reason}`;
|
|
4605
|
-
if (format === "json") {
|
|
4606
|
-
emitJsonError(
|
|
4607
|
-
operation,
|
|
4608
|
-
mvi,
|
|
4609
|
-
ErrorCodes.FEDERATION_CHECKSUM_MISMATCH,
|
|
4610
|
-
message,
|
|
4611
|
-
ErrorCategories.VALIDATION,
|
|
4612
|
-
{
|
|
4613
|
-
expectedChecksum: fedGate.expectedChecksum,
|
|
4614
|
-
computedChecksum: fedGate.computedChecksum
|
|
4615
|
-
}
|
|
4616
|
-
);
|
|
4617
|
-
}
|
|
4618
|
-
console.error(pc11.red(message));
|
|
4619
|
-
process.exit(1);
|
|
4620
|
-
}
|
|
4621
|
-
if (fedGate.decision === "prompt-first-install") {
|
|
4622
|
-
const message = `${fedGate.reason} Use --allow-new-source to approve in non-interactive contexts.`;
|
|
4623
|
-
if (format === "json") {
|
|
4624
|
-
emitJsonError(
|
|
4625
|
-
operation,
|
|
4626
|
-
mvi,
|
|
4627
|
-
ErrorCodes.FEDERATION_UNKNOWN_SOURCE_INTERACTIVE_REQUIRED,
|
|
4628
|
-
message,
|
|
4629
|
-
ErrorCategories.VALIDATION,
|
|
4630
|
-
{ peer: fedGate.peer?.url ?? null }
|
|
4631
|
-
);
|
|
4632
|
-
}
|
|
4633
|
-
console.error(pc11.yellow(message));
|
|
4634
|
-
process.exit(1);
|
|
4635
|
-
}
|
|
4636
|
-
}
|
|
4637
|
-
if (sourceType !== "library" && sourceType !== "package") {
|
|
4638
|
-
const gate = await evaluateSkillTrustGate(localPath, sourceValue, opts.force ?? false);
|
|
4639
|
-
if (gate.decision === "block") {
|
|
4640
|
-
const message = `Trust gate blocked install: ${gate.reason}`;
|
|
4641
|
-
if (format === "json") {
|
|
4642
|
-
const envelope = buildEnvelope(
|
|
4643
|
-
operation,
|
|
4644
|
-
mvi,
|
|
4645
|
-
{ scan: gate.scan },
|
|
4646
|
-
{
|
|
4647
|
-
code: ErrorCodes.SKILL_TRUST_GATE_BLOCKED,
|
|
4648
|
-
message,
|
|
4649
|
-
category: ErrorCategories.VALIDATION,
|
|
4650
|
-
retryable: false,
|
|
4651
|
-
retryAfterMs: null,
|
|
4652
|
-
details: {
|
|
4653
|
-
verdict: gate.scan.verdict,
|
|
4654
|
-
trustLevel: gate.scan.trustLevel,
|
|
4655
|
-
findingsCount: gate.scan.findings.length
|
|
4656
|
-
}
|
|
4657
|
-
}
|
|
4658
|
-
);
|
|
4659
|
-
console.error(JSON.stringify(envelope, null, 2));
|
|
4660
|
-
} else {
|
|
4661
|
-
console.error(pc11.red(`
|
|
4662
|
-
${message}`));
|
|
4663
|
-
for (const f of gate.scan.findings.slice(0, 5)) {
|
|
4664
|
-
console.error(
|
|
4665
|
-
pc11.dim(
|
|
4666
|
-
` [${f.severity}] ${f.category} ${f.file}:${f.line} \u2014 ${f.description}`
|
|
4667
|
-
)
|
|
4668
|
-
);
|
|
4669
|
-
}
|
|
4670
|
-
console.error(pc11.yellow(" Use --force to override (audited)."));
|
|
4671
|
-
}
|
|
4672
|
-
process.exit(1);
|
|
4673
|
-
}
|
|
4674
|
-
if (gate.decision === "ask") {
|
|
4675
|
-
const message = `Trust gate requires confirmation: ${gate.reason}`;
|
|
4676
|
-
if (format === "json") {
|
|
4677
|
-
emitJsonError(
|
|
4678
|
-
operation,
|
|
4679
|
-
mvi,
|
|
4680
|
-
ErrorCodes.SKILL_TRUST_GATE_BLOCKED,
|
|
4681
|
-
message,
|
|
4682
|
-
ErrorCategories.VALIDATION
|
|
4683
|
-
);
|
|
4684
|
-
}
|
|
4685
|
-
console.error(pc11.red(message));
|
|
4686
|
-
process.exit(1);
|
|
4687
|
-
}
|
|
4688
|
-
if (opts.force === true && gate.scan.verdict !== "safe") {
|
|
4689
|
-
await recordSkillTrustBypass(gate.scan, "operator --force on caamp skills install");
|
|
4690
|
-
}
|
|
4691
|
-
}
|
|
4692
|
-
const result = await dispatchInstallSkillAcrossProviders(
|
|
4693
|
-
localPath,
|
|
4694
|
-
skillName,
|
|
4695
|
-
providers,
|
|
4696
|
-
opts.global ?? false
|
|
4697
|
-
);
|
|
4698
|
-
if (result.success) {
|
|
4699
|
-
const isGlobal = sourceType === "library" || sourceType === "package" ? true : opts.global ?? false;
|
|
4700
|
-
await recordSkillInstall(
|
|
4701
|
-
skillName,
|
|
4702
|
-
sourceValue,
|
|
4703
|
-
sourceValue,
|
|
4704
|
-
sourceType,
|
|
4705
|
-
result.linkedAgents,
|
|
4706
|
-
result.canonicalPath,
|
|
4707
|
-
isGlobal
|
|
4708
|
-
);
|
|
4709
|
-
const installedItem = {
|
|
4710
|
-
name: skillName,
|
|
4711
|
-
scopedName: sourceValue,
|
|
4712
|
-
canonicalPath: result.canonicalPath,
|
|
4713
|
-
providers: result.linkedAgents
|
|
4714
|
-
};
|
|
4715
|
-
const summary = {
|
|
4716
|
-
installed: [installedItem],
|
|
4717
|
-
failed: [],
|
|
4718
|
-
count: {
|
|
4719
|
-
installed: 1,
|
|
4720
|
-
failed: 0,
|
|
4721
|
-
total: 1
|
|
4722
|
-
}
|
|
4723
|
-
};
|
|
4724
|
-
if (format === "json") {
|
|
4725
|
-
outputSuccess(operation, mvi, summary);
|
|
4726
|
-
} else {
|
|
4727
|
-
console.log(pc11.green(`
|
|
4728
|
-
\u2713 Installed ${pc11.bold(skillName)}`));
|
|
4729
|
-
console.log(` Canonical: ${pc11.dim(result.canonicalPath)}`);
|
|
4730
|
-
console.log(` Linked to: ${result.linkedAgents.join(", ")}`);
|
|
4731
|
-
if (result.errors.length > 0) {
|
|
4732
|
-
console.log(pc11.yellow("\nWarnings:"));
|
|
4733
|
-
for (const err of result.errors) {
|
|
4734
|
-
console.log(` ${pc11.yellow("!")} ${err}`);
|
|
4735
|
-
}
|
|
4736
|
-
}
|
|
4737
|
-
}
|
|
4297
|
+
if (result.success) {
|
|
4298
|
+
const installedItem = {
|
|
4299
|
+
name: result.name,
|
|
4300
|
+
scopedName: result.sourceValue,
|
|
4301
|
+
canonicalPath: result.canonicalPath,
|
|
4302
|
+
providers: result.linkedAgents
|
|
4303
|
+
};
|
|
4304
|
+
const summary2 = {
|
|
4305
|
+
installed: [installedItem],
|
|
4306
|
+
failed: [],
|
|
4307
|
+
count: { installed: 1, failed: 0, total: 1 }
|
|
4308
|
+
};
|
|
4309
|
+
if (format === "json") {
|
|
4310
|
+
outputSuccess(operation, mvi, summary2);
|
|
4738
4311
|
} else {
|
|
4739
|
-
|
|
4740
|
-
|
|
4741
|
-
|
|
4742
|
-
|
|
4743
|
-
|
|
4744
|
-
|
|
4745
|
-
}
|
|
4746
|
-
],
|
|
4747
|
-
count: {
|
|
4748
|
-
installed: 0,
|
|
4749
|
-
failed: 1,
|
|
4750
|
-
total: 1
|
|
4751
|
-
}
|
|
4752
|
-
};
|
|
4753
|
-
if (format === "json") {
|
|
4754
|
-
const envelope = buildEnvelope(operation, mvi, summary, {
|
|
4755
|
-
code: ErrorCodes.INSTALL_FAILED,
|
|
4756
|
-
message: result.errors.join(", "),
|
|
4757
|
-
category: ErrorCategories.INTERNAL,
|
|
4758
|
-
retryable: false,
|
|
4759
|
-
retryAfterMs: null,
|
|
4760
|
-
details: { skillName, sourceValue }
|
|
4761
|
-
});
|
|
4762
|
-
console.error(JSON.stringify(envelope, null, 2));
|
|
4763
|
-
} else {
|
|
4764
|
-
console.log(pc11.yellow(`
|
|
4765
|
-
\u2717 Failed to install ${pc11.bold(skillName)}`));
|
|
4766
|
-
console.log(pc11.yellow("Errors:"));
|
|
4312
|
+
console.log(pc11.green(`
|
|
4313
|
+
\u2713 Installed ${pc11.bold(result.name)}`));
|
|
4314
|
+
console.log(` Canonical: ${pc11.dim(result.canonicalPath)}`);
|
|
4315
|
+
console.log(` Linked to: ${result.linkedAgents.join(", ")}`);
|
|
4316
|
+
if (result.errors.length > 0) {
|
|
4317
|
+
console.log(pc11.yellow("\nWarnings:"));
|
|
4767
4318
|
for (const err of result.errors) {
|
|
4768
4319
|
console.log(` ${pc11.yellow("!")} ${err}`);
|
|
4769
4320
|
}
|
|
4770
4321
|
}
|
|
4771
|
-
process.exit(1);
|
|
4772
4322
|
}
|
|
4773
|
-
|
|
4774
|
-
if (cleanup) await cleanup();
|
|
4323
|
+
return;
|
|
4775
4324
|
}
|
|
4325
|
+
const summary = {
|
|
4326
|
+
installed: [],
|
|
4327
|
+
failed: [{ name: result.name, error: result.errors.join(", ") }],
|
|
4328
|
+
count: { installed: 0, failed: 1, total: 1 }
|
|
4329
|
+
};
|
|
4330
|
+
if (format === "json") {
|
|
4331
|
+
const envelope = buildEnvelope(operation, mvi, summary, {
|
|
4332
|
+
code: ErrorCodes.INSTALL_FAILED,
|
|
4333
|
+
message: result.errors.join(", "),
|
|
4334
|
+
category: ErrorCategories.INTERNAL,
|
|
4335
|
+
retryable: false,
|
|
4336
|
+
retryAfterMs: null,
|
|
4337
|
+
details: { skillName: result.name, sourceValue: result.sourceValue }
|
|
4338
|
+
});
|
|
4339
|
+
console.error(JSON.stringify(envelope, null, 2));
|
|
4340
|
+
} else {
|
|
4341
|
+
console.log(pc11.yellow(`
|
|
4342
|
+
\u2717 Failed to install ${pc11.bold(result.name)}`));
|
|
4343
|
+
console.log(pc11.yellow("Errors:"));
|
|
4344
|
+
for (const err of result.errors) {
|
|
4345
|
+
console.log(` ${pc11.yellow("!")} ${err}`);
|
|
4346
|
+
}
|
|
4347
|
+
}
|
|
4348
|
+
process.exit(1);
|
|
4776
4349
|
}
|
|
4777
4350
|
);
|
|
4778
4351
|
}
|
|
@@ -4780,7 +4353,7 @@ async function handleProfileInstall(profileName, providers, isGlobal, format, op
|
|
|
4780
4353
|
if (!isCatalogAvailable()) {
|
|
4781
4354
|
const message = "No skill library registered. Register one with registerSkillLibraryFromPath() or set CAAMP_SKILL_LIBRARY env var.";
|
|
4782
4355
|
if (format === "json") {
|
|
4783
|
-
|
|
4356
|
+
emitError(operation, mvi, ErrorCodes.INVALID_INPUT, message, ErrorCategories.VALIDATION);
|
|
4784
4357
|
}
|
|
4785
4358
|
console.error(pc11.red(message));
|
|
4786
4359
|
process.exit(1);
|
|
@@ -4814,22 +4387,20 @@ async function handleProfileInstall(profileName, providers, isGlobal, format, op
|
|
|
4814
4387
|
const installed = [];
|
|
4815
4388
|
const failed = [];
|
|
4816
4389
|
for (const name of profileSkills) {
|
|
4817
|
-
const skillDir = getSkillDir(name);
|
|
4818
4390
|
try {
|
|
4819
|
-
const result = await
|
|
4391
|
+
const result = await installResolvedSkill(
|
|
4392
|
+
{
|
|
4393
|
+
localPath: getSkillDir(name),
|
|
4394
|
+
skillName: name,
|
|
4395
|
+
sourceValue: `library:${name}`,
|
|
4396
|
+
sourceType: "library"
|
|
4397
|
+
},
|
|
4398
|
+
{ providers, isGlobal, recordLock: true }
|
|
4399
|
+
);
|
|
4820
4400
|
if (result.success) {
|
|
4821
4401
|
if (format === "human") {
|
|
4822
4402
|
console.log(pc11.green(` + ${name}`));
|
|
4823
4403
|
}
|
|
4824
|
-
await recordSkillInstall(
|
|
4825
|
-
name,
|
|
4826
|
-
`library:${name}`,
|
|
4827
|
-
`library:${name}`,
|
|
4828
|
-
"library",
|
|
4829
|
-
result.linkedAgents,
|
|
4830
|
-
result.canonicalPath,
|
|
4831
|
-
true
|
|
4832
|
-
);
|
|
4833
4404
|
installed.push({
|
|
4834
4405
|
name,
|
|
4835
4406
|
scopedName: `library:${name}`,
|
|
@@ -4890,89 +4461,10 @@ ${pc11.green(`${installed.length} installed`)}, ${failed.length > 0 ? pc11.yello
|
|
|
4890
4461
|
}
|
|
4891
4462
|
}
|
|
4892
4463
|
}
|
|
4893
|
-
async function handleMarketplaceSource(source, _providers, _isGlobal, format, operation, mvi) {
|
|
4894
|
-
if (format === "human") {
|
|
4895
|
-
console.log(pc11.dim(`Searching marketplace for ${source}...`));
|
|
4896
|
-
}
|
|
4897
|
-
const client = new MarketplaceClient();
|
|
4898
|
-
let skill;
|
|
4899
|
-
try {
|
|
4900
|
-
skill = await client.getSkill(source);
|
|
4901
|
-
} catch (error) {
|
|
4902
|
-
const message = `Marketplace lookup failed: ${formatNetworkError(error)}`;
|
|
4903
|
-
if (format === "json") {
|
|
4904
|
-
emitJsonError(operation, mvi, ErrorCodes.NETWORK_ERROR, message, ErrorCategories.TRANSIENT);
|
|
4905
|
-
}
|
|
4906
|
-
console.error(pc11.red(message));
|
|
4907
|
-
return { success: false };
|
|
4908
|
-
}
|
|
4909
|
-
if (!skill) {
|
|
4910
|
-
const message = `Skill not found: ${source}`;
|
|
4911
|
-
if (format === "json") {
|
|
4912
|
-
emitJsonError(operation, mvi, ErrorCodes.SKILL_NOT_FOUND, message, ErrorCategories.NOT_FOUND);
|
|
4913
|
-
}
|
|
4914
|
-
console.error(pc11.red(message));
|
|
4915
|
-
return { success: false };
|
|
4916
|
-
}
|
|
4917
|
-
if (format === "human") {
|
|
4918
|
-
console.log(
|
|
4919
|
-
` Found: ${pc11.bold(skill.name)} by ${skill.author} (${pc11.dim(skill.repoFullName)})`
|
|
4920
|
-
);
|
|
4921
|
-
}
|
|
4922
|
-
const parsed = parseSource(skill.githubUrl);
|
|
4923
|
-
if (parsed.type !== "github" || !parsed.owner || !parsed.repo) {
|
|
4924
|
-
const message = "Could not resolve GitHub source";
|
|
4925
|
-
if (format === "json") {
|
|
4926
|
-
emitJsonError(operation, mvi, ErrorCodes.INVALID_FORMAT, message, ErrorCategories.VALIDATION);
|
|
4927
|
-
}
|
|
4928
|
-
console.error(pc11.red(message));
|
|
4929
|
-
return { success: false };
|
|
4930
|
-
}
|
|
4931
|
-
try {
|
|
4932
|
-
const subPathCandidates = buildSkillSubPathCandidates(skill.path, parsed.path);
|
|
4933
|
-
let cloneError;
|
|
4934
|
-
let cloned = false;
|
|
4935
|
-
let localPath;
|
|
4936
|
-
let cleanup;
|
|
4937
|
-
for (const subPath of subPathCandidates) {
|
|
4938
|
-
try {
|
|
4939
|
-
const result = await cloneRepo(parsed.owner, parsed.repo, parsed.ref, subPath);
|
|
4940
|
-
if (subPath && !existsSync11(result.localPath)) {
|
|
4941
|
-
await result.cleanup();
|
|
4942
|
-
continue;
|
|
4943
|
-
}
|
|
4944
|
-
localPath = result.localPath;
|
|
4945
|
-
cleanup = result.cleanup;
|
|
4946
|
-
cloned = true;
|
|
4947
|
-
break;
|
|
4948
|
-
} catch (error) {
|
|
4949
|
-
cloneError = error;
|
|
4950
|
-
}
|
|
4951
|
-
}
|
|
4952
|
-
if (!cloned) {
|
|
4953
|
-
throw cloneError ?? new Error("Unable to resolve skill path from marketplace metadata");
|
|
4954
|
-
}
|
|
4955
|
-
return {
|
|
4956
|
-
success: true,
|
|
4957
|
-
localPath,
|
|
4958
|
-
cleanup,
|
|
4959
|
-
skillName: skill.name,
|
|
4960
|
-
sourceValue: skill.githubUrl,
|
|
4961
|
-
sourceType: parsed.type
|
|
4962
|
-
};
|
|
4963
|
-
} catch (error) {
|
|
4964
|
-
const message = `Failed to fetch source repository: ${formatNetworkError(error)}`;
|
|
4965
|
-
if (format === "json") {
|
|
4966
|
-
emitJsonError(operation, mvi, ErrorCodes.NETWORK_ERROR, message, ErrorCategories.TRANSIENT);
|
|
4967
|
-
}
|
|
4968
|
-
console.error(pc11.red(message));
|
|
4969
|
-
return { success: false };
|
|
4970
|
-
}
|
|
4971
|
-
}
|
|
4972
4464
|
|
|
4973
4465
|
// src/commands/skills/list.ts
|
|
4974
|
-
import { randomUUID as
|
|
4975
|
-
import { resolveOutputFormat as
|
|
4466
|
+
import { randomUUID as randomUUID4 } from "crypto";
|
|
4467
|
+
import { resolveOutputFormat as resolveOutputFormat3 } from "@cleocode/lafs";
|
|
4976
4468
|
import pc12 from "picocolors";
|
|
4977
4469
|
function registerSkillsList(parent) {
|
|
4978
4470
|
parent.command("list").description("List installed skills").option("-g, --global", "List global skills").option("-a, --agent <name>", "List skills for specific agent").option("--json", "Output as JSON (default)").option("--human", "Output in human-readable format").action(async (opts) => {
|
|
@@ -4980,7 +4472,7 @@ function registerSkillsList(parent) {
|
|
|
4980
4472
|
const mvi = "standard";
|
|
4981
4473
|
let format;
|
|
4982
4474
|
try {
|
|
4983
|
-
format =
|
|
4475
|
+
format = resolveOutputFormat3({
|
|
4984
4476
|
jsonFlag: opts.json ?? false,
|
|
4985
4477
|
humanFlag: (opts.human ?? false) || isHuman(),
|
|
4986
4478
|
projectDefault: "json"
|
|
@@ -5053,7 +4545,7 @@ function buildEnvelope4(operation, mvi, result, error) {
|
|
|
5053
4545
|
schemaVersion: "1.0.0",
|
|
5054
4546
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
5055
4547
|
operation,
|
|
5056
|
-
requestId:
|
|
4548
|
+
requestId: randomUUID4(),
|
|
5057
4549
|
transport: "cli",
|
|
5058
4550
|
strict: true,
|
|
5059
4551
|
mvi,
|
|
@@ -5310,12 +4802,14 @@ ${outdated.length} skill(s) have updates available:
|
|
|
5310
4802
|
skipped.push(skill.name);
|
|
5311
4803
|
continue;
|
|
5312
4804
|
}
|
|
5313
|
-
const installResult = await
|
|
5314
|
-
|
|
5315
|
-
|
|
5316
|
-
|
|
5317
|
-
|
|
5318
|
-
|
|
4805
|
+
const installResult = await installResolvedSkill(
|
|
4806
|
+
{
|
|
4807
|
+
localPath,
|
|
4808
|
+
skillName: skill.name,
|
|
4809
|
+
sourceValue: entry.source,
|
|
4810
|
+
sourceType: parsed.type
|
|
4811
|
+
},
|
|
4812
|
+
{ providers, isGlobal: entry.isGlobal, projectDir: entry.projectDir }
|
|
5319
4813
|
);
|
|
5320
4814
|
if (installResult.success) {
|
|
5321
4815
|
await recordSkillInstall(
|
|
@@ -5379,7 +4873,7 @@ ${outdated.length} skill(s) have updates available:
|
|
|
5379
4873
|
}
|
|
5380
4874
|
|
|
5381
4875
|
// src/commands/skills/validate.ts
|
|
5382
|
-
import { resolveOutputFormat as
|
|
4876
|
+
import { resolveOutputFormat as resolveOutputFormat4 } from "@cleocode/lafs";
|
|
5383
4877
|
import pc15 from "picocolors";
|
|
5384
4878
|
function registerSkillsValidate(parent) {
|
|
5385
4879
|
parent.command("validate").description("Validate SKILL.md format").argument("[path]", "Path to SKILL.md", "SKILL.md").option("--json", "Output as JSON (default)").option("--human", "Output in human-readable format").action(async (path, opts) => {
|
|
@@ -5387,7 +4881,7 @@ function registerSkillsValidate(parent) {
|
|
|
5387
4881
|
const mvi = "standard";
|
|
5388
4882
|
let format;
|
|
5389
4883
|
try {
|
|
5390
|
-
format =
|
|
4884
|
+
format = resolveOutputFormat4({
|
|
5391
4885
|
jsonFlag: opts.json ?? false,
|
|
5392
4886
|
humanFlag: (opts.human ?? false) || isHuman(),
|
|
5393
4887
|
projectDefault: "json"
|