@cleocode/caamp 2026.9.19 → 2026.9.20
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-JELNPPLN.js} +118 -18
- package/dist/chunk-JELNPPLN.js.map +1 -0
- package/dist/{chunk-IBHW6GEI.js → chunk-QC6CHW72.js} +3345 -2803
- package/dist/chunk-QC6CHW72.js.map +1 -0
- package/dist/cli.js +203 -711
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +581 -1
- package/dist/index.js +25 -3
- package/dist/index.js.map +1 -1
- package/dist/{injector-ZUPRC2HS.js → injector-7NNSGPGQ.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-7NNSGPGQ.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-QC6CHW72.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-JELNPPLN.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,8 @@ 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 { simpleGit } from "simple-git";
|
|
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";
|
|
2007
1846
|
|
|
2008
1847
|
// src/commands/pi/common.ts
|
|
2009
1848
|
var PI_ERROR_CODES = {
|
|
@@ -2066,7 +1905,7 @@ function resolveProjectDir2(tier, explicit) {
|
|
|
2066
1905
|
// src/commands/pi/cant.ts
|
|
2067
1906
|
async function resolveCantSource(source) {
|
|
2068
1907
|
if (isAbsolute(source) || source.startsWith("./") || source.startsWith("../") || source.startsWith("~")) {
|
|
2069
|
-
const expanded = source.startsWith("~/") ?
|
|
1908
|
+
const expanded = source.startsWith("~/") ? join3(process.env["HOME"] ?? "", source.slice(2)) : source;
|
|
2070
1909
|
if (!existsSync4(expanded)) {
|
|
2071
1910
|
throw new LAFSCommandError(
|
|
2072
1911
|
PI_ERROR_CODES.NOT_FOUND,
|
|
@@ -2086,7 +1925,7 @@ async function resolveCantSource(source) {
|
|
|
2086
1925
|
const parsed2 = parseSource(source);
|
|
2087
1926
|
if (parsed2.type === "github" && parsed2.owner !== void 0 && parsed2.repo !== void 0) {
|
|
2088
1927
|
const cloneResult = await cloneRepo(parsed2.owner, parsed2.repo, parsed2.ref);
|
|
2089
|
-
const filePath = parsed2.path !== void 0 ?
|
|
1928
|
+
const filePath = parsed2.path !== void 0 ? join3(cloneResult.localPath, parsed2.path) : cloneResult.localPath;
|
|
2090
1929
|
if (!existsSync4(filePath)) {
|
|
2091
1930
|
await cloneResult.cleanup();
|
|
2092
1931
|
throw new LAFSCommandError(
|
|
@@ -2104,7 +1943,7 @@ async function resolveCantSource(source) {
|
|
|
2104
1943
|
}
|
|
2105
1944
|
if (parsed2.type === "gitlab" && parsed2.owner !== void 0 && parsed2.repo !== void 0) {
|
|
2106
1945
|
const cloneResult = await cloneGitLabRepo(parsed2.owner, parsed2.repo, parsed2.ref);
|
|
2107
|
-
const filePath = parsed2.path !== void 0 ?
|
|
1946
|
+
const filePath = parsed2.path !== void 0 ? join3(cloneResult.localPath, parsed2.path) : cloneResult.localPath;
|
|
2108
1947
|
if (!existsSync4(filePath)) {
|
|
2109
1948
|
await cloneResult.cleanup();
|
|
2110
1949
|
throw new LAFSCommandError(
|
|
@@ -2131,7 +1970,7 @@ async function resolveCantSource(source) {
|
|
|
2131
1970
|
}
|
|
2132
1971
|
const body = await resp.text();
|
|
2133
1972
|
const baseName = inferNameFromUrl(source);
|
|
2134
|
-
const tmp =
|
|
1973
|
+
const tmp = join3(tmpdir(), `caamp-pi-cant-${process.pid}-${Date.now()}-${baseName}.cant`);
|
|
2135
1974
|
await writeFile(tmp, body, "utf8");
|
|
2136
1975
|
return {
|
|
2137
1976
|
localPath: tmp,
|
|
@@ -2147,7 +1986,7 @@ async function resolveCantSource(source) {
|
|
|
2147
1986
|
const parsed = parseSource(source);
|
|
2148
1987
|
if (parsed.type === "github" && parsed.owner !== void 0 && parsed.repo !== void 0) {
|
|
2149
1988
|
const cloneResult = await cloneRepo(parsed.owner, parsed.repo, parsed.ref);
|
|
2150
|
-
const filePath = parsed.path !== void 0 ?
|
|
1989
|
+
const filePath = parsed.path !== void 0 ? join3(cloneResult.localPath, parsed.path) : cloneResult.localPath;
|
|
2151
1990
|
if (!existsSync4(filePath)) {
|
|
2152
1991
|
await cloneResult.cleanup();
|
|
2153
1992
|
throw new LAFSCommandError(
|
|
@@ -2311,11 +2150,11 @@ function registerPiCantCommands(parent) {
|
|
|
2311
2150
|
// src/commands/pi/extensions.ts
|
|
2312
2151
|
import { existsSync as existsSync5 } from "fs";
|
|
2313
2152
|
import { writeFile as writeFile2 } from "fs/promises";
|
|
2314
|
-
import { tmpdir as
|
|
2315
|
-
import { isAbsolute as isAbsolute2, join as
|
|
2153
|
+
import { tmpdir as tmpdir2 } from "os";
|
|
2154
|
+
import { isAbsolute as isAbsolute2, join as join4 } from "path";
|
|
2316
2155
|
async function resolveExtensionSource(source) {
|
|
2317
2156
|
if (isAbsolute2(source) || source.startsWith("./") || source.startsWith("../") || source.startsWith("~")) {
|
|
2318
|
-
const expanded = source.startsWith("~/") ?
|
|
2157
|
+
const expanded = source.startsWith("~/") ? join4(process.env["HOME"] ?? "", source.slice(2)) : source;
|
|
2319
2158
|
if (!existsSync5(expanded)) {
|
|
2320
2159
|
throw new LAFSCommandError(
|
|
2321
2160
|
PI_ERROR_CODES.NOT_FOUND,
|
|
@@ -2336,7 +2175,7 @@ async function resolveExtensionSource(source) {
|
|
|
2336
2175
|
const parsed2 = parseSource(source);
|
|
2337
2176
|
if (parsed2.type === "github" && parsed2.owner !== void 0 && parsed2.repo !== void 0) {
|
|
2338
2177
|
const cloneResult = await cloneRepo(parsed2.owner, parsed2.repo, parsed2.ref);
|
|
2339
|
-
const filePath = parsed2.path !== void 0 ?
|
|
2178
|
+
const filePath = parsed2.path !== void 0 ? join4(cloneResult.localPath, parsed2.path) : cloneResult.localPath;
|
|
2340
2179
|
if (!existsSync5(filePath)) {
|
|
2341
2180
|
await cloneResult.cleanup();
|
|
2342
2181
|
throw new LAFSCommandError(
|
|
@@ -2354,7 +2193,7 @@ async function resolveExtensionSource(source) {
|
|
|
2354
2193
|
}
|
|
2355
2194
|
if (parsed2.type === "gitlab" && parsed2.owner !== void 0 && parsed2.repo !== void 0) {
|
|
2356
2195
|
const cloneResult = await cloneGitLabRepo(parsed2.owner, parsed2.repo, parsed2.ref);
|
|
2357
|
-
const filePath = parsed2.path !== void 0 ?
|
|
2196
|
+
const filePath = parsed2.path !== void 0 ? join4(cloneResult.localPath, parsed2.path) : cloneResult.localPath;
|
|
2358
2197
|
if (!existsSync5(filePath)) {
|
|
2359
2198
|
await cloneResult.cleanup();
|
|
2360
2199
|
throw new LAFSCommandError(
|
|
@@ -2381,7 +2220,7 @@ async function resolveExtensionSource(source) {
|
|
|
2381
2220
|
}
|
|
2382
2221
|
const body = await resp.text();
|
|
2383
2222
|
const baseName = inferNameFromUrl2(source);
|
|
2384
|
-
const tmp =
|
|
2223
|
+
const tmp = join4(tmpdir2(), `caamp-pi-ext-${process.pid}-${Date.now()}-${baseName}.ts`);
|
|
2385
2224
|
await writeFile2(tmp, body, "utf8");
|
|
2386
2225
|
return {
|
|
2387
2226
|
localPath: tmp,
|
|
@@ -2397,7 +2236,7 @@ async function resolveExtensionSource(source) {
|
|
|
2397
2236
|
const parsed = parseSource(source);
|
|
2398
2237
|
if (parsed.type === "github" && parsed.owner !== void 0 && parsed.repo !== void 0) {
|
|
2399
2238
|
const cloneResult = await cloneRepo(parsed.owner, parsed.repo, parsed.ref);
|
|
2400
|
-
const filePath = parsed.path !== void 0 ?
|
|
2239
|
+
const filePath = parsed.path !== void 0 ? join4(cloneResult.localPath, parsed.path) : cloneResult.localPath;
|
|
2401
2240
|
if (!existsSync5(filePath)) {
|
|
2402
2241
|
await cloneResult.cleanup();
|
|
2403
2242
|
throw new LAFSCommandError(
|
|
@@ -2666,7 +2505,7 @@ function registerPiModelsCommands(parent) {
|
|
|
2666
2505
|
|
|
2667
2506
|
// src/commands/pi/prompts.ts
|
|
2668
2507
|
import { existsSync as existsSync6 } from "fs";
|
|
2669
|
-
import { join as
|
|
2508
|
+
import { join as join5, resolve } from "path";
|
|
2670
2509
|
function inferPromptName(sourceDir) {
|
|
2671
2510
|
const normalized = resolve(sourceDir).replace(/[\\/]+$/, "");
|
|
2672
2511
|
const base = normalized.split(/[\\/]/).pop();
|
|
@@ -2696,7 +2535,7 @@ function registerPiPromptsCommands(parent) {
|
|
|
2696
2535
|
false
|
|
2697
2536
|
);
|
|
2698
2537
|
}
|
|
2699
|
-
if (!existsSync6(
|
|
2538
|
+
if (!existsSync6(join5(absSource, "prompt.md"))) {
|
|
2700
2539
|
throw new LAFSCommandError(
|
|
2701
2540
|
PI_ERROR_CODES.VALIDATION,
|
|
2702
2541
|
`Source directory is missing prompt.md: ${absSource}`,
|
|
@@ -3013,8 +2852,8 @@ function registerPiCommands(program2) {
|
|
|
3013
2852
|
}
|
|
3014
2853
|
|
|
3015
2854
|
// src/commands/providers.ts
|
|
3016
|
-
import { randomUUID as
|
|
3017
|
-
import { resolveOutputFormat
|
|
2855
|
+
import { randomUUID as randomUUID2 } from "crypto";
|
|
2856
|
+
import { resolveOutputFormat } from "@cleocode/lafs";
|
|
3018
2857
|
import pc6 from "picocolors";
|
|
3019
2858
|
function registerProvidersCommand(program2) {
|
|
3020
2859
|
const providers = program2.command("providers").description("Manage AI agent providers");
|
|
@@ -3023,7 +2862,7 @@ function registerProvidersCommand(program2) {
|
|
|
3023
2862
|
const mvi = "standard";
|
|
3024
2863
|
let format;
|
|
3025
2864
|
try {
|
|
3026
|
-
format =
|
|
2865
|
+
format = resolveOutputFormat({
|
|
3027
2866
|
jsonFlag: opts.json ?? false,
|
|
3028
2867
|
humanFlag: (opts.human ?? false) || isHuman(),
|
|
3029
2868
|
projectDefault: "json"
|
|
@@ -3073,7 +2912,7 @@ CAMP Provider Registry v${getRegistryVersion()}`));
|
|
|
3073
2912
|
const mvi = "standard";
|
|
3074
2913
|
let format;
|
|
3075
2914
|
try {
|
|
3076
|
-
format =
|
|
2915
|
+
format = resolveOutputFormat({
|
|
3077
2916
|
jsonFlag: opts.json ?? false,
|
|
3078
2917
|
humanFlag: (opts.human ?? false) || isHuman(),
|
|
3079
2918
|
projectDefault: "json"
|
|
@@ -3129,7 +2968,7 @@ Detected ${installed.length} installed providers:
|
|
|
3129
2968
|
const mvi = "standard";
|
|
3130
2969
|
let format;
|
|
3131
2970
|
try {
|
|
3132
|
-
format =
|
|
2971
|
+
format = resolveOutputFormat({
|
|
3133
2972
|
jsonFlag: opts.json ?? false,
|
|
3134
2973
|
humanFlag: (opts.human ?? false) || isHuman(),
|
|
3135
2974
|
projectDefault: "json"
|
|
@@ -3202,7 +3041,7 @@ ${provider.toolName}`));
|
|
|
3202
3041
|
const mvi = "standard";
|
|
3203
3042
|
let format;
|
|
3204
3043
|
try {
|
|
3205
|
-
format =
|
|
3044
|
+
format = resolveOutputFormat({
|
|
3206
3045
|
jsonFlag: opts.json ?? false,
|
|
3207
3046
|
humanFlag: (opts.human ?? false) || isHuman(),
|
|
3208
3047
|
projectDefault: "json"
|
|
@@ -3260,7 +3099,7 @@ ${provider.toolName}`));
|
|
|
3260
3099
|
const mvi = "standard";
|
|
3261
3100
|
let format;
|
|
3262
3101
|
try {
|
|
3263
|
-
format =
|
|
3102
|
+
format = resolveOutputFormat({
|
|
3264
3103
|
jsonFlag: opts.json ?? false,
|
|
3265
3104
|
humanFlag: (opts.human ?? false) || isHuman(),
|
|
3266
3105
|
projectDefault: "json"
|
|
@@ -3328,7 +3167,7 @@ CAMP Hook Support (mappings v${getHookMappingsVersion()})
|
|
|
3328
3167
|
const mvi = "standard";
|
|
3329
3168
|
let format;
|
|
3330
3169
|
try {
|
|
3331
|
-
format =
|
|
3170
|
+
format = resolveOutputFormat({
|
|
3332
3171
|
jsonFlag: opts.json ?? false,
|
|
3333
3172
|
humanFlag: (opts.human ?? false) || isHuman(),
|
|
3334
3173
|
projectDefault: "json"
|
|
@@ -3375,7 +3214,7 @@ CAMP Hook Support (mappings v${getHookMappingsVersion()})
|
|
|
3375
3214
|
const mvi = "standard";
|
|
3376
3215
|
let format;
|
|
3377
3216
|
try {
|
|
3378
|
-
format =
|
|
3217
|
+
format = resolveOutputFormat({
|
|
3379
3218
|
jsonFlag: opts.json ?? false,
|
|
3380
3219
|
humanFlag: (opts.human ?? false) || isHuman(),
|
|
3381
3220
|
projectDefault: "json"
|
|
@@ -3506,7 +3345,7 @@ CAMP Hook Support (mappings v${getHookMappingsVersion()})
|
|
|
3506
3345
|
const mvi = "standard";
|
|
3507
3346
|
let format;
|
|
3508
3347
|
try {
|
|
3509
|
-
format =
|
|
3348
|
+
format = resolveOutputFormat({
|
|
3510
3349
|
jsonFlag: opts.json ?? false,
|
|
3511
3350
|
humanFlag: (opts.human ?? false) || isHuman(),
|
|
3512
3351
|
projectDefault: "json"
|
|
@@ -3576,7 +3415,7 @@ function buildEnvelope2(operation, mvi, result, error) {
|
|
|
3576
3415
|
schemaVersion: "1.0.0",
|
|
3577
3416
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3578
3417
|
operation,
|
|
3579
|
-
requestId:
|
|
3418
|
+
requestId: randomUUID2(),
|
|
3580
3419
|
transport: "cli",
|
|
3581
3420
|
strict: true,
|
|
3582
3421
|
mvi,
|
|
@@ -3892,8 +3731,8 @@ function registerSkillsCheck(parent) {
|
|
|
3892
3731
|
}
|
|
3893
3732
|
|
|
3894
3733
|
// src/commands/skills/find.ts
|
|
3895
|
-
import { randomUUID as
|
|
3896
|
-
import { resolveOutputFormat as
|
|
3734
|
+
import { randomUUID as randomUUID3 } from "crypto";
|
|
3735
|
+
import { resolveOutputFormat as resolveOutputFormat2 } from "@cleocode/lafs";
|
|
3897
3736
|
import pc9 from "picocolors";
|
|
3898
3737
|
var SkillsFindValidationError = class extends Error {
|
|
3899
3738
|
code;
|
|
@@ -3925,7 +3764,7 @@ function registerSkillsFind(parent) {
|
|
|
3925
3764
|
const mvi = details ? "full" : "standard";
|
|
3926
3765
|
let format;
|
|
3927
3766
|
try {
|
|
3928
|
-
format =
|
|
3767
|
+
format = resolveOutputFormat2({
|
|
3929
3768
|
jsonFlag: opts.json ?? false,
|
|
3930
3769
|
humanFlag: (opts.human ?? false) || isHuman(),
|
|
3931
3770
|
projectDefault: "json"
|
|
@@ -4154,7 +3993,7 @@ function buildEnvelope3(operation, mvi, result, error) {
|
|
|
4154
3993
|
schemaVersion: "1.0.0",
|
|
4155
3994
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4156
3995
|
operation,
|
|
4157
|
-
requestId:
|
|
3996
|
+
requestId: randomUUID3(),
|
|
4158
3997
|
transport: "cli",
|
|
4159
3998
|
strict: true,
|
|
4160
3999
|
mvi,
|
|
@@ -4181,7 +4020,7 @@ function emitJsonError3(operation, mvi, code, message, category, details = {}) {
|
|
|
4181
4020
|
// src/commands/skills/init.ts
|
|
4182
4021
|
import { existsSync as existsSync10 } from "fs";
|
|
4183
4022
|
import { mkdir, writeFile as writeFile3 } from "fs/promises";
|
|
4184
|
-
import { join as
|
|
4023
|
+
import { join as join6 } from "path";
|
|
4185
4024
|
import pc10 from "picocolors";
|
|
4186
4025
|
function registerSkillsInit(parent) {
|
|
4187
4026
|
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 +4046,7 @@ function registerSkillsInit(parent) {
|
|
|
4207
4046
|
process.exit(1);
|
|
4208
4047
|
}
|
|
4209
4048
|
const skillName = name ?? "my-skill";
|
|
4210
|
-
const skillDir =
|
|
4049
|
+
const skillDir = join6(opts.dir, skillName);
|
|
4211
4050
|
if (existsSync10(skillDir)) {
|
|
4212
4051
|
const message = `Directory already exists: ${skillDir}`;
|
|
4213
4052
|
if (format === "json") {
|
|
@@ -4250,7 +4089,7 @@ Provide detailed instructions for the AI agent here.
|
|
|
4250
4089
|
|
|
4251
4090
|
Show example inputs and expected outputs.
|
|
4252
4091
|
`;
|
|
4253
|
-
await writeFile3(
|
|
4092
|
+
await writeFile3(join6(skillDir, "SKILL.md"), template, "utf-8");
|
|
4254
4093
|
const result = {
|
|
4255
4094
|
name: skillName,
|
|
4256
4095
|
directory: skillDir,
|
|
@@ -4264,95 +4103,88 @@ Show example inputs and expected outputs.
|
|
|
4264
4103
|
console.log(pc10.green(`\u2713 Created skill template: ${skillDir}/SKILL.md`));
|
|
4265
4104
|
console.log(pc10.dim("\nNext steps:"));
|
|
4266
4105
|
console.log(pc10.dim(" 1. Edit SKILL.md with your instructions"));
|
|
4267
|
-
console.log(pc10.dim(` 2. Validate: caamp skills validate ${
|
|
4106
|
+
console.log(pc10.dim(` 2. Validate: caamp skills validate ${join6(skillDir, "SKILL.md")}`));
|
|
4268
4107
|
console.log(pc10.dim(` 3. Install: caamp skills install ${skillDir}`));
|
|
4269
4108
|
}
|
|
4270
4109
|
);
|
|
4271
4110
|
}
|
|
4272
4111
|
|
|
4273
4112
|
// src/commands/skills/install.ts
|
|
4274
|
-
import { existsSync as existsSync11 } from "fs";
|
|
4275
|
-
import { createRequire } from "module";
|
|
4276
|
-
import { pushWarning } from "@cleocode/lafs";
|
|
4277
4113
|
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
|
-
});
|
|
4114
|
+
function renderProgress(event) {
|
|
4115
|
+
switch (event.kind) {
|
|
4116
|
+
case "marketplace-search":
|
|
4117
|
+
console.log(pc11.dim(`Searching marketplace for ${event.source}...`));
|
|
4118
|
+
return;
|
|
4119
|
+
case "marketplace-found":
|
|
4120
|
+
console.log(` Found: ${pc11.bold(event.name)} by ${event.author} (${pc11.dim(event.repo)})`);
|
|
4121
|
+
return;
|
|
4122
|
+
case "catalog-found":
|
|
4123
|
+
console.log(
|
|
4124
|
+
` Found in catalog: ${pc11.bold(event.name)} v${event.version} (${pc11.dim(event.category)})`
|
|
4125
|
+
);
|
|
4126
|
+
return;
|
|
4299
4127
|
}
|
|
4300
|
-
return cachedCore;
|
|
4301
4128
|
}
|
|
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
|
-
};
|
|
4129
|
+
function categoryFor(err) {
|
|
4130
|
+
switch (err.code) {
|
|
4131
|
+
case ErrorCodes.NETWORK_ERROR:
|
|
4132
|
+
return ErrorCategories.TRANSIENT;
|
|
4133
|
+
case ErrorCodes.SKILL_NOT_FOUND:
|
|
4134
|
+
return ErrorCategories.NOT_FOUND;
|
|
4135
|
+
case ErrorCodes.SKILL_GATE_UNAVAILABLE:
|
|
4136
|
+
return ErrorCategories.INTERNAL;
|
|
4137
|
+
default:
|
|
4138
|
+
return ErrorCategories.VALIDATION;
|
|
4318
4139
|
}
|
|
4319
|
-
const scan = core.scanSkill(localPath, source);
|
|
4320
|
-
const gate = core.shouldAllowInstall(scan, force);
|
|
4321
|
-
return { decision: gate.decision, reason: gate.reason, scan };
|
|
4322
4140
|
}
|
|
4323
|
-
|
|
4324
|
-
const
|
|
4325
|
-
if (
|
|
4326
|
-
|
|
4327
|
-
|
|
4328
|
-
|
|
4329
|
-
|
|
4330
|
-
|
|
4331
|
-
|
|
4332
|
-
|
|
4333
|
-
|
|
4141
|
+
function reportRefusal(err, format, operation, mvi) {
|
|
4142
|
+
const scan = err.details.scan;
|
|
4143
|
+
if (format === "json") {
|
|
4144
|
+
if (scan && err.code === ErrorCodes.SKILL_TRUST_GATE_BLOCKED) {
|
|
4145
|
+
const envelope = buildEnvelope(
|
|
4146
|
+
operation,
|
|
4147
|
+
mvi,
|
|
4148
|
+
{ scan },
|
|
4149
|
+
{
|
|
4150
|
+
code: err.code,
|
|
4151
|
+
message: err.message,
|
|
4152
|
+
category: categoryFor(err),
|
|
4153
|
+
retryable: false,
|
|
4154
|
+
retryAfterMs: null,
|
|
4155
|
+
details: {
|
|
4156
|
+
verdict: scan.verdict,
|
|
4157
|
+
trustLevel: scan.trustLevel,
|
|
4158
|
+
findingsCount: scan.findings.length
|
|
4159
|
+
}
|
|
4160
|
+
}
|
|
4161
|
+
);
|
|
4162
|
+
console.error(JSON.stringify(envelope, null, 2));
|
|
4163
|
+
} else {
|
|
4164
|
+
const details = {};
|
|
4165
|
+
if (err.details.availableSkills) details.availableSkills = err.details.availableSkills;
|
|
4166
|
+
if (err.details.federation) {
|
|
4167
|
+
details.expectedChecksum = err.details.federation.expectedChecksum;
|
|
4168
|
+
details.computedChecksum = err.details.federation.computedChecksum;
|
|
4169
|
+
details.peer = err.details.federation.peer?.url ?? null;
|
|
4170
|
+
}
|
|
4171
|
+
if (err.details.cause) details.cause = err.details.cause;
|
|
4172
|
+
emitJsonError(operation, mvi, err.code, err.message, categoryFor(err), details);
|
|
4173
|
+
}
|
|
4334
4174
|
}
|
|
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
|
-
});
|
|
4175
|
+
console.error(pc11.red(err.message));
|
|
4176
|
+
if (scan && err.code === ErrorCodes.SKILL_TRUST_GATE_BLOCKED && format === "human") {
|
|
4177
|
+
for (const f of scan.findings.slice(0, 5)) {
|
|
4178
|
+
console.error(
|
|
4179
|
+
pc11.dim(` [${f.severity}] ${f.category} ${f.file}:${f.line} \u2014 ${f.description}`)
|
|
4180
|
+
);
|
|
4181
|
+
}
|
|
4182
|
+
console.error(pc11.yellow(" Use --force to override (audited)."));
|
|
4355
4183
|
}
|
|
4184
|
+
if (err.details.availableSkills && format === "human") {
|
|
4185
|
+
console.log(pc11.dim(`Available skills: ${err.details.availableSkills.join(", ")}`));
|
|
4186
|
+
}
|
|
4187
|
+
process.exit(1);
|
|
4356
4188
|
}
|
|
4357
4189
|
function registerSkillsInstall(parent) {
|
|
4358
4190
|
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 +4234,7 @@ function registerSkillsInstall(parent) {
|
|
|
4402
4234
|
if (providers.length === 0) {
|
|
4403
4235
|
const message = "No target providers found. Use --agent or --all.";
|
|
4404
4236
|
if (format === "json") {
|
|
4405
|
-
|
|
4237
|
+
emitError(
|
|
4406
4238
|
operation,
|
|
4407
4239
|
mvi,
|
|
4408
4240
|
ErrorCodes.PROVIDER_NOT_FOUND,
|
|
@@ -4427,7 +4259,7 @@ function registerSkillsInstall(parent) {
|
|
|
4427
4259
|
if (!source) {
|
|
4428
4260
|
const message = "Missing required argument: source";
|
|
4429
4261
|
if (format === "json") {
|
|
4430
|
-
|
|
4262
|
+
emitError(
|
|
4431
4263
|
operation,
|
|
4432
4264
|
mvi,
|
|
4433
4265
|
ErrorCodes.INVALID_INPUT,
|
|
@@ -4444,335 +4276,74 @@ function registerSkillsInstall(parent) {
|
|
|
4444
4276
|
if (format === "human") {
|
|
4445
4277
|
console.log(pc11.dim(`Installing to ${providers.length} provider(s)...`));
|
|
4446
4278
|
}
|
|
4447
|
-
let
|
|
4448
|
-
|
|
4449
|
-
|
|
4450
|
-
let sourceValue;
|
|
4451
|
-
let sourceType;
|
|
4452
|
-
if (isMarketplaceScoped(source)) {
|
|
4453
|
-
const sourceResult = await handleMarketplaceSource(
|
|
4454
|
-
source,
|
|
4279
|
+
let result;
|
|
4280
|
+
try {
|
|
4281
|
+
result = await installSkillFromSource(source, {
|
|
4455
4282
|
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);
|
|
4283
|
+
isGlobal: opts.global ?? false,
|
|
4284
|
+
force: opts.force ?? false,
|
|
4285
|
+
allowNewSource: opts.allowNewSource === true,
|
|
4286
|
+
recordLock: true,
|
|
4287
|
+
onProgress: format === "human" ? renderProgress : void 0
|
|
4288
|
+
});
|
|
4289
|
+
} catch (error) {
|
|
4290
|
+
if (error instanceof SkillInstallError) {
|
|
4291
|
+
reportRefusal(error, format, operation, mvi);
|
|
4581
4292
|
}
|
|
4293
|
+
throw error;
|
|
4582
4294
|
}
|
|
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
|
-
}
|
|
4295
|
+
if (result.success) {
|
|
4296
|
+
const installedItem = {
|
|
4297
|
+
name: result.name,
|
|
4298
|
+
scopedName: result.sourceValue,
|
|
4299
|
+
canonicalPath: result.canonicalPath,
|
|
4300
|
+
providers: result.linkedAgents
|
|
4301
|
+
};
|
|
4302
|
+
const summary2 = {
|
|
4303
|
+
installed: [installedItem],
|
|
4304
|
+
failed: [],
|
|
4305
|
+
count: { installed: 1, failed: 0, total: 1 }
|
|
4306
|
+
};
|
|
4307
|
+
if (format === "json") {
|
|
4308
|
+
outputSuccess(operation, mvi, summary2);
|
|
4738
4309
|
} 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:"));
|
|
4310
|
+
console.log(pc11.green(`
|
|
4311
|
+
\u2713 Installed ${pc11.bold(result.name)}`));
|
|
4312
|
+
console.log(` Canonical: ${pc11.dim(result.canonicalPath)}`);
|
|
4313
|
+
console.log(` Linked to: ${result.linkedAgents.join(", ")}`);
|
|
4314
|
+
if (result.errors.length > 0) {
|
|
4315
|
+
console.log(pc11.yellow("\nWarnings:"));
|
|
4767
4316
|
for (const err of result.errors) {
|
|
4768
4317
|
console.log(` ${pc11.yellow("!")} ${err}`);
|
|
4769
4318
|
}
|
|
4770
4319
|
}
|
|
4771
|
-
process.exit(1);
|
|
4772
4320
|
}
|
|
4773
|
-
|
|
4774
|
-
if (cleanup) await cleanup();
|
|
4321
|
+
return;
|
|
4775
4322
|
}
|
|
4323
|
+
const summary = {
|
|
4324
|
+
installed: [],
|
|
4325
|
+
failed: [{ name: result.name, error: result.errors.join(", ") }],
|
|
4326
|
+
count: { installed: 0, failed: 1, total: 1 }
|
|
4327
|
+
};
|
|
4328
|
+
if (format === "json") {
|
|
4329
|
+
const envelope = buildEnvelope(operation, mvi, summary, {
|
|
4330
|
+
code: ErrorCodes.INSTALL_FAILED,
|
|
4331
|
+
message: result.errors.join(", "),
|
|
4332
|
+
category: ErrorCategories.INTERNAL,
|
|
4333
|
+
retryable: false,
|
|
4334
|
+
retryAfterMs: null,
|
|
4335
|
+
details: { skillName: result.name, sourceValue: result.sourceValue }
|
|
4336
|
+
});
|
|
4337
|
+
console.error(JSON.stringify(envelope, null, 2));
|
|
4338
|
+
} else {
|
|
4339
|
+
console.log(pc11.yellow(`
|
|
4340
|
+
\u2717 Failed to install ${pc11.bold(result.name)}`));
|
|
4341
|
+
console.log(pc11.yellow("Errors:"));
|
|
4342
|
+
for (const err of result.errors) {
|
|
4343
|
+
console.log(` ${pc11.yellow("!")} ${err}`);
|
|
4344
|
+
}
|
|
4345
|
+
}
|
|
4346
|
+
process.exit(1);
|
|
4776
4347
|
}
|
|
4777
4348
|
);
|
|
4778
4349
|
}
|
|
@@ -4780,7 +4351,7 @@ async function handleProfileInstall(profileName, providers, isGlobal, format, op
|
|
|
4780
4351
|
if (!isCatalogAvailable()) {
|
|
4781
4352
|
const message = "No skill library registered. Register one with registerSkillLibraryFromPath() or set CAAMP_SKILL_LIBRARY env var.";
|
|
4782
4353
|
if (format === "json") {
|
|
4783
|
-
|
|
4354
|
+
emitError(operation, mvi, ErrorCodes.INVALID_INPUT, message, ErrorCategories.VALIDATION);
|
|
4784
4355
|
}
|
|
4785
4356
|
console.error(pc11.red(message));
|
|
4786
4357
|
process.exit(1);
|
|
@@ -4814,22 +4385,20 @@ async function handleProfileInstall(profileName, providers, isGlobal, format, op
|
|
|
4814
4385
|
const installed = [];
|
|
4815
4386
|
const failed = [];
|
|
4816
4387
|
for (const name of profileSkills) {
|
|
4817
|
-
const skillDir = getSkillDir(name);
|
|
4818
4388
|
try {
|
|
4819
|
-
const result = await
|
|
4389
|
+
const result = await installResolvedSkill(
|
|
4390
|
+
{
|
|
4391
|
+
localPath: getSkillDir(name),
|
|
4392
|
+
skillName: name,
|
|
4393
|
+
sourceValue: `library:${name}`,
|
|
4394
|
+
sourceType: "library"
|
|
4395
|
+
},
|
|
4396
|
+
{ providers, isGlobal, recordLock: true }
|
|
4397
|
+
);
|
|
4820
4398
|
if (result.success) {
|
|
4821
4399
|
if (format === "human") {
|
|
4822
4400
|
console.log(pc11.green(` + ${name}`));
|
|
4823
4401
|
}
|
|
4824
|
-
await recordSkillInstall(
|
|
4825
|
-
name,
|
|
4826
|
-
`library:${name}`,
|
|
4827
|
-
`library:${name}`,
|
|
4828
|
-
"library",
|
|
4829
|
-
result.linkedAgents,
|
|
4830
|
-
result.canonicalPath,
|
|
4831
|
-
true
|
|
4832
|
-
);
|
|
4833
4402
|
installed.push({
|
|
4834
4403
|
name,
|
|
4835
4404
|
scopedName: `library:${name}`,
|
|
@@ -4890,89 +4459,10 @@ ${pc11.green(`${installed.length} installed`)}, ${failed.length > 0 ? pc11.yello
|
|
|
4890
4459
|
}
|
|
4891
4460
|
}
|
|
4892
4461
|
}
|
|
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
4462
|
|
|
4973
4463
|
// src/commands/skills/list.ts
|
|
4974
|
-
import { randomUUID as
|
|
4975
|
-
import { resolveOutputFormat as
|
|
4464
|
+
import { randomUUID as randomUUID4 } from "crypto";
|
|
4465
|
+
import { resolveOutputFormat as resolveOutputFormat3 } from "@cleocode/lafs";
|
|
4976
4466
|
import pc12 from "picocolors";
|
|
4977
4467
|
function registerSkillsList(parent) {
|
|
4978
4468
|
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 +4470,7 @@ function registerSkillsList(parent) {
|
|
|
4980
4470
|
const mvi = "standard";
|
|
4981
4471
|
let format;
|
|
4982
4472
|
try {
|
|
4983
|
-
format =
|
|
4473
|
+
format = resolveOutputFormat3({
|
|
4984
4474
|
jsonFlag: opts.json ?? false,
|
|
4985
4475
|
humanFlag: (opts.human ?? false) || isHuman(),
|
|
4986
4476
|
projectDefault: "json"
|
|
@@ -5053,7 +4543,7 @@ function buildEnvelope4(operation, mvi, result, error) {
|
|
|
5053
4543
|
schemaVersion: "1.0.0",
|
|
5054
4544
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
5055
4545
|
operation,
|
|
5056
|
-
requestId:
|
|
4546
|
+
requestId: randomUUID4(),
|
|
5057
4547
|
transport: "cli",
|
|
5058
4548
|
strict: true,
|
|
5059
4549
|
mvi,
|
|
@@ -5310,12 +4800,14 @@ ${outdated.length} skill(s) have updates available:
|
|
|
5310
4800
|
skipped.push(skill.name);
|
|
5311
4801
|
continue;
|
|
5312
4802
|
}
|
|
5313
|
-
const installResult = await
|
|
5314
|
-
|
|
5315
|
-
|
|
5316
|
-
|
|
5317
|
-
|
|
5318
|
-
|
|
4803
|
+
const installResult = await installResolvedSkill(
|
|
4804
|
+
{
|
|
4805
|
+
localPath,
|
|
4806
|
+
skillName: skill.name,
|
|
4807
|
+
sourceValue: entry.source,
|
|
4808
|
+
sourceType: parsed.type
|
|
4809
|
+
},
|
|
4810
|
+
{ providers, isGlobal: entry.isGlobal, projectDir: entry.projectDir }
|
|
5319
4811
|
);
|
|
5320
4812
|
if (installResult.success) {
|
|
5321
4813
|
await recordSkillInstall(
|
|
@@ -5379,7 +4871,7 @@ ${outdated.length} skill(s) have updates available:
|
|
|
5379
4871
|
}
|
|
5380
4872
|
|
|
5381
4873
|
// src/commands/skills/validate.ts
|
|
5382
|
-
import { resolveOutputFormat as
|
|
4874
|
+
import { resolveOutputFormat as resolveOutputFormat4 } from "@cleocode/lafs";
|
|
5383
4875
|
import pc15 from "picocolors";
|
|
5384
4876
|
function registerSkillsValidate(parent) {
|
|
5385
4877
|
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 +4879,7 @@ function registerSkillsValidate(parent) {
|
|
|
5387
4879
|
const mvi = "standard";
|
|
5388
4880
|
let format;
|
|
5389
4881
|
try {
|
|
5390
|
-
format =
|
|
4882
|
+
format = resolveOutputFormat4({
|
|
5391
4883
|
jsonFlag: opts.json ?? false,
|
|
5392
4884
|
humanFlag: (opts.human ?? false) || isHuman(),
|
|
5393
4885
|
projectDefault: "json"
|