agents-inc 0.170.2 → 0.172.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +38 -0
- package/dist/{chunk-PSUTNOQ2.js → chunk-255DGUCH.js} +2 -2
- package/dist/chunk-33JICQD5.js +196 -0
- package/dist/chunk-33JICQD5.js.map +1 -0
- package/dist/{chunk-3ED3KHHD.js → chunk-3R3LHA4Q.js} +2 -2
- package/dist/{chunk-YXKTY5WM.js → chunk-5MGRHS2G.js} +94 -58
- package/dist/chunk-5MGRHS2G.js.map +1 -0
- package/dist/{chunk-PLFANHRZ.js → chunk-5PPB6HT6.js} +2 -2
- package/dist/{chunk-66AEVERM.js → chunk-6CRA46YO.js} +14 -14
- package/dist/{chunk-ELV5WDS3.js → chunk-6LUTY35Q.js} +25 -14
- package/dist/chunk-6LUTY35Q.js.map +1 -0
- package/dist/{chunk-AUNRHWH4.js → chunk-7OG635DK.js} +26 -4
- package/dist/chunk-7OG635DK.js.map +1 -0
- package/dist/{chunk-GEMW5RQ2.js → chunk-7ZOWSCAO.js} +29 -102
- package/dist/chunk-7ZOWSCAO.js.map +1 -0
- package/dist/{chunk-YGDWHDOY.js → chunk-A3ZAXL5T.js} +4 -5
- package/dist/{chunk-YGDWHDOY.js.map → chunk-A3ZAXL5T.js.map} +1 -1
- package/dist/chunk-G7NUK3BF.js +253 -0
- package/dist/chunk-G7NUK3BF.js.map +1 -0
- package/dist/{chunk-THO7LO5B.js → chunk-KCLBLK3F.js} +3 -3
- package/dist/{chunk-2YA4DDRM.js → chunk-LUKDDHSI.js} +8 -6
- package/dist/{chunk-2YA4DDRM.js.map → chunk-LUKDDHSI.js.map} +1 -1
- package/dist/{chunk-OCAVW6N5.js → chunk-MBIOZ5LW.js} +12 -3
- package/dist/{chunk-OCAVW6N5.js.map → chunk-MBIOZ5LW.js.map} +1 -1
- package/dist/{chunk-7C3PFRBU.js → chunk-MHAQWMNJ.js} +35 -5
- package/dist/{chunk-7C3PFRBU.js.map → chunk-MHAQWMNJ.js.map} +1 -1
- package/dist/{chunk-HACRR422.js → chunk-MOL2J5HS.js} +2 -2
- package/dist/{chunk-BBDGYJHX.js → chunk-N33AKFLR.js} +2 -2
- package/dist/{chunk-5BNX73OU.js → chunk-NISWBQNS.js} +52 -31
- package/dist/chunk-NISWBQNS.js.map +1 -0
- package/dist/{chunk-GAKVZNTX.js → chunk-VILFCMRN.js} +420 -316
- package/dist/chunk-VILFCMRN.js.map +1 -0
- package/dist/{chunk-IWY5IR4F.js → chunk-Y23MP2OC.js} +8 -8
- package/dist/commands/build/marketplace.js +16 -14
- package/dist/commands/build/marketplace.js.map +1 -1
- package/dist/commands/build/plugins.js +6 -6
- package/dist/commands/compile.js +12 -12
- package/dist/commands/doctor.js +64 -81
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/edit.js +150 -152
- package/dist/commands/edit.js.map +1 -1
- package/dist/commands/eject.js +10 -10
- package/dist/commands/init.js +19 -16
- package/dist/commands/list.js +14 -17
- package/dist/commands/list.js.map +1 -1
- package/dist/commands/new/marketplace.js +4 -4
- package/dist/commands/search.js +15 -13
- package/dist/commands/search.js.map +1 -1
- package/dist/commands/share.js +11 -11
- package/dist/commands/uninstall.js +109 -98
- package/dist/commands/uninstall.js.map +1 -1
- package/dist/commands/update.js +6 -6
- package/dist/components/common/scroll-affordance.js +2 -2
- package/dist/components/common/select-list.js +2 -2
- package/dist/components/common/skill-agent-summary.js +3 -4
- package/dist/components/common/summary-panel.js +11 -146
- package/dist/components/common/summary-panel.js.map +1 -1
- package/dist/hooks/init.js +22 -19
- package/dist/hooks/init.js.map +1 -1
- package/dist/load-agent-defs-54VIKN4T.js +14 -0
- package/dist/{recompile-project-agents-I33KQJFB.js → recompile-project-agents-5A44NJRD.js} +8 -8
- package/dist/{source-loader-TTJVW2ER.js → source-loader-LQNRI5UZ.js} +4 -4
- package/dist/src/agents/tester/web-tester/playbook.md +1 -1
- package/package.json +1 -1
- package/src/agents/tester/web-tester/playbook.md +1 -1
- package/dist/chunk-5BNX73OU.js.map +0 -1
- package/dist/chunk-AUNRHWH4.js.map +0 -1
- package/dist/chunk-ELV5WDS3.js.map +0 -1
- package/dist/chunk-GAKVZNTX.js.map +0 -1
- package/dist/chunk-GEMW5RQ2.js.map +0 -1
- package/dist/chunk-O4LN3HFI.js +0 -69
- package/dist/chunk-O4LN3HFI.js.map +0 -1
- package/dist/chunk-PMUZR4XO.js +0 -108
- package/dist/chunk-PMUZR4XO.js.map +0 -1
- package/dist/chunk-RIK45Q4I.js +0 -103
- package/dist/chunk-RIK45Q4I.js.map +0 -1
- package/dist/chunk-YXKTY5WM.js.map +0 -1
- package/dist/components/common/removal-plan-confirm.js +0 -10
- package/dist/load-agent-defs-6QUUMGHK.js +0 -14
- package/dist/source-loader-TTJVW2ER.js.map +0 -1
- /package/dist/{chunk-PSUTNOQ2.js.map → chunk-255DGUCH.js.map} +0 -0
- /package/dist/{chunk-3ED3KHHD.js.map → chunk-3R3LHA4Q.js.map} +0 -0
- /package/dist/{chunk-PLFANHRZ.js.map → chunk-5PPB6HT6.js.map} +0 -0
- /package/dist/{chunk-66AEVERM.js.map → chunk-6CRA46YO.js.map} +0 -0
- /package/dist/{chunk-THO7LO5B.js.map → chunk-KCLBLK3F.js.map} +0 -0
- /package/dist/{chunk-HACRR422.js.map → chunk-MOL2J5HS.js.map} +0 -0
- /package/dist/{chunk-BBDGYJHX.js.map → chunk-N33AKFLR.js.map} +0 -0
- /package/dist/{chunk-IWY5IR4F.js.map → chunk-Y23MP2OC.js.map} +0 -0
- /package/dist/{components/common/removal-plan-confirm.js.map → load-agent-defs-54VIKN4T.js.map} +0 -0
- /package/dist/{recompile-project-agents-I33KQJFB.js.map → recompile-project-agents-5A44NJRD.js.map} +0 -0
- /package/dist/{load-agent-defs-6QUUMGHK.js.map → source-loader-LQNRI5UZ.js.map} +0 -0
|
@@ -2,12 +2,18 @@
|
|
|
2
2
|
import {
|
|
3
3
|
BUILT_IN_MATRIX,
|
|
4
4
|
getSkillById,
|
|
5
|
+
getSkillDisplayName,
|
|
6
|
+
inertLine,
|
|
5
7
|
initializeMatrix,
|
|
6
8
|
matrix,
|
|
7
9
|
plural,
|
|
8
10
|
stripTerminalControls,
|
|
9
|
-
toTitleCase
|
|
10
|
-
|
|
11
|
+
toTitleCase,
|
|
12
|
+
typedEntries,
|
|
13
|
+
typedFromEntries,
|
|
14
|
+
typedKeys,
|
|
15
|
+
typedValues
|
|
16
|
+
} from "./chunk-7OG635DK.js";
|
|
11
17
|
import {
|
|
12
18
|
AGENT_NAMES,
|
|
13
19
|
AUTHOR_HANDLE_PATTERN,
|
|
@@ -76,7 +82,7 @@ import {
|
|
|
76
82
|
seedAgentScope,
|
|
77
83
|
sourceDirName,
|
|
78
84
|
validateSelection
|
|
79
|
-
} from "./chunk-
|
|
85
|
+
} from "./chunk-MHAQWMNJ.js";
|
|
80
86
|
import {
|
|
81
87
|
defaultCategories,
|
|
82
88
|
defaultRules,
|
|
@@ -86,7 +92,7 @@ import {
|
|
|
86
92
|
// src/cli/lib/loading/source-loader.ts
|
|
87
93
|
import os14 from "os";
|
|
88
94
|
import { partition as partition4, unique as unique6 } from "remeda";
|
|
89
|
-
import
|
|
95
|
+
import path29 from "path";
|
|
90
96
|
|
|
91
97
|
// src/cli/lib/installation/is-home-directory.ts
|
|
92
98
|
import fs from "fs";
|
|
@@ -485,13 +491,15 @@ function sourceRootOf(root) {
|
|
|
485
491
|
}
|
|
486
492
|
var RETIRED_SOURCE_FOLDER = ".claude-src";
|
|
487
493
|
function retiredSourceFolderIn(roots) {
|
|
488
|
-
|
|
489
|
-
return sourceDirName("claude");
|
|
494
|
+
return [...new Set(roots)].filter(holdsTheRetiredSourceFolder);
|
|
490
495
|
}
|
|
491
496
|
function holdsTheRetiredSourceFolder(root) {
|
|
492
497
|
return directoryExists(path.join(root, RETIRED_SOURCE_FOLDER));
|
|
493
498
|
}
|
|
494
499
|
var PROVIDER_OF_A_NEW_INSTALLATION = "claude";
|
|
500
|
+
function isTheProviderOfANewInstallation(provider) {
|
|
501
|
+
return provider === PROVIDER_OF_A_NEW_INSTALLATION;
|
|
502
|
+
}
|
|
495
503
|
var providerChosenForThisRun;
|
|
496
504
|
function chooseProviderForThisRun(provider) {
|
|
497
505
|
providerChosenForThisRun = provider;
|
|
@@ -862,6 +870,9 @@ function warnOnce(msg) {
|
|
|
862
870
|
sayingEachWarningOnce(() => warn(msg));
|
|
863
871
|
}
|
|
864
872
|
|
|
873
|
+
// src/cli/utils/messages.ts
|
|
874
|
+
import path3 from "path";
|
|
875
|
+
|
|
865
876
|
// src/cli/lib/validate-kebab-name.ts
|
|
866
877
|
import { unique } from "remeda";
|
|
867
878
|
var KEBAB_CASE_CHARACTER = /[a-z0-9-]/;
|
|
@@ -974,9 +985,9 @@ function completedWithFailures(failures) {
|
|
|
974
985
|
function failureLines({ what, recovery }) {
|
|
975
986
|
return [` ${what}`, ` ${recovery}`];
|
|
976
987
|
}
|
|
977
|
-
function propagatedRecompileSummary(
|
|
988
|
+
function propagatedRecompileSummary(recompiled, failed) {
|
|
978
989
|
const failureSuffix = failed > 0 ? ` (${failed} failed)` : "";
|
|
979
|
-
return `Registered projects: ${
|
|
990
|
+
return `Registered projects: ${recompiled} recompiled${failureSuffix}`;
|
|
980
991
|
}
|
|
981
992
|
function skillAssignedToNoAgent(skillId) {
|
|
982
993
|
return `Skill '${skillId}' is assigned to no sub-agent \u2014 nothing will load it.`;
|
|
@@ -1133,22 +1144,25 @@ function sharedSkillsLeftBehind(skillIds) {
|
|
|
1133
1144
|
function sharedConfigExistingInstall(configPath, id, provider) {
|
|
1134
1145
|
return `An installation already exists at ${configPath}. Run '${CLI_INVOKE_COMMAND} uninstall${providerArgument(provider)}' first \u2014 ${SHARED_CONFIG_GREENFIELD_HINT}. ${applySharedConfigHere(id, true, provider)}`;
|
|
1135
1146
|
}
|
|
1136
|
-
function sharedConfigProjectScopeAtHome(skillIds, agentNames) {
|
|
1147
|
+
function sharedConfigProjectScopeAtHome(skillIds, agentNames, installedHere, provider) {
|
|
1137
1148
|
return [
|
|
1138
1149
|
"This configuration cannot be installed here: the home directory is the global scope, and a global installation holds only global-scoped content \u2014 so these project-scoped entries have nowhere to be written:",
|
|
1139
1150
|
...skillIds.map((id) => ` skill ${id} (scope: project)`),
|
|
1140
1151
|
...agentNames.map((name) => ` sub-agent ${name} (scope: project)`),
|
|
1141
|
-
"Run this from inside a project directory, or re-share it with each entry above at global scope."
|
|
1152
|
+
installedHere ? changeTheGlobalInstallFromHome(providerArgument(provider)) : "Run this from inside a project directory, or re-share it with each entry above at global scope."
|
|
1142
1153
|
].join("\n");
|
|
1143
1154
|
}
|
|
1155
|
+
function changeTheGlobalInstallFromHome(named) {
|
|
1156
|
+
return `Run this from inside a project directory, or change the global install from here: run '${CLI_INVOKE_COMMAND} edit${named}', make the change in the editor, then apply the id it gives you with '${CLI_INVOKE_COMMAND} edit --from <id>${named}'.`;
|
|
1157
|
+
}
|
|
1144
1158
|
function unknownKeys(keys) {
|
|
1145
|
-
return keys.map(
|
|
1159
|
+
return keys.map(inertLine).join(", ");
|
|
1146
1160
|
}
|
|
1147
|
-
function skippedUnknownSkills(skillIds,
|
|
1161
|
+
function skippedUnknownSkills(skillIds, installedWithout) {
|
|
1148
1162
|
return [
|
|
1149
1163
|
`Skipped ${skillIds.length} skill(s) this catalog does not know: ${unknownKeys(skillIds)}`,
|
|
1150
|
-
...
|
|
1151
|
-
({ skillId, agentNames }) => ` sub-agent(s)
|
|
1164
|
+
...installedWithout.map(
|
|
1165
|
+
({ skillId, agentNames }) => ` sub-agent(s) installed without ${unknownKeys([skillId])}, carrying nothing else this catalog knows: ${agentNames.join(", ")}`
|
|
1152
1166
|
)
|
|
1153
1167
|
].join("\n");
|
|
1154
1168
|
}
|
|
@@ -1159,30 +1173,18 @@ function carriedSkillsWritten(skillIds) {
|
|
|
1159
1173
|
return `Wrote ${skillIds.length} skill(s) this configuration carries: ${skillIds.join(", ")}`;
|
|
1160
1174
|
}
|
|
1161
1175
|
var SHARED_CONFIG_APPLY = {
|
|
1162
|
-
PREVIEW_HEADING: "Applying this configuration will remove:",
|
|
1163
|
-
SKILLS_HEADING: "Skills:",
|
|
1164
|
-
AGENTS_HEADING: "Sub-agents:",
|
|
1165
|
-
NOTHING_REMOVED: "Nothing is removed \u2014 this configuration only adds and re-tunes.",
|
|
1166
|
-
OVERWRITTEN_HEADING: "Will be overwritten:",
|
|
1167
1176
|
CONFIRM: "Apply this configuration?"
|
|
1168
1177
|
};
|
|
1169
|
-
function
|
|
1170
|
-
return `${subject}: this project's copy is removed; the global one takes over`;
|
|
1171
|
-
}
|
|
1172
|
-
function projectCopyMovedToGlobal(subject) {
|
|
1173
|
-
return `${subject}: moves to the global install, so this project's copy is removed`;
|
|
1174
|
-
}
|
|
1175
|
-
function registeredProjectsRewritten(projectPaths) {
|
|
1178
|
+
function registeredProjectsRecompiled(projectPaths) {
|
|
1176
1179
|
return [
|
|
1177
|
-
"Each project registered with this global install is
|
|
1180
|
+
"Each project registered with this global install is recompiled to match:",
|
|
1178
1181
|
...projectPaths.map((projectPath) => ` ${projectPath}`)
|
|
1179
1182
|
].join("\n");
|
|
1180
1183
|
}
|
|
1181
|
-
function sharedConfigNeedsTerminal(id,
|
|
1182
|
-
const named = providerArgument(provider);
|
|
1184
|
+
function sharedConfigNeedsTerminal(id, editProvider, initProvider) {
|
|
1183
1185
|
return [
|
|
1184
1186
|
`Applying configuration '${id}' removes whatever it leaves out, so it has to be confirmed \u2014 and there is no terminal here to confirm it at.`,
|
|
1185
|
-
`Run '${CLI_INVOKE_COMMAND} edit --from ${id}${
|
|
1187
|
+
`Run '${CLI_INVOKE_COMMAND} edit --from ${id}${providerArgument(editProvider)}' from a terminal, or '${CLI_INVOKE_COMMAND} init --from ${id}${providerArgument(initProvider)}' in a clean directory, which installs without removing anything.`
|
|
1186
1188
|
].join("\n");
|
|
1187
1189
|
}
|
|
1188
1190
|
function nothingInstalledToApplyTo(id, provider) {
|
|
@@ -1199,21 +1201,38 @@ function addMarketplaceInTheEditor(ref, isFolder) {
|
|
|
1199
1201
|
return isFolder ? `${ref} is a folder on this machine, which the editor cannot read \u2014 push it to GitHub, then add it from the editor's Marketplace button.` : `Add ${ref} from the editor's Marketplace button.`;
|
|
1200
1202
|
}
|
|
1201
1203
|
var SHARED_CONFIG_ARRIVALS = {
|
|
1202
|
-
PROJECT_HEADING: "Into this project:",
|
|
1203
|
-
GLOBAL_HEADING: "Into the global install:",
|
|
1204
|
-
SKIPPED_HEADING: "Skipped, already in the global install:",
|
|
1205
1204
|
INSTALL_CONFIRM: "Install this configuration?"
|
|
1206
1205
|
};
|
|
1207
|
-
function keptAsInstalledGlobally(skillIds, agentNames, idAppliedAtHome) {
|
|
1206
|
+
function keptAsInstalledGlobally(skillIds, agentNames, idAppliedAtHome, provider) {
|
|
1208
1207
|
return [
|
|
1209
1208
|
"Kept as installed in the global install \u2014 this configuration states them differently or leaves them out, and a project run only adds to the global install:",
|
|
1210
1209
|
...skillIds.map((id) => ` skill ${id}`),
|
|
1211
1210
|
...agentNames.map((name) => ` sub-agent ${name}`),
|
|
1212
1211
|
...idAppliedAtHome === void 0 ? [] : [
|
|
1213
|
-
`Change them with '${CLI_INVOKE_COMMAND} edit --from ${idAppliedAtHome}' from your home directory.`
|
|
1212
|
+
`Change them with '${CLI_INVOKE_COMMAND} edit --from ${idAppliedAtHome}${providerArgument(provider)}' from your home directory.`
|
|
1214
1213
|
]
|
|
1215
1214
|
].join("\n");
|
|
1216
1215
|
}
|
|
1216
|
+
function skillsMoved(verb, skillIds) {
|
|
1217
|
+
return skillIds.length === 0 ? [] : [`${verb} ${listed(skillIds.map(getSkillDisplayName))}`];
|
|
1218
|
+
}
|
|
1219
|
+
function settingMoved({ setting, from, to }) {
|
|
1220
|
+
return `${setting} ${from ?? "default"} \u2192 ${to ?? "default"}`;
|
|
1221
|
+
}
|
|
1222
|
+
function listed(names) {
|
|
1223
|
+
if (names.length <= 1) return names.join("");
|
|
1224
|
+
return `${names.slice(0, -1).join(", ")} and ${names.at(-1)}`;
|
|
1225
|
+
}
|
|
1226
|
+
var SKILLS_REASSIGNED = "skills reassigned";
|
|
1227
|
+
function subAgentChanged({ name, scope, gains, loses, settings }) {
|
|
1228
|
+
const details = [
|
|
1229
|
+
...skillsMoved("gains", gains),
|
|
1230
|
+
...skillsMoved("loses", loses),
|
|
1231
|
+
...settings.map(settingMoved)
|
|
1232
|
+
];
|
|
1233
|
+
const where = scope === "global" ? " (global)" : "";
|
|
1234
|
+
return `~ ${name}${where}: ${details.length > 0 ? details.join(", ") : SKILLS_REASSIGNED}`;
|
|
1235
|
+
}
|
|
1217
1236
|
function addedToGlobalSubAgents(joined) {
|
|
1218
1237
|
return [
|
|
1219
1238
|
"Added to sub-agents in the global install \u2014 each keeps everything it already has, since a project run only adds to the global install:",
|
|
@@ -1260,17 +1279,18 @@ function uninstallSkillMetadataUnreadable(metadataPath) {
|
|
|
1260
1279
|
}
|
|
1261
1280
|
function recreateConfigFrom({
|
|
1262
1281
|
scopeRoot,
|
|
1263
|
-
providerToName
|
|
1282
|
+
providerToName,
|
|
1283
|
+
initProviderToName
|
|
1264
1284
|
}) {
|
|
1265
|
-
|
|
1266
|
-
return `'${CLI_INVOKE_COMMAND} uninstall${named}' from '${scopeRoot}', which still works on a config it cannot read, then '${CLI_INVOKE_COMMAND} init --from <id>${named}' with an id from ${EDITOR_URL}`;
|
|
1285
|
+
return `'${CLI_INVOKE_COMMAND} uninstall${providerArgument(providerToName)}' from '${scopeRoot}', which still works on a config it cannot read, then '${CLI_INVOKE_COMMAND} init --from <id>${providerArgument(initProviderToName)}' with an id from ${EDITOR_URL}`;
|
|
1267
1286
|
}
|
|
1268
1287
|
function providerArgument(provider) {
|
|
1269
|
-
|
|
1288
|
+
if (provider === void 0) return "";
|
|
1289
|
+
return ` --provider ${typeof provider === "string" ? provider : `<${provider.join("|")}>`}`;
|
|
1270
1290
|
}
|
|
1271
|
-
function configUnreadableError(
|
|
1291
|
+
function configUnreadableError(configLoadFailure3) {
|
|
1272
1292
|
return [
|
|
1273
|
-
|
|
1293
|
+
configLoadFailure3,
|
|
1274
1294
|
"This is the marketplace's own config rather than an installation's, so it is fixed in the marketplace repository it comes from."
|
|
1275
1295
|
].join("\n");
|
|
1276
1296
|
}
|
|
@@ -1281,17 +1301,8 @@ function unmarkedAgentsKept(agentsDir2, count) {
|
|
|
1281
1301
|
const object = count === 1 ? "it" : "them";
|
|
1282
1302
|
return `Kept ${plural(count, "agent")} in ${agentsDir2}/ \u2014 no ${DEFAULT_PLUGIN_NAME} marker, so this CLI did not compile ${object}.`;
|
|
1283
1303
|
}
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
PLUGINS_HEADING: "Plugins:",
|
|
1287
|
-
CLI_MANAGED_FILES_HEADING: "CLI-managed files:",
|
|
1288
|
-
CONFIG_HEADING: "Config:"
|
|
1289
|
-
};
|
|
1290
|
-
function localSkillsRemoval(skillsDir2) {
|
|
1291
|
-
return `${skillsDir2}/ (matching the marketplace)`;
|
|
1292
|
-
}
|
|
1293
|
-
function compiledAgentsRemoval(agentsDir2) {
|
|
1294
|
-
return `${agentsDir2}/ (CLI-compiled)`;
|
|
1304
|
+
function configFileRemoved(filePath) {
|
|
1305
|
+
return `- ${filePath}`;
|
|
1295
1306
|
}
|
|
1296
1307
|
function scopeNoun(kind) {
|
|
1297
1308
|
return kind === "project" ? "this project" : "the global installation";
|
|
@@ -1305,8 +1316,8 @@ function sentenceCase(text) {
|
|
|
1305
1316
|
function layoutIsCurrent(label, to) {
|
|
1306
1317
|
return `${label} is on ${to}/`;
|
|
1307
1318
|
}
|
|
1308
|
-
function retiredSourceFolderUnsupported(
|
|
1309
|
-
return `${RETIRED_SOURCE_FOLDER}/ is no longer supported (agents-inc now serves Claude and Codex). Move it to ${
|
|
1319
|
+
function retiredSourceFolderUnsupported(root) {
|
|
1320
|
+
return `${path3.join(root, RETIRED_SOURCE_FOLDER)}/ is no longer supported (agents-inc now serves Claude and Codex). Move it to ${path3.join(root, sourceDirName("claude"))}/.`;
|
|
1310
1321
|
}
|
|
1311
1322
|
|
|
1312
1323
|
// src/cli/types/generated/source-types.ts
|
|
@@ -1930,24 +1941,10 @@ function isSkillAssignment(value) {
|
|
|
1930
1941
|
return typeof value.id === "string";
|
|
1931
1942
|
}
|
|
1932
1943
|
|
|
1933
|
-
// src/cli/utils/typed-object.ts
|
|
1934
|
-
function typedEntries(obj) {
|
|
1935
|
-
return Object.entries(obj);
|
|
1936
|
-
}
|
|
1937
|
-
function typedKeys(obj) {
|
|
1938
|
-
return Object.keys(obj);
|
|
1939
|
-
}
|
|
1940
|
-
function typedFromEntries(entries) {
|
|
1941
|
-
return Object.fromEntries(entries);
|
|
1942
|
-
}
|
|
1943
|
-
function typedValues(obj) {
|
|
1944
|
-
return Object.values(obj).filter((value) => value !== void 0);
|
|
1945
|
-
}
|
|
1946
|
-
|
|
1947
1944
|
// src/cli/lib/configuration/config.ts
|
|
1948
1945
|
import { BlockList, isIPv4 } from "net";
|
|
1949
1946
|
import os4 from "os";
|
|
1950
|
-
import
|
|
1947
|
+
import path6 from "path";
|
|
1951
1948
|
import { z as z3 } from "zod";
|
|
1952
1949
|
|
|
1953
1950
|
// src/cli/lib/schemas.ts
|
|
@@ -1957,11 +1954,11 @@ import { partition } from "remeda";
|
|
|
1957
1954
|
// src/cli/lib/schema-validator.ts
|
|
1958
1955
|
import "zod";
|
|
1959
1956
|
function formatZodIssue(issue) {
|
|
1960
|
-
const
|
|
1957
|
+
const path30 = stripTerminalControls(issue.path.join("."));
|
|
1961
1958
|
if (issue.code === "unrecognized_keys") {
|
|
1962
1959
|
return `Unrecognized key: "${stripTerminalControls(issue.keys.join('", "'))}"`;
|
|
1963
1960
|
}
|
|
1964
|
-
return
|
|
1961
|
+
return path30 ? `${path30}: ${stripTerminalControls(issue.message)}` : stripTerminalControls(issue.message);
|
|
1965
1962
|
}
|
|
1966
1963
|
function formatZodErrors(error) {
|
|
1967
1964
|
return error.issues.map(formatZodIssue);
|
|
@@ -2103,12 +2100,12 @@ var RENAMED_SKILL_ENTRY_FIELDS = { source: "origin" };
|
|
|
2103
2100
|
function renamedFieldMessage(oldKey, newKey) {
|
|
2104
2101
|
return `"${oldKey}" was renamed to "${newKey}". Rename the key in this config \u2014 the CLI does not read "${oldKey}" any more and will not fall back to it.`;
|
|
2105
2102
|
}
|
|
2106
|
-
function reportRenamedKeys(record, renames,
|
|
2103
|
+
function reportRenamedKeys(record, renames, path30, ctx) {
|
|
2107
2104
|
for (const [oldKey, newKey] of Object.entries(renames)) {
|
|
2108
2105
|
if (!(oldKey in record)) continue;
|
|
2109
2106
|
ctx.addIssue({
|
|
2110
2107
|
code: "custom",
|
|
2111
|
-
path: [...
|
|
2108
|
+
path: [...path30, oldKey],
|
|
2112
2109
|
message: renamedFieldMessage(oldKey, newKey)
|
|
2113
2110
|
});
|
|
2114
2111
|
}
|
|
@@ -2426,9 +2423,16 @@ var stackConfigValidationSchema = z2.object({
|
|
|
2426
2423
|
function formatZodIssues(issues) {
|
|
2427
2424
|
return issues.map(formatZodIssue).join("; ");
|
|
2428
2425
|
}
|
|
2426
|
+
var carriedMetadataValidationSchema = customMetadataValidationSchema.extend({
|
|
2427
|
+
displayName: z2.string().min(1),
|
|
2428
|
+
slug: z2.string().regex(KEBAB_CASE_PATTERN).min(1)
|
|
2429
|
+
});
|
|
2429
2430
|
function validateSkillMetadata(rawMetadata) {
|
|
2430
|
-
|
|
2431
|
-
|
|
2431
|
+
return metadataSchemaFor(rawMetadata).safeParse(rawMetadata);
|
|
2432
|
+
}
|
|
2433
|
+
function metadataSchemaFor(raw) {
|
|
2434
|
+
if (!isCustomMetadata(raw)) return metadataValidationSchema;
|
|
2435
|
+
return isCarriedMetadata(raw) ? carriedMetadataValidationSchema : customMetadataValidationSchema;
|
|
2432
2436
|
}
|
|
2433
2437
|
function describeMetadataSchemaFailure(issues, rawMetadata) {
|
|
2434
2438
|
const [absent, malformed] = partition(issues, (issue) => isAbsentField(issue, rawMetadata));
|
|
@@ -2479,6 +2483,9 @@ function validateNestingDepth(value, maxDepth) {
|
|
|
2479
2483
|
function isCustomMetadata(raw) {
|
|
2480
2484
|
return isRecord(raw) && raw.custom === true;
|
|
2481
2485
|
}
|
|
2486
|
+
function isCarriedMetadata(raw) {
|
|
2487
|
+
return isRecord(raw) && isRecord(raw.forkedFrom) && typeof raw.forkedFrom.path === "string";
|
|
2488
|
+
}
|
|
2482
2489
|
function warnUnknownFields(parsed, expectedKeys, context) {
|
|
2483
2490
|
const expectedSet = new Set(expectedKeys);
|
|
2484
2491
|
const unknownKeys2 = Object.keys(parsed).filter((k) => !expectedSet.has(k));
|
|
@@ -2488,11 +2495,11 @@ function warnUnknownFields(parsed, expectedKeys, context) {
|
|
|
2488
2495
|
}
|
|
2489
2496
|
|
|
2490
2497
|
// src/cli/lib/configuration/config-loader.ts
|
|
2491
|
-
import
|
|
2498
|
+
import path4 from "path";
|
|
2492
2499
|
import { fileURLToPath } from "url";
|
|
2493
2500
|
import { createJiti } from "jiti";
|
|
2494
|
-
var CONFIG_EXPORTS_PATH =
|
|
2495
|
-
|
|
2501
|
+
var CONFIG_EXPORTS_PATH = path4.resolve(
|
|
2502
|
+
path4.dirname(fileURLToPath(import.meta.url)),
|
|
2496
2503
|
"../../config-exports.ts"
|
|
2497
2504
|
);
|
|
2498
2505
|
var ConfigSchemaError = class extends Error {
|
|
@@ -2515,13 +2522,16 @@ var ConfigDefaultExportError = class extends Error {
|
|
|
2515
2522
|
};
|
|
2516
2523
|
var ES_MODULE_MARKER = "__esModule";
|
|
2517
2524
|
function unwrapDefaultExport(namespace) {
|
|
2518
|
-
if (isRecord(namespace) &&
|
|
2525
|
+
if (isRecord(namespace) && "default" in namespace) return namespace.default;
|
|
2519
2526
|
return namespace;
|
|
2520
2527
|
}
|
|
2521
2528
|
function declaresNoDefaultExport(namespace) {
|
|
2522
2529
|
return isRecord(namespace) && ES_MODULE_MARKER in namespace && !("default" in namespace);
|
|
2523
2530
|
}
|
|
2524
2531
|
var NO_VALID_DEFAULT_EXPORT = "the file has no valid default export";
|
|
2532
|
+
function configLoadFailure(configPath, reason) {
|
|
2533
|
+
return `Failed to load config from '${configPath}': ${reason}`;
|
|
2534
|
+
}
|
|
2525
2535
|
function exportsNothing(value) {
|
|
2526
2536
|
return value == null || typeof value === "object" && Object.keys(value).length === 0;
|
|
2527
2537
|
}
|
|
@@ -2557,16 +2567,14 @@ async function importConfigModule(configPath) {
|
|
|
2557
2567
|
});
|
|
2558
2568
|
return await jiti.import(configPath);
|
|
2559
2569
|
} catch (error) {
|
|
2560
|
-
throw new Error(
|
|
2561
|
-
cause: error
|
|
2562
|
-
});
|
|
2570
|
+
throw new Error(configLoadFailure(configPath, getErrorMessage(error)), { cause: error });
|
|
2563
2571
|
}
|
|
2564
2572
|
}
|
|
2565
2573
|
|
|
2566
2574
|
// src/cli/lib/installation/install-base-dir.ts
|
|
2567
|
-
import
|
|
2575
|
+
import path5 from "path";
|
|
2568
2576
|
function getProjectConfigPath(dir, provider) {
|
|
2569
|
-
return
|
|
2577
|
+
return path5.join(sourceFolderInUse(dir, provider).dir, STANDARD_FILES.CONFIG_TS);
|
|
2570
2578
|
}
|
|
2571
2579
|
function getInstalledConfigPath(dir) {
|
|
2572
2580
|
return getProjectConfigPath(dir, providerInUse(dir));
|
|
@@ -2589,6 +2597,9 @@ function providerToNameAt(root, provider) {
|
|
|
2589
2597
|
);
|
|
2590
2598
|
return besideAnother ? provider : void 0;
|
|
2591
2599
|
}
|
|
2600
|
+
function initProviderToNameAt(root, provider) {
|
|
2601
|
+
return providerToNameAt(root, provider) ?? (isTheProviderOfANewInstallation(provider) ? void 0 : provider);
|
|
2602
|
+
}
|
|
2592
2603
|
|
|
2593
2604
|
// src/cli/lib/configuration/config.ts
|
|
2594
2605
|
var SOURCE_ENV_VAR = "CC_MARKETPLACE";
|
|
@@ -2613,8 +2624,11 @@ async function loadSourceConfig(dir, scope, provider) {
|
|
|
2613
2624
|
}
|
|
2614
2625
|
function refuseInstallationConfig(configPath, scope, scopeRoot, provider) {
|
|
2615
2626
|
const providerToName = providerToNameAt(scopeRoot, provider);
|
|
2627
|
+
const initProviderToName = initProviderToNameAt(scopeRoot, provider);
|
|
2616
2628
|
return (reason, cause) => new Error(
|
|
2617
|
-
installationConfigsUnreadable([
|
|
2629
|
+
installationConfigsUnreadable([
|
|
2630
|
+
{ configPath, reason, scope, scopeRoot, providerToName, initProviderToName }
|
|
2631
|
+
]),
|
|
2618
2632
|
{ cause }
|
|
2619
2633
|
);
|
|
2620
2634
|
}
|
|
@@ -2638,7 +2652,7 @@ function describesItsOwnFault(error) {
|
|
|
2638
2652
|
}
|
|
2639
2653
|
var unreadableSourceRepoConfig = (reason, cause) => new Error(configUnreadableError(reason), { cause });
|
|
2640
2654
|
async function readSourceRepoConfig(basePath) {
|
|
2641
|
-
const configPath =
|
|
2655
|
+
const configPath = path6.join(basePath, SOURCE_ROOT_DIR, STANDARD_FILES.CONFIG_TS);
|
|
2642
2656
|
if (!await fileExists(configPath)) {
|
|
2643
2657
|
verbose(`Source config not found at ${configPath}`);
|
|
2644
2658
|
return { kind: "absent" };
|
|
@@ -2902,6 +2916,7 @@ function validateSourceFormat(source, carrier) {
|
|
|
2902
2916
|
function validateRemoteSource(source, protocol, carrier) {
|
|
2903
2917
|
const isHttp = protocol === "https://" || protocol === "http://";
|
|
2904
2918
|
if (isHttp) refuseCredentials(source, protocol, carrier);
|
|
2919
|
+
refuseLineBreaksAndControls(source, carrier, REMOTE_EXAMPLES);
|
|
2905
2920
|
const pathAfterProtocol = source.slice(protocol.length).trim();
|
|
2906
2921
|
if (pathAfterProtocol.length < MIN_REMOTE_PATH_LENGTH) {
|
|
2907
2922
|
throw refusal(
|
|
@@ -3041,16 +3056,18 @@ function validateGitShorthand(source, repoPath, carrier) {
|
|
|
3041
3056
|
);
|
|
3042
3057
|
}
|
|
3043
3058
|
}
|
|
3059
|
+
function refuseLineBreaksAndControls(source, carrier, examples) {
|
|
3060
|
+
const inert = inertLine(source);
|
|
3061
|
+
if (inert === source) return;
|
|
3062
|
+
throw refusal(
|
|
3063
|
+
carrier,
|
|
3064
|
+
`contains invalid characters: "${inert}"`,
|
|
3065
|
+
["Marketplace values must not contain line breaks or control characters."],
|
|
3066
|
+
examples
|
|
3067
|
+
);
|
|
3068
|
+
}
|
|
3044
3069
|
function validateLocalPath(source, carrier) {
|
|
3045
|
-
|
|
3046
|
-
if (CONTROL_CHAR_PATTERN2.test(source)) {
|
|
3047
|
-
throw refusal(
|
|
3048
|
-
carrier,
|
|
3049
|
-
`contains invalid characters: "${source}"`,
|
|
3050
|
-
["Marketplace paths must not contain control characters."],
|
|
3051
|
-
LOCAL_EXAMPLES
|
|
3052
|
-
);
|
|
3053
|
-
}
|
|
3070
|
+
refuseLineBreaksAndControls(source, carrier, LOCAL_EXAMPLES);
|
|
3054
3071
|
if (UNC_PATH_PATTERN.test(source)) {
|
|
3055
3072
|
throw refusal(
|
|
3056
3073
|
carrier,
|
|
@@ -3068,7 +3085,7 @@ function isDefaultSource(source) {
|
|
|
3068
3085
|
}
|
|
3069
3086
|
var packageIdentitySchema = z3.object({ name: z3.string() });
|
|
3070
3087
|
async function isPublicCatalogueCheckout(basePath) {
|
|
3071
|
-
const raw = await readFileOptional(
|
|
3088
|
+
const raw = await readFileOptional(path6.join(basePath, STANDARD_FILES.PACKAGE_JSON));
|
|
3072
3089
|
return declaredPackageName(raw) === PUBLIC_CATALOGUE_PACKAGE;
|
|
3073
3090
|
}
|
|
3074
3091
|
function declaredPackageName(raw) {
|
|
@@ -3099,7 +3116,10 @@ function isLocalSource(source) {
|
|
|
3099
3116
|
}
|
|
3100
3117
|
|
|
3101
3118
|
// src/cli/lib/compile-seat.ts
|
|
3102
|
-
seatDiagnostics({
|
|
3119
|
+
seatDiagnostics({
|
|
3120
|
+
warn: (message) => warn(inertLine(message)),
|
|
3121
|
+
verbose: (message) => verbose(inertLine(message))
|
|
3122
|
+
});
|
|
3103
3123
|
|
|
3104
3124
|
// ../compile/src/seed-to-config.ts
|
|
3105
3125
|
import { groupBy, indexBy, isDefined, mapValues, omit as omit2, partition as partition2 } from "remeda";
|
|
@@ -3273,6 +3293,10 @@ var HAND_WRITTEN_FIELDS = [
|
|
|
3273
3293
|
"categoriesFile",
|
|
3274
3294
|
"rulesFile"
|
|
3275
3295
|
];
|
|
3296
|
+
var GLOBAL_IDENTITY_FIELDS = [
|
|
3297
|
+
...HAND_WRITTEN_FIELDS,
|
|
3298
|
+
"description"
|
|
3299
|
+
];
|
|
3276
3300
|
var EXTRACTED_FIELDS = /* @__PURE__ */ new Set([
|
|
3277
3301
|
"skills",
|
|
3278
3302
|
"agents",
|
|
@@ -3560,7 +3584,7 @@ function stackOfAgents(stack, agents) {
|
|
|
3560
3584
|
function mergeInlinedScalarFields(cleaned, cleanedGlobal) {
|
|
3561
3585
|
return Object.entries(
|
|
3562
3586
|
canonicalizeFieldOrder({
|
|
3563
|
-
...omit(cleanedGlobal,
|
|
3587
|
+
...omit(cleanedGlobal, GLOBAL_IDENTITY_FIELDS),
|
|
3564
3588
|
...cleaned
|
|
3565
3589
|
})
|
|
3566
3590
|
).filter(([key]) => isCopiedScalarField(key));
|
|
@@ -4008,9 +4032,9 @@ function seedToInstallSelection(payload, catalog) {
|
|
|
4008
4032
|
const rows = installable.flatMap((skill) => assignmentRows(skill, agentMap));
|
|
4009
4033
|
refuseUnwritableAssignments(rows);
|
|
4010
4034
|
const placed = rows.filter((row) => row.kind === "placed");
|
|
4011
|
-
const
|
|
4035
|
+
const carried = new Set(agentsCarriedIn(placed, agentMap));
|
|
4036
|
+
const selectedAgents = withAgentsSkippedSkillsName(carried, skipped, agentMap);
|
|
4012
4037
|
const skills = installable.map(toSeedSkillConfig);
|
|
4013
|
-
const selected = new Set(selectedAgents);
|
|
4014
4038
|
return {
|
|
4015
4039
|
result: {
|
|
4016
4040
|
skills,
|
|
@@ -4036,7 +4060,7 @@ function seedToInstallSelection(payload, catalog) {
|
|
|
4036
4060
|
skippedSkillIds: skipped.map(({ skillId }) => skillId),
|
|
4037
4061
|
skippedAgentNames: skippedAgentNamesOf(agentMap, rows),
|
|
4038
4062
|
agentsOnlySkippedSkillsCarried: skipped.flatMap(
|
|
4039
|
-
(skill) => agentsOnlyItCarried(skill, agentMap,
|
|
4063
|
+
(skill) => agentsOnlyItCarried(skill, agentMap, carried)
|
|
4040
4064
|
)
|
|
4041
4065
|
};
|
|
4042
4066
|
}
|
|
@@ -4046,11 +4070,14 @@ function refuseUnwritableAssignments(rows) {
|
|
|
4046
4070
|
throw new Error(unwritableAssignmentsError(unwritable));
|
|
4047
4071
|
}
|
|
4048
4072
|
}
|
|
4049
|
-
function
|
|
4073
|
+
function agentsCarriedIn(placed, agentMap) {
|
|
4074
|
+
return [...placed.map((row) => row.agent), ...agentsSwitchedOn(agentMap)];
|
|
4075
|
+
}
|
|
4076
|
+
function withAgentsSkippedSkillsName(carried, skipped, agentMap) {
|
|
4050
4077
|
return [
|
|
4051
4078
|
.../* @__PURE__ */ new Set([
|
|
4052
|
-
...
|
|
4053
|
-
...
|
|
4079
|
+
...carried,
|
|
4080
|
+
...skipped.flatMap((skill) => agentsNamedBy(skill, agentMap))
|
|
4054
4081
|
])
|
|
4055
4082
|
];
|
|
4056
4083
|
}
|
|
@@ -4058,9 +4085,14 @@ function skippedAgentNamesOf(agentMap, rows) {
|
|
|
4058
4085
|
const unknownAssignees = rows.filter((row) => row.kind === "unknownAgent").map((row) => row.agentName);
|
|
4059
4086
|
return [.../* @__PURE__ */ new Set([...agentMap.unknown, ...unknownAssignees])];
|
|
4060
4087
|
}
|
|
4061
|
-
function
|
|
4062
|
-
|
|
4063
|
-
|
|
4088
|
+
function agentsNamedBy({ seedSkill }, agentMap) {
|
|
4089
|
+
return Object.keys(seedSkill.assignments).filter(isAgentName2).filter((name) => !agentMap.switchedOff.has(name));
|
|
4090
|
+
}
|
|
4091
|
+
function agentsOnlyItCarried(skill, agentMap, carried) {
|
|
4092
|
+
const agentNames = agentsNamedBy(skill, agentMap).filter(
|
|
4093
|
+
(name) => !carried.has(name)
|
|
4094
|
+
);
|
|
4095
|
+
return agentNames.length === 0 ? [] : [{ skillId: skill.skillId, agentNames }];
|
|
4064
4096
|
}
|
|
4065
4097
|
function readAgentMap(agents) {
|
|
4066
4098
|
const known = /* @__PURE__ */ new Map();
|
|
@@ -4178,10 +4210,10 @@ import { indexBy as indexBy2, omit as omit3, pick, uniqueBy as uniqueBy2 } from
|
|
|
4178
4210
|
|
|
4179
4211
|
// src/cli/lib/configuration/project-config.ts
|
|
4180
4212
|
import os5 from "os";
|
|
4181
|
-
import
|
|
4213
|
+
import path8 from "path";
|
|
4182
4214
|
|
|
4183
4215
|
// src/cli/lib/stacks/stacks-loader.ts
|
|
4184
|
-
import
|
|
4216
|
+
import path7 from "path";
|
|
4185
4217
|
import { flatMap, groupBy as groupBy2, mapValues as mapValues2, partition as partition3, pipe, unique as unique2, uniqueBy } from "remeda";
|
|
4186
4218
|
var stacksCache = /* @__PURE__ */ new Map();
|
|
4187
4219
|
function normalizeAgentConfig(agentConfig) {
|
|
@@ -4241,7 +4273,7 @@ async function loadStacks(configDir, stacksFile) {
|
|
|
4241
4273
|
const cacheKey = `${configDir}:${resolvedStacksFile}`;
|
|
4242
4274
|
const cached = stacksCache.get(cacheKey);
|
|
4243
4275
|
if (cached) return cached;
|
|
4244
|
-
const stacksPath =
|
|
4276
|
+
const stacksPath = path7.join(configDir, resolvedStacksFile);
|
|
4245
4277
|
try {
|
|
4246
4278
|
const raw = await loadConfig(stacksPath, stacksConfigSchema);
|
|
4247
4279
|
if (raw == null) {
|
|
@@ -4287,7 +4319,7 @@ async function loadStackById(stackId, configDir, source) {
|
|
|
4287
4319
|
return defaultStack;
|
|
4288
4320
|
}
|
|
4289
4321
|
function stackNotOfferedMessage(stackId, source) {
|
|
4290
|
-
return `Stack '${stackId}' is not a stack the source '${source}' offers. A marketplace ships its own stacks; the CLI's built-in ones belong to the default public marketplace alone.`;
|
|
4322
|
+
return `Stack '${inertLine(stackId)}' is not a stack the source '${source}' offers. A marketplace ships its own stacks; the CLI's built-in ones belong to the default public marketplace alone.`;
|
|
4291
4323
|
}
|
|
4292
4324
|
function defaultUsageGuidance(category) {
|
|
4293
4325
|
return `Use when working with ${category}.`;
|
|
@@ -4327,6 +4359,7 @@ var ConfigLoadError = class extends Error {
|
|
|
4327
4359
|
this.name = "ConfigLoadError";
|
|
4328
4360
|
this.scope = isHomeDirectory(scopeRoot) ? "global" : "project";
|
|
4329
4361
|
this.providerToName = providerToNameAt(scopeRoot, provider);
|
|
4362
|
+
this.initProviderToName = initProviderToNameAt(scopeRoot, provider);
|
|
4330
4363
|
}
|
|
4331
4364
|
configPath;
|
|
4332
4365
|
reason;
|
|
@@ -4334,6 +4367,8 @@ var ConfigLoadError = class extends Error {
|
|
|
4334
4367
|
scope;
|
|
4335
4368
|
/** Named with `--provider` in a remedy handed out for this installation; beside another only. */
|
|
4336
4369
|
providerToName;
|
|
4370
|
+
/** Named in the remedy's `init --from` half, which a bare run would answer with another one. */
|
|
4371
|
+
initProviderToName;
|
|
4337
4372
|
};
|
|
4338
4373
|
async function loadProjectConfigFromDir(projectDir, provider) {
|
|
4339
4374
|
return loadProjectConfigAt(getProjectConfigPath(projectDir, provider), projectDir, provider);
|
|
@@ -4372,7 +4407,7 @@ function asProjectConfig(parsed, projectDir) {
|
|
|
4372
4407
|
const normalizedStack = parsed.stack ? normalizeStackRecord(parsed.stack) : void 0;
|
|
4373
4408
|
return {
|
|
4374
4409
|
...parsed,
|
|
4375
|
-
name: parsed.name ??
|
|
4410
|
+
name: parsed.name ?? path8.basename(projectDir),
|
|
4376
4411
|
skills: parsed.skills ?? [],
|
|
4377
4412
|
agents: parsed.agents ?? [],
|
|
4378
4413
|
...normalizedStack && { stack: normalizedStack }
|
|
@@ -4395,10 +4430,10 @@ function configDirsInPlay(projectDir) {
|
|
|
4395
4430
|
return isHomeDirectory(projectDir) ? [projectDir] : [projectDir, os5.homedir()];
|
|
4396
4431
|
}
|
|
4397
4432
|
async function findConfigLoadFailures(projectDir) {
|
|
4398
|
-
const outcomes = await Promise.all(configDirsInPlay(projectDir).map(
|
|
4433
|
+
const outcomes = await Promise.all(configDirsInPlay(projectDir).map(configLoadFailure2));
|
|
4399
4434
|
return outcomes.filter((failure) => failure !== void 0);
|
|
4400
4435
|
}
|
|
4401
|
-
async function
|
|
4436
|
+
async function configLoadFailure2(dir) {
|
|
4402
4437
|
try {
|
|
4403
4438
|
await loadInstalledConfig(dir);
|
|
4404
4439
|
return void 0;
|
|
@@ -4499,7 +4534,6 @@ function mergeConfigs(newConfig, existingConfig, options) {
|
|
|
4499
4534
|
}
|
|
4500
4535
|
return merged;
|
|
4501
4536
|
}
|
|
4502
|
-
var GLOBAL_IDENTITY_FIELDS = [...HAND_WRITTEN_FIELDS, "description"];
|
|
4503
4537
|
function existingConfigForMerge(loaded, projectDir, ownName) {
|
|
4504
4538
|
const isProjectsOwnFile = loaded.configPath === getProjectConfigPath(projectDir, loaded.provider);
|
|
4505
4539
|
if (isProjectsOwnFile) return loaded.config;
|
|
@@ -4521,13 +4555,13 @@ async function mergeWithExistingConfig(newConfig, context) {
|
|
|
4521
4555
|
}
|
|
4522
4556
|
|
|
4523
4557
|
// src/cli/lib/skills/skill-metadata.ts
|
|
4524
|
-
import
|
|
4558
|
+
import path10 from "path";
|
|
4525
4559
|
import { parse as parseYaml, stringify as stringifyYaml } from "yaml";
|
|
4526
4560
|
|
|
4527
4561
|
// src/cli/lib/versioning.ts
|
|
4528
4562
|
import { createHash } from "crypto";
|
|
4529
4563
|
import { readFile as readFileBytes } from "fs/promises";
|
|
4530
|
-
import
|
|
4564
|
+
import path9 from "path";
|
|
4531
4565
|
var ISO_DATE_LENGTH = 10;
|
|
4532
4566
|
function getCurrentDate() {
|
|
4533
4567
|
return (/* @__PURE__ */ new Date()).toISOString().slice(0, ISO_DATE_LENGTH);
|
|
@@ -4544,18 +4578,18 @@ async function computeFileHash(filePath) {
|
|
|
4544
4578
|
async function computeSkillFolderHash(skillPath) {
|
|
4545
4579
|
const contents = [];
|
|
4546
4580
|
for (const fileName of SKILL_CONTENT_FILES) {
|
|
4547
|
-
const filePath =
|
|
4581
|
+
const filePath = path9.join(skillPath, fileName);
|
|
4548
4582
|
if (await fileExists(filePath)) {
|
|
4549
4583
|
const content = await readFile(filePath);
|
|
4550
4584
|
contents.push(`${fileName}:${content}`);
|
|
4551
4585
|
}
|
|
4552
4586
|
}
|
|
4553
4587
|
for (const dirName of SKILL_CONTENT_DIRS) {
|
|
4554
|
-
const dirPath =
|
|
4588
|
+
const dirPath = path9.join(skillPath, dirName);
|
|
4555
4589
|
if (await fileExists(dirPath)) {
|
|
4556
4590
|
const files = await glob("**/*", dirPath);
|
|
4557
4591
|
for (const file of files.sort()) {
|
|
4558
|
-
const filePath =
|
|
4592
|
+
const filePath = path9.join(dirPath, file);
|
|
4559
4593
|
const content = await readFile(filePath);
|
|
4560
4594
|
contents.push(`${dirName}/${file}:${content}`);
|
|
4561
4595
|
}
|
|
@@ -4576,21 +4610,6 @@ function bumpMajorVersion(version) {
|
|
|
4576
4610
|
const major = parseMajorVersion(version);
|
|
4577
4611
|
return `${major + 1}.0.0`;
|
|
4578
4612
|
}
|
|
4579
|
-
async function readExistingPluginManifest(pluginDir, getManifestPath) {
|
|
4580
|
-
const manifestPath = getManifestPath(pluginDir);
|
|
4581
|
-
if (!await fileExists(manifestPath)) {
|
|
4582
|
-
return null;
|
|
4583
|
-
}
|
|
4584
|
-
try {
|
|
4585
|
-
const version = await readManifestVersion(manifestPath);
|
|
4586
|
-
const hashFilePath = contentHashFileBeside(manifestPath);
|
|
4587
|
-
const contentHash = await fileExists(hashFilePath) ? (await readFile(hashFilePath)).trim() : void 0;
|
|
4588
|
-
return { version, contentHash };
|
|
4589
|
-
} catch (error) {
|
|
4590
|
-
warn(`Failed to read plugin manifest at '${manifestPath}': ${getErrorMessage(error)}`);
|
|
4591
|
-
return null;
|
|
4592
|
-
}
|
|
4593
|
-
}
|
|
4594
4613
|
async function readManifestVersion(manifestPath) {
|
|
4595
4614
|
const content = await readFileSafe(manifestPath, MAX_PLUGIN_FILE_SIZE);
|
|
4596
4615
|
return pluginManifestSchema.parse(JSON.parse(content)).version ?? DEFAULT_VERSION;
|
|
@@ -4599,7 +4618,7 @@ async function computeBytesHash(filePath) {
|
|
|
4599
4618
|
return createHash("sha256").update(await readFileBytes(filePath)).digest("hex");
|
|
4600
4619
|
}
|
|
4601
4620
|
async function describeShippedFile(pluginDir, file) {
|
|
4602
|
-
return `${file}\0${await computeBytesHash(
|
|
4621
|
+
return `${file}\0${await computeBytesHash(path9.join(pluginDir, file))}\0`;
|
|
4603
4622
|
}
|
|
4604
4623
|
async function computeShippedHash(pluginDir) {
|
|
4605
4624
|
const files = await glob("**/*", pluginDir, { dot: true });
|
|
@@ -4620,25 +4639,6 @@ function versionAfterRebuild(earlier, shippedHash) {
|
|
|
4620
4639
|
if (!earlier) return DEFAULT_VERSION;
|
|
4621
4640
|
return earlier.shippedHash === shippedHash ? earlier.version : bumpMajorVersion(earlier.version);
|
|
4622
4641
|
}
|
|
4623
|
-
async function determinePluginVersion(newHash, pluginDir, getManifestPath) {
|
|
4624
|
-
const existing = await readExistingPluginManifest(pluginDir, getManifestPath);
|
|
4625
|
-
if (!existing) {
|
|
4626
|
-
return {
|
|
4627
|
-
version: DEFAULT_VERSION,
|
|
4628
|
-
contentHash: newHash
|
|
4629
|
-
};
|
|
4630
|
-
}
|
|
4631
|
-
if (existing.contentHash !== newHash) {
|
|
4632
|
-
return {
|
|
4633
|
-
version: bumpMajorVersion(existing.version),
|
|
4634
|
-
contentHash: newHash
|
|
4635
|
-
};
|
|
4636
|
-
}
|
|
4637
|
-
return {
|
|
4638
|
-
version: existing.version,
|
|
4639
|
-
contentHash: newHash
|
|
4640
|
-
};
|
|
4641
|
-
}
|
|
4642
4642
|
async function writeContentHash(pluginDir, contentHash, getManifestPath) {
|
|
4643
4643
|
await writeFile(contentHashFileBeside(getManifestPath(pluginDir)), contentHash);
|
|
4644
4644
|
}
|
|
@@ -4662,7 +4662,7 @@ async function readForkedFromMetadata(skillDir) {
|
|
|
4662
4662
|
return metadata?.forkedFrom ?? null;
|
|
4663
4663
|
}
|
|
4664
4664
|
async function readLocalSkillMetadata(skillDir) {
|
|
4665
|
-
const metadataPath =
|
|
4665
|
+
const metadataPath = path10.join(skillDir, STANDARD_FILES.METADATA_YAML);
|
|
4666
4666
|
if (!await fileExists(metadataPath)) {
|
|
4667
4667
|
return null;
|
|
4668
4668
|
}
|
|
@@ -4680,7 +4680,7 @@ async function readLocalSkillMetadata(skillDir) {
|
|
|
4680
4680
|
return result.data;
|
|
4681
4681
|
}
|
|
4682
4682
|
async function injectForkedFromMetadata(destPath, skillId, contentHash, origin = {}) {
|
|
4683
|
-
const metadataPath =
|
|
4683
|
+
const metadataPath = path10.join(destPath, STANDARD_FILES.METADATA_YAML);
|
|
4684
4684
|
const rawContent = await readFile(metadataPath);
|
|
4685
4685
|
const { yamlContent } = stripYamlSchemaComment(rawContent);
|
|
4686
4686
|
const metadata = {
|
|
@@ -4718,7 +4718,7 @@ function existingMetadataFields(yamlContent, metadataPath) {
|
|
|
4718
4718
|
}
|
|
4719
4719
|
|
|
4720
4720
|
// src/cli/lib/skills/skill-copier.ts
|
|
4721
|
-
import
|
|
4721
|
+
import path11 from "path";
|
|
4722
4722
|
var NULL_BYTE_PATTERN2 = /\0/;
|
|
4723
4723
|
function validateSkillPath(resolvedPath, expectedParent, skillPath) {
|
|
4724
4724
|
if (NULL_BYTE_PATTERN2.test(skillPath)) {
|
|
@@ -4726,26 +4726,26 @@ function validateSkillPath(resolvedPath, expectedParent, skillPath) {
|
|
|
4726
4726
|
}
|
|
4727
4727
|
if (!isPathWithin(resolvedPath, expectedParent)) {
|
|
4728
4728
|
throw new Error(
|
|
4729
|
-
`Invalid skill path: '${skillPath}' escapes expected directory '${
|
|
4729
|
+
`Invalid skill path: '${skillPath}' escapes expected directory '${path11.resolve(expectedParent)}'`
|
|
4730
4730
|
);
|
|
4731
4731
|
}
|
|
4732
4732
|
}
|
|
4733
4733
|
function resolveSkillPath(basePath, skillPath) {
|
|
4734
|
-
const resolved =
|
|
4734
|
+
const resolved = path11.join(basePath, skillPath);
|
|
4735
4735
|
validateSkillPath(resolved, basePath, skillPath);
|
|
4736
4736
|
return resolved;
|
|
4737
4737
|
}
|
|
4738
4738
|
function getSkillSourcePath(skill, rootDir) {
|
|
4739
|
-
const srcDir =
|
|
4739
|
+
const srcDir = path11.join(rootDir, SOURCE_SRC_DIR);
|
|
4740
4740
|
return resolveSkillPath(srcDir, skill.path);
|
|
4741
4741
|
}
|
|
4742
4742
|
async function generateSkillHash(skillSourcePath) {
|
|
4743
|
-
const skillMdPath =
|
|
4743
|
+
const skillMdPath = path11.join(skillSourcePath, STANDARD_FILES.SKILL_MD);
|
|
4744
4744
|
return computeFileHash(skillMdPath);
|
|
4745
4745
|
}
|
|
4746
4746
|
async function copySkillTo(skill, sourcePath, destPath, source) {
|
|
4747
4747
|
const contentHash = await generateSkillHash(sourcePath);
|
|
4748
|
-
await ensureDir(
|
|
4748
|
+
await ensureDir(path11.dirname(destPath));
|
|
4749
4749
|
await copy(sourcePath, destPath);
|
|
4750
4750
|
await injectForkedFromMetadata(destPath, skill.id, contentHash, {
|
|
4751
4751
|
...source !== void 0 && { source }
|
|
@@ -4812,7 +4812,7 @@ async function copySelectedSkill(skillId, localSkillsDir, sourceResult, selected
|
|
|
4812
4812
|
return copySkillToLocalFlattened(skill, localSkillsDir, sourceResult);
|
|
4813
4813
|
}
|
|
4814
4814
|
const destPath = getFlattenedSkillDestPath(skill, localSkillsDir);
|
|
4815
|
-
if (
|
|
4815
|
+
if (path11.resolve(localPath) === path11.resolve(destPath)) {
|
|
4816
4816
|
return resolveLocalCopiedSkill(skill, localPath);
|
|
4817
4817
|
}
|
|
4818
4818
|
return copyLocalSkillTo(skill, localPath, destPath);
|
|
@@ -4825,33 +4825,33 @@ function localPathOf(skill) {
|
|
|
4825
4825
|
}
|
|
4826
4826
|
async function copyLocalSkillTo(skill, localPath, destPath) {
|
|
4827
4827
|
const contentHash = await generateSkillHash(localPath);
|
|
4828
|
-
await ensureDir(
|
|
4828
|
+
await ensureDir(path11.dirname(destPath));
|
|
4829
4829
|
await copy(localPath, destPath);
|
|
4830
4830
|
return { skillId: skill.id, sourcePath: localPath, destPath, contentHash };
|
|
4831
4831
|
}
|
|
4832
4832
|
|
|
4833
4833
|
// src/cli/lib/skills/skill-plugin-compiler.ts
|
|
4834
|
-
import
|
|
4834
|
+
import path24 from "path";
|
|
4835
4835
|
import { parse as parseYaml4 } from "yaml";
|
|
4836
4836
|
|
|
4837
4837
|
// src/cli/lib/plugins/plugin-manifest.ts
|
|
4838
|
-
import
|
|
4838
|
+
import path13 from "path";
|
|
4839
4839
|
|
|
4840
4840
|
// src/cli/lib/plugins/plugin-finder.ts
|
|
4841
4841
|
import os6 from "os";
|
|
4842
|
-
import
|
|
4842
|
+
import path12 from "path";
|
|
4843
4843
|
function getUserPluginsDir() {
|
|
4844
|
-
return
|
|
4844
|
+
return path12.join(os6.homedir(), CLAUDE_DIR, PLUGINS_SUBDIR);
|
|
4845
4845
|
}
|
|
4846
4846
|
function getProjectPluginsDir(projectDir) {
|
|
4847
4847
|
const dir = projectDir ?? process.cwd();
|
|
4848
|
-
return
|
|
4848
|
+
return path12.join(dir, CLAUDE_DIR, PLUGINS_SUBDIR);
|
|
4849
4849
|
}
|
|
4850
4850
|
function getPluginAgentsDir(pluginDir) {
|
|
4851
|
-
return
|
|
4851
|
+
return path12.join(pluginDir, STANDARD_DIRS.AGENTS);
|
|
4852
4852
|
}
|
|
4853
4853
|
function getPluginManifestPath(pluginDir) {
|
|
4854
|
-
return
|
|
4854
|
+
return path12.join(pluginDir, PLUGIN_MANIFEST_DIR, PLUGIN_MANIFEST_FILE);
|
|
4855
4855
|
}
|
|
4856
4856
|
async function readPluginManifest(pluginDir) {
|
|
4857
4857
|
const manifestPath = getPluginManifestPath(pluginDir);
|
|
@@ -4906,7 +4906,7 @@ function generateAgentPluginManifest(options) {
|
|
|
4906
4906
|
}
|
|
4907
4907
|
async function writePluginManifest(outputDir, manifest) {
|
|
4908
4908
|
const manifestPath = getPluginManifestPath(outputDir);
|
|
4909
|
-
await ensureDir(
|
|
4909
|
+
await ensureDir(path13.dirname(manifestPath));
|
|
4910
4910
|
const content = JSON.stringify(manifest, null, 2);
|
|
4911
4911
|
await writeFile(manifestPath, content);
|
|
4912
4912
|
return manifestPath;
|
|
@@ -4921,12 +4921,24 @@ function parseMarketplacePluginRef(ref) {
|
|
|
4921
4921
|
return separator === -1 ? ref : ref.slice(0, separator);
|
|
4922
4922
|
}
|
|
4923
4923
|
|
|
4924
|
+
// src/cli/lib/plugins/earlier-build.ts
|
|
4925
|
+
async function isEarlierBuild(pluginDir) {
|
|
4926
|
+
return fileExists(getPluginManifestPath(pluginDir));
|
|
4927
|
+
}
|
|
4928
|
+
async function holdsContentNoBuildMade(pluginDir) {
|
|
4929
|
+
if (await isEarlierBuild(pluginDir)) return false;
|
|
4930
|
+
return !await isDirectoryEmpty(pluginDir);
|
|
4931
|
+
}
|
|
4932
|
+
async function clearEarlierBuild(pluginDir) {
|
|
4933
|
+
if (await isEarlierBuild(pluginDir)) await remove(pluginDir);
|
|
4934
|
+
}
|
|
4935
|
+
|
|
4924
4936
|
// src/cli/lib/plugins/plugin-info.ts
|
|
4925
4937
|
import { readdir } from "fs/promises";
|
|
4926
4938
|
|
|
4927
4939
|
// src/cli/lib/installation/installation.ts
|
|
4928
4940
|
import os7 from "os";
|
|
4929
|
-
import
|
|
4941
|
+
import path14 from "path";
|
|
4930
4942
|
var INSTALL_MODE_LABELS = {
|
|
4931
4943
|
plugin: "Plugin",
|
|
4932
4944
|
mixed: "Mixed",
|
|
@@ -4965,7 +4977,7 @@ async function detectInstallationInDir(dir, scope) {
|
|
|
4965
4977
|
configPath,
|
|
4966
4978
|
agentsDir: agentsDir(provider, scope, dir),
|
|
4967
4979
|
// Mixed mode uses the local skills dir, as eject does.
|
|
4968
|
-
skillsDir:
|
|
4980
|
+
skillsDir: path14.join(
|
|
4969
4981
|
dir,
|
|
4970
4982
|
CLAUDE_DIR,
|
|
4971
4983
|
mode === "plugin" ? PLUGINS_SUBDIR : STANDARD_DIRS.SKILLS
|
|
@@ -4995,12 +5007,12 @@ async function detectInstallation(projectDir = process.cwd()) {
|
|
|
4995
5007
|
|
|
4996
5008
|
// src/cli/lib/installation/local-installer.ts
|
|
4997
5009
|
import os10 from "os";
|
|
4998
|
-
import
|
|
5010
|
+
import path18 from "path";
|
|
4999
5011
|
import { unique as unique4 } from "remeda";
|
|
5000
5012
|
|
|
5001
5013
|
// src/cli/lib/loading/loader.ts
|
|
5002
5014
|
import { parse as parseYaml3 } from "yaml";
|
|
5003
|
-
import
|
|
5015
|
+
import path15 from "path";
|
|
5004
5016
|
|
|
5005
5017
|
// src/cli/utils/frontmatter.ts
|
|
5006
5018
|
import { parse as parseYaml2 } from "yaml";
|
|
@@ -5073,7 +5085,7 @@ async function loadAgentsFromDir(agentsDir2, sourceRoot, options) {
|
|
|
5073
5085
|
return agents;
|
|
5074
5086
|
}
|
|
5075
5087
|
async function readAgentDefinition(agentsDir2, file, sourceRoot, options) {
|
|
5076
|
-
const fullPath =
|
|
5088
|
+
const fullPath = path15.join(agentsDir2, file);
|
|
5077
5089
|
try {
|
|
5078
5090
|
const content = await readFile(fullPath);
|
|
5079
5091
|
const parsed = agentYamlConfigSchema.safeParse(parseYaml3(content));
|
|
@@ -5106,7 +5118,7 @@ function toAgentDefinition(config, file, sourceRoot, options) {
|
|
|
5106
5118
|
...config.hooks !== void 0 && { hooks: config.hooks },
|
|
5107
5119
|
...config.experimental !== void 0 && { experimental: config.experimental },
|
|
5108
5120
|
...config.outputFormat !== void 0 && { outputFormat: config.outputFormat },
|
|
5109
|
-
path:
|
|
5121
|
+
path: path15.dirname(file),
|
|
5110
5122
|
sourceRoot,
|
|
5111
5123
|
...options.agentBaseDir ? { agentBaseDir: options.agentBaseDir } : {},
|
|
5112
5124
|
...config.domain ? { domain: config.domain } : {},
|
|
@@ -5114,7 +5126,7 @@ function toAgentDefinition(config, file, sourceRoot, options) {
|
|
|
5114
5126
|
};
|
|
5115
5127
|
}
|
|
5116
5128
|
async function loadAllAgents(projectRoot) {
|
|
5117
|
-
return loadAgentsFromDir(
|
|
5129
|
+
return loadAgentsFromDir(path15.join(projectRoot, DIRS.agents), projectRoot, {
|
|
5118
5130
|
includeCustomFlag: true,
|
|
5119
5131
|
verboseLabel: "agent"
|
|
5120
5132
|
});
|
|
@@ -5128,7 +5140,7 @@ async function loadMergedAgents(sourcePath) {
|
|
|
5128
5140
|
}
|
|
5129
5141
|
async function loadProjectAgents(projectRoot) {
|
|
5130
5142
|
const sourceFolder = sourceFolderInUse(projectRoot, providerInUse(projectRoot));
|
|
5131
|
-
const projectAgentsDir =
|
|
5143
|
+
const projectAgentsDir = path15.join(sourceFolder.dir, STANDARD_DIRS.AGENTS);
|
|
5132
5144
|
if (!await directoryExists2(projectAgentsDir)) {
|
|
5133
5145
|
verbose(`No project agents directory at ${projectAgentsDir}`);
|
|
5134
5146
|
return {};
|
|
@@ -5160,19 +5172,19 @@ async function loadSkillsFromDir(skillsDir2, options = {}) {
|
|
|
5160
5172
|
return { skills, unusableMetadata };
|
|
5161
5173
|
}
|
|
5162
5174
|
function locateSkill(skillsDir2, skillFile, pathPrefix) {
|
|
5163
|
-
const skillMdPath =
|
|
5164
|
-
const skillDir =
|
|
5165
|
-
const relativePath =
|
|
5175
|
+
const skillMdPath = path15.join(skillsDir2, skillFile);
|
|
5176
|
+
const skillDir = path15.dirname(skillMdPath);
|
|
5177
|
+
const relativePath = path15.relative(skillsDir2, skillDir);
|
|
5166
5178
|
return {
|
|
5167
5179
|
skillFile,
|
|
5168
5180
|
skillMdPath,
|
|
5169
5181
|
skillDir,
|
|
5170
|
-
skillDirName:
|
|
5182
|
+
skillDirName: path15.basename(skillDir),
|
|
5171
5183
|
displayPath: pathPrefix ? `${pathPrefix}/${relativePath}/` : `${relativePath}/`
|
|
5172
5184
|
};
|
|
5173
5185
|
}
|
|
5174
5186
|
async function judgeSkillMetadata(skill) {
|
|
5175
|
-
const metadataPath =
|
|
5187
|
+
const metadataPath = path15.join(skill.skillDir, STANDARD_FILES.METADATA_YAML);
|
|
5176
5188
|
if (!await fileExists(metadataPath)) {
|
|
5177
5189
|
warn(
|
|
5178
5190
|
`Skill '${skill.skillDirName}' in '${skill.displayPath}' is missing ${STANDARD_FILES.METADATA_YAML} \u2014 skipped. Add ${STANDARD_FILES.METADATA_YAML} to register it with the CLI.`
|
|
@@ -5214,7 +5226,7 @@ async function readSkillDefinition(skill) {
|
|
|
5214
5226
|
}
|
|
5215
5227
|
}
|
|
5216
5228
|
async function loadPluginSkills(pluginDir) {
|
|
5217
|
-
const { skills } = await loadSkillsFromDir(
|
|
5229
|
+
const { skills } = await loadSkillsFromDir(path15.join(pluginDir, "skills"), {
|
|
5218
5230
|
pathPrefix: "skills",
|
|
5219
5231
|
requireMetadata: false
|
|
5220
5232
|
});
|
|
@@ -5222,13 +5234,15 @@ async function loadPluginSkills(pluginDir) {
|
|
|
5222
5234
|
}
|
|
5223
5235
|
|
|
5224
5236
|
// src/cli/lib/loading/source-fetcher.ts
|
|
5237
|
+
import { AsyncLocalStorage as AsyncLocalStorage3 } from "async_hooks";
|
|
5225
5238
|
import { createHash as createHash2 } from "crypto";
|
|
5239
|
+
import { rename } from "fs/promises";
|
|
5226
5240
|
import { downloadTemplate } from "giget";
|
|
5227
5241
|
import os8 from "os";
|
|
5228
|
-
import
|
|
5242
|
+
import path17 from "path";
|
|
5229
5243
|
|
|
5230
5244
|
// src/cli/lib/marketplace-generator.ts
|
|
5231
|
-
import
|
|
5245
|
+
import path16 from "path";
|
|
5232
5246
|
import { countBy, sortBy } from "remeda";
|
|
5233
5247
|
var PLUGIN_MANIFEST_PATH = `${PLUGIN_MANIFEST_DIR}/${PLUGIN_MANIFEST_FILE}`;
|
|
5234
5248
|
var MARKETPLACE_SCHEMA_URL = "https://anthropic.com/claude-code/marketplace.schema.json";
|
|
@@ -5260,7 +5274,7 @@ async function generateMarketplace(pluginsDir2, options) {
|
|
|
5260
5274
|
const rootWithoutDotSlash = options.pluginRoot.replace(/^\.\//, "");
|
|
5261
5275
|
for (const manifestFile of manifestFiles) {
|
|
5262
5276
|
const pluginDirName = pluginDirNameOf(manifestFile);
|
|
5263
|
-
const pluginDir =
|
|
5277
|
+
const pluginDir = path16.join(pluginsDir2, pluginDirName);
|
|
5264
5278
|
const manifest = await readPluginManifest(pluginDir);
|
|
5265
5279
|
if (!manifest) {
|
|
5266
5280
|
warn(`Could not read plugin manifest: '${manifestFile}'`);
|
|
@@ -5315,17 +5329,17 @@ function reservedNameError(marketplaceName, wayOut) {
|
|
|
5315
5329
|
return `Marketplace name '${marketplaceName}' is reserved. '${DEFAULT_PUBLIC_SOURCE_NAME}' is the public catalogue's own namespace, '${EXTERNAL_SKILL_NAMESPACE}' and '${LOCAL_SKILL_NAMESPACE}' hold the skills that belong to no marketplace, and '${EJECT_SOURCE}' is what an installation records for a skill copied into it rather than installed as a plugin \u2014 a marketplace under any of them is read back as something it is not. Choose a name of your own: ${wayOut}.`;
|
|
5316
5330
|
}
|
|
5317
5331
|
function namespaceViolationError(foreignIds, marketplaceName) {
|
|
5318
|
-
const
|
|
5319
|
-
const unlisted = foreignIds.length -
|
|
5332
|
+
const listed2 = foreignIds.slice(0, MAX_REPORTED_NAMESPACE_VIOLATIONS).map((id) => ` ${id} -> ${marketplaceName}-${id}`);
|
|
5333
|
+
const unlisted = foreignIds.length - listed2.length;
|
|
5320
5334
|
return [
|
|
5321
5335
|
`Marketplace '${marketplaceName}' ships ${foreignIds.length} skill id(s) outside its own namespace. Every skill id must begin with the marketplace's name:`,
|
|
5322
|
-
...
|
|
5336
|
+
...listed2,
|
|
5323
5337
|
...unlisted > 0 ? [` ... and ${unlisted} more`] : [],
|
|
5324
5338
|
`Rename each skill directory and the 'name' in its SKILL.md, re-run 'build plugins', then build the marketplace again.`
|
|
5325
5339
|
].join("\n");
|
|
5326
5340
|
}
|
|
5327
5341
|
async function writeMarketplace(outputPath, marketplace) {
|
|
5328
|
-
await ensureDir(
|
|
5342
|
+
await ensureDir(path16.dirname(outputPath));
|
|
5329
5343
|
const content = `${JSON.stringify(marketplace, null, 2)}
|
|
5330
5344
|
`;
|
|
5331
5345
|
await writeFile(outputPath, content);
|
|
@@ -5343,6 +5357,29 @@ var MAX_NAME_LENGTH = 200;
|
|
|
5343
5357
|
var QUOTED_NAME_LENGTH = 50;
|
|
5344
5358
|
var SOURCE_PROTO_RE = /^([\w-.]+):/;
|
|
5345
5359
|
var GIT_URI_RE = /^(?<repo>[\w.-]+\/[\w.-]+)(?<subdir>[^#]+)?(?<ref>#[\w./@-]+)?/;
|
|
5360
|
+
var MarketplaceUnreachableError = class extends Error {
|
|
5361
|
+
constructor(source, reason) {
|
|
5362
|
+
super(`Could not reach ${source}: ${reason}`);
|
|
5363
|
+
this.source = source;
|
|
5364
|
+
this.reason = reason;
|
|
5365
|
+
this.name = "MarketplaceUnreachableError";
|
|
5366
|
+
}
|
|
5367
|
+
source;
|
|
5368
|
+
reason;
|
|
5369
|
+
};
|
|
5370
|
+
var TarballWithheldError = class extends Error {
|
|
5371
|
+
constructor({ status, statusText }) {
|
|
5372
|
+
super(`the marketplace answered ${status} ${statusText}`.trimEnd());
|
|
5373
|
+
this.name = "TarballWithheldError";
|
|
5374
|
+
}
|
|
5375
|
+
};
|
|
5376
|
+
var marketplaceMustAnswer = new AsyncLocalStorage3();
|
|
5377
|
+
function askingEachMarketplaceItself(body) {
|
|
5378
|
+
return marketplaceMustAnswer.run(true, body);
|
|
5379
|
+
}
|
|
5380
|
+
function mustAnswer() {
|
|
5381
|
+
return marketplaceMustAnswer.getStore() === true;
|
|
5382
|
+
}
|
|
5346
5383
|
function sanitizeSourceForCache(source) {
|
|
5347
5384
|
const hash = createHash2("sha256").update(source).digest("hex").slice(0, CACHE_HASH_LENGTH);
|
|
5348
5385
|
const readable = source.replace(/[^a-zA-Z0-9]/g, "-").replace(/--+/g, "-").replace(/^-|-$/g, "").slice(0, CACHE_READABLE_PREFIX_LENGTH);
|
|
@@ -5350,7 +5387,7 @@ function sanitizeSourceForCache(source) {
|
|
|
5350
5387
|
}
|
|
5351
5388
|
function getCacheDir(source) {
|
|
5352
5389
|
const sanitized = sanitizeSourceForCache(source) || "unknown";
|
|
5353
|
-
return
|
|
5390
|
+
return path17.join(cacheRoot(), "sources", sanitized);
|
|
5354
5391
|
}
|
|
5355
5392
|
async function fetchFromSource(source, options = {}) {
|
|
5356
5393
|
const { subdir } = options;
|
|
@@ -5361,8 +5398,8 @@ async function fetchFromSource(source, options = {}) {
|
|
|
5361
5398
|
return fetchFromRemoteSource(source, subdir);
|
|
5362
5399
|
}
|
|
5363
5400
|
async function fetchFromLocalSource(source, subdir) {
|
|
5364
|
-
const fullPath = subdir ?
|
|
5365
|
-
const absolutePath =
|
|
5401
|
+
const fullPath = subdir ? path17.join(source, subdir) : source;
|
|
5402
|
+
const absolutePath = path17.isAbsolute(fullPath) ? fullPath : path17.resolve(process.cwd(), fullPath);
|
|
5366
5403
|
if (!await directoryExists2(absolutePath)) {
|
|
5367
5404
|
throw new Error(
|
|
5368
5405
|
`Local marketplace not found: '${absolutePath}'
|
|
@@ -5393,8 +5430,8 @@ function getGigetCacheDir(source) {
|
|
|
5393
5430
|
return void 0;
|
|
5394
5431
|
}
|
|
5395
5432
|
const templateName = uriMatch.groups.repo.replace("/", "-").replace(/[^\da-z-]/gi, "-");
|
|
5396
|
-
const gigetCacheRoot = process.env.XDG_CACHE_HOME ?
|
|
5397
|
-
return
|
|
5433
|
+
const gigetCacheRoot = process.env.XDG_CACHE_HOME ? path17.resolve(process.env.XDG_CACHE_HOME, "giget") : path17.resolve(os8.homedir(), ".cache", "giget");
|
|
5434
|
+
return path17.join(gigetCacheRoot, providerName, templateName);
|
|
5398
5435
|
}
|
|
5399
5436
|
async function clearGigetCache(source) {
|
|
5400
5437
|
const gigetDir = getGigetCacheDir(source);
|
|
@@ -5421,16 +5458,16 @@ async function fetchFromRemoteSource(source, subdir) {
|
|
|
5421
5458
|
};
|
|
5422
5459
|
}
|
|
5423
5460
|
announceRefetch(verdict);
|
|
5424
|
-
await discardCachedCopy(cacheDir, source);
|
|
5461
|
+
if (!mustAnswer()) await discardCachedCopy(cacheDir, source);
|
|
5425
5462
|
}
|
|
5426
|
-
return downloadFreshCopy(cacheDir, source, fullSource);
|
|
5463
|
+
return mustAnswer() ? downloadAnsweredFor(cacheDir, source, fullSource) : downloadFreshCopy(cacheDir, source, fullSource);
|
|
5427
5464
|
}
|
|
5428
5465
|
async function discardCachedCopy(cacheDir, source) {
|
|
5429
5466
|
await clearGigetCache(source);
|
|
5430
5467
|
await remove(cacheDir);
|
|
5431
5468
|
}
|
|
5432
5469
|
async function downloadFreshCopy(cacheDir, source, fullSource) {
|
|
5433
|
-
await ensureDir(
|
|
5470
|
+
await ensureDir(path17.dirname(cacheDir));
|
|
5434
5471
|
try {
|
|
5435
5472
|
const result = await downloadTemplate(fullSource, {
|
|
5436
5473
|
dir: cacheDir,
|
|
@@ -5451,40 +5488,75 @@ async function downloadFreshCopy(cacheDir, source, fullSource) {
|
|
|
5451
5488
|
throw createDetailedFetchError(error, source);
|
|
5452
5489
|
}
|
|
5453
5490
|
}
|
|
5491
|
+
var STAGED_DOWNLOAD_SUFFIX = ".download";
|
|
5492
|
+
async function downloadAnsweredFor(cacheDir, source, fullSource) {
|
|
5493
|
+
const staged = `${cacheDir}${STAGED_DOWNLOAD_SUFFIX}`;
|
|
5494
|
+
await ensureDir(path17.dirname(cacheDir));
|
|
5495
|
+
try {
|
|
5496
|
+
const result = await downloadTemplate(fullSource, {
|
|
5497
|
+
dir: staged,
|
|
5498
|
+
force: true,
|
|
5499
|
+
forceClean: true,
|
|
5500
|
+
offline: false
|
|
5501
|
+
});
|
|
5502
|
+
const record = await askAfterTheDownload(result, source);
|
|
5503
|
+
await replaceCopy(cacheDir, staged, record);
|
|
5504
|
+
markCopyCurrentForThisRun(cacheDir);
|
|
5505
|
+
return { path: cacheDir, fromCache: false, unreachable: false, source: fullSource };
|
|
5506
|
+
} catch (error) {
|
|
5507
|
+
if (error instanceof MarketplaceUnreachableError) throw error;
|
|
5508
|
+
throw createDetailedFetchError(error, source);
|
|
5509
|
+
} finally {
|
|
5510
|
+
await remove(staged);
|
|
5511
|
+
}
|
|
5512
|
+
}
|
|
5513
|
+
async function replaceCopy(cacheDir, staged, record) {
|
|
5514
|
+
await remove(cacheDir);
|
|
5515
|
+
await rename(staged, cacheDir);
|
|
5516
|
+
await writeFile(fetchRecordPath(cacheDir), JSON.stringify(record));
|
|
5517
|
+
}
|
|
5454
5518
|
var REVALIDATION_TIMEOUT_MS = 5e3;
|
|
5455
5519
|
var FETCH_RECORD_SUFFIX = ".etag.json";
|
|
5456
5520
|
var askedThisRun = /* @__PURE__ */ new Map();
|
|
5521
|
+
var askedItselfThisRun = /* @__PURE__ */ new Map();
|
|
5522
|
+
function verdictsThisRun() {
|
|
5523
|
+
return mustAnswer() ? askedItselfThisRun : askedThisRun;
|
|
5524
|
+
}
|
|
5457
5525
|
function announceRefetch(verdict) {
|
|
5458
5526
|
if (verdict === "superseded") {
|
|
5459
5527
|
log(STATUS_MESSAGES.MARKETPLACE_HAS_NEWER_CONTENT);
|
|
5460
5528
|
}
|
|
5461
5529
|
}
|
|
5462
5530
|
function revalidateCachedCopy(cacheDir, source) {
|
|
5463
|
-
const
|
|
5531
|
+
const verdicts = verdictsThisRun();
|
|
5532
|
+
const asked = verdicts.get(cacheDir);
|
|
5464
5533
|
if (asked) return asked;
|
|
5465
5534
|
const verdict = classifyCachedCopy(cacheDir, source);
|
|
5466
|
-
|
|
5535
|
+
verdicts.set(cacheDir, verdict);
|
|
5467
5536
|
return verdict;
|
|
5468
5537
|
}
|
|
5469
5538
|
function markCopyCurrentForThisRun(cacheDir) {
|
|
5470
|
-
|
|
5539
|
+
verdictsThisRun().set(cacheDir, Promise.resolve("current"));
|
|
5471
5540
|
}
|
|
5472
5541
|
async function classifyCachedCopy(cacheDir, source) {
|
|
5473
5542
|
const record = await readFetchRecord(cacheDir);
|
|
5474
5543
|
if (!record) return "unrecorded";
|
|
5475
|
-
if (record.etag === void 0) {
|
|
5544
|
+
if (record.etag === void 0 && !mustAnswer()) {
|
|
5476
5545
|
verbose(`No ETag was recorded for ${record.tar} \u2014 keeping the cached copy`);
|
|
5477
5546
|
return "current";
|
|
5478
5547
|
}
|
|
5479
5548
|
try {
|
|
5480
5549
|
const live = await fetchEtag(record.tar);
|
|
5481
|
-
if (live
|
|
5482
|
-
|
|
5483
|
-
return "current";
|
|
5550
|
+
if (live !== void 0 && record.etag !== void 0) {
|
|
5551
|
+
return live === record.etag ? "current" : "superseded";
|
|
5484
5552
|
}
|
|
5485
|
-
|
|
5553
|
+
if (mustAnswer()) return "unconfirmed";
|
|
5554
|
+
verbose(`${record.tar} answered without an ETag \u2014 keeping the cached copy`);
|
|
5555
|
+
return "current";
|
|
5486
5556
|
} catch (error) {
|
|
5557
|
+
if (error instanceof TarballWithheldError) throw createDetailedFetchError(error, source);
|
|
5487
5558
|
verbose(`Could not revalidate ${record.tar}: ${getErrorMessage(error)}`);
|
|
5559
|
+
if (mustAnswer()) throw new MarketplaceUnreachableError(source, getErrorMessage(error));
|
|
5488
5560
|
warn(sourceUnreachableUsingCache(source));
|
|
5489
5561
|
return "unreachable";
|
|
5490
5562
|
}
|
|
@@ -5492,10 +5564,12 @@ async function classifyCachedCopy(cacheDir, source) {
|
|
|
5492
5564
|
async function fetchEtag(tar) {
|
|
5493
5565
|
const auth = process.env.GIGET_AUTH;
|
|
5494
5566
|
const response = await fetch(tar, {
|
|
5495
|
-
method: "HEAD",
|
|
5567
|
+
method: mustAnswer() ? "GET" : "HEAD",
|
|
5496
5568
|
...auth && { headers: { Authorization: `Bearer ${auth}` } },
|
|
5497
5569
|
signal: AbortSignal.timeout(REVALIDATION_TIMEOUT_MS)
|
|
5498
5570
|
});
|
|
5571
|
+
await response.body?.cancel();
|
|
5572
|
+
if (mustAnswer() && !response.ok) throw new TarballWithheldError(response);
|
|
5499
5573
|
return response.headers.get("etag") ?? void 0;
|
|
5500
5574
|
}
|
|
5501
5575
|
function fetchRecordPath(cacheDir) {
|
|
@@ -5512,14 +5586,40 @@ async function readFetchRecord(cacheDir) {
|
|
|
5512
5586
|
return parsed.data;
|
|
5513
5587
|
}
|
|
5514
5588
|
async function recordFetchedCopy(cacheDir, result) {
|
|
5515
|
-
const tar = result
|
|
5516
|
-
if (
|
|
5589
|
+
const tar = tarballOf(result);
|
|
5590
|
+
if (tar === void 0) {
|
|
5517
5591
|
verbose("No tarball URL came back from the download \u2014 the copy cannot be revalidated");
|
|
5518
5592
|
return;
|
|
5519
5593
|
}
|
|
5520
|
-
const etag = await
|
|
5521
|
-
|
|
5522
|
-
|
|
5594
|
+
const etag = await etagIfAnswered(tar);
|
|
5595
|
+
await writeFile(fetchRecordPath(cacheDir), JSON.stringify(fetchRecord(tar, etag)));
|
|
5596
|
+
}
|
|
5597
|
+
async function etagIfAnswered(tar) {
|
|
5598
|
+
try {
|
|
5599
|
+
return await fetchEtag(tar);
|
|
5600
|
+
} catch (error) {
|
|
5601
|
+
verbose(`Could not ask ${tar} after the download: ${getErrorMessage(error)}`);
|
|
5602
|
+
return void 0;
|
|
5603
|
+
}
|
|
5604
|
+
}
|
|
5605
|
+
async function askAfterTheDownload(result, source) {
|
|
5606
|
+
const tar = tarballOf(result);
|
|
5607
|
+
if (tar === void 0) {
|
|
5608
|
+
throw new Error("the download named no tarball to ask the marketplace about");
|
|
5609
|
+
}
|
|
5610
|
+
try {
|
|
5611
|
+
return fetchRecord(tar, await fetchEtag(tar));
|
|
5612
|
+
} catch (error) {
|
|
5613
|
+
if (error instanceof TarballWithheldError) throw error;
|
|
5614
|
+
throw new MarketplaceUnreachableError(source, getErrorMessage(error));
|
|
5615
|
+
}
|
|
5616
|
+
}
|
|
5617
|
+
function tarballOf(result) {
|
|
5618
|
+
const tar = result.tar;
|
|
5619
|
+
return typeof tar === "string" ? tar : void 0;
|
|
5620
|
+
}
|
|
5621
|
+
function fetchRecord(tar, etag) {
|
|
5622
|
+
return { tar, ...etag !== void 0 && { etag } };
|
|
5523
5623
|
}
|
|
5524
5624
|
function parseJsonOrUndefined(raw) {
|
|
5525
5625
|
try {
|
|
@@ -5824,9 +5924,9 @@ function agentNotFoundError(agentName, agents) {
|
|
|
5824
5924
|
}
|
|
5825
5925
|
function describeAvailableAgents(availableAgents) {
|
|
5826
5926
|
if (availableAgents.length === 0) return "No agents found in scanned directories";
|
|
5827
|
-
const
|
|
5927
|
+
const listed2 = availableAgents.slice(0, MAX_LISTED_AVAILABLE_AGENTS).join(", ");
|
|
5828
5928
|
const unlisted = availableAgents.length - MAX_LISTED_AVAILABLE_AGENTS;
|
|
5829
|
-
return unlisted > 0 ? `Available agents: ${
|
|
5929
|
+
return unlisted > 0 ? `Available agents: ${listed2} (and ${unlisted} more)` : `Available agents: ${listed2}`;
|
|
5830
5930
|
}
|
|
5831
5931
|
function assembleAgentConfig(agentName, definition, agentConfig, resolvedSkills) {
|
|
5832
5932
|
const model = agentConfig.model ?? definition.model;
|
|
@@ -5863,10 +5963,10 @@ function resolveStackProperty(generated, assigned) {
|
|
|
5863
5963
|
return generated === void 0 ? void 0 : assigned;
|
|
5864
5964
|
}
|
|
5865
5965
|
function resolveDescription(loadedStack, shared) {
|
|
5866
|
-
return
|
|
5966
|
+
return shared ?? loadedStack?.description;
|
|
5867
5967
|
}
|
|
5868
5968
|
function configNameFor(projectDir) {
|
|
5869
|
-
return isHomeDirectory(projectDir) ? DEFAULT_PLUGIN_NAME :
|
|
5969
|
+
return isHomeDirectory(projectDir) ? DEFAULT_PLUGIN_NAME : path18.basename(projectDir);
|
|
5870
5970
|
}
|
|
5871
5971
|
async function loadCuratedStack(projectDir, projectStack) {
|
|
5872
5972
|
const globalStack = isHomeDirectory(projectDir) ? void 0 : await loadGlobalStack();
|
|
@@ -6039,12 +6139,12 @@ async function installationIfPresent(candidate) {
|
|
|
6039
6139
|
|
|
6040
6140
|
// src/cli/lib/hosts/claude-host.ts
|
|
6041
6141
|
import os12 from "os";
|
|
6042
|
-
import
|
|
6142
|
+
import path21 from "path";
|
|
6043
6143
|
import { z as z5 } from "zod";
|
|
6044
6144
|
|
|
6045
6145
|
// src/cli/utils/exec.ts
|
|
6046
6146
|
import { spawn } from "child_process";
|
|
6047
|
-
import
|
|
6147
|
+
import path19 from "path";
|
|
6048
6148
|
var MAX_PLUGIN_PATH_LENGTH = 1024;
|
|
6049
6149
|
var MAX_PLUGIN_NAME_LENGTH = 256;
|
|
6050
6150
|
var MAX_MARKETPLACE_SOURCE_LENGTH = 1024;
|
|
@@ -6052,7 +6152,7 @@ var SAFE_NAME_PATTERN2 = /^[a-zA-Z0-9._@/-]+$/;
|
|
|
6052
6152
|
var SAFE_PLUGIN_PATH_PATTERN = /^[a-zA-Z0-9._@/:~-]+$/;
|
|
6053
6153
|
var OPENS_A_RELATIVE_PATH = /^\.\.?[/\\]/;
|
|
6054
6154
|
function namesADirectoryOnThisMachine(source) {
|
|
6055
|
-
return
|
|
6155
|
+
return path19.isAbsolute(source) || OPENS_A_RELATIVE_PATH.test(source);
|
|
6056
6156
|
}
|
|
6057
6157
|
var CONTROL_CHAR_PATTERN = /[\x00-\x08\x0E-\x1F\x7F]/u;
|
|
6058
6158
|
function validatePluginPath(pluginPath) {
|
|
@@ -6142,7 +6242,7 @@ async function execCommand(command, args, options) {
|
|
|
6142
6242
|
}
|
|
6143
6243
|
|
|
6144
6244
|
// src/cli/lib/plugins/plugin-settings.ts
|
|
6145
|
-
import
|
|
6245
|
+
import path20 from "path";
|
|
6146
6246
|
import { z as z4 } from "zod";
|
|
6147
6247
|
var pluginSettingsSchema = z4.object({
|
|
6148
6248
|
// Absent when no plugin is enabled.
|
|
@@ -6163,7 +6263,7 @@ var installedPluginsSchema = z4.object({
|
|
|
6163
6263
|
plugins: z4.record(z4.string(), z4.array(pluginInstallationSchema))
|
|
6164
6264
|
}).passthrough();
|
|
6165
6265
|
function getInstalledPluginsRegistryPath(pluginsDir2) {
|
|
6166
|
-
return
|
|
6266
|
+
return path20.join(pluginsDir2, INSTALLED_PLUGINS_FILE);
|
|
6167
6267
|
}
|
|
6168
6268
|
async function readRegisteredInstallations(pluginsDir2) {
|
|
6169
6269
|
const registryPath = getInstalledPluginsRegistryPath(pluginsDir2);
|
|
@@ -6196,7 +6296,7 @@ async function listPluginInstallsForProject(pluginsDir2, projectDir) {
|
|
|
6196
6296
|
});
|
|
6197
6297
|
}
|
|
6198
6298
|
async function getEnabledPluginKeys(projectDir) {
|
|
6199
|
-
const settingsPath =
|
|
6299
|
+
const settingsPath = path20.join(projectDir, CLAUDE_DIR, STANDARD_FILES.SETTINGS_JSON);
|
|
6200
6300
|
if (!await fileExists(settingsPath)) {
|
|
6201
6301
|
verbose(`No settings.json found at '${settingsPath}'`);
|
|
6202
6302
|
return [];
|
|
@@ -6344,7 +6444,7 @@ function namesNothingThere(message) {
|
|
|
6344
6444
|
return NOT_INSTALLED_MESSAGES.some((phrase) => message.includes(phrase));
|
|
6345
6445
|
}
|
|
6346
6446
|
function claudePluginsRoot(projectDir, options) {
|
|
6347
|
-
if (options?.configDir !== void 0) return
|
|
6447
|
+
if (options?.configDir !== void 0) return path21.join(options.configDir, PLUGINS_SUBDIR);
|
|
6348
6448
|
return pluginsDir(CLAUDE, "global", projectDir);
|
|
6349
6449
|
}
|
|
6350
6450
|
async function claudeListPlugins(projectDir, options) {
|
|
@@ -6379,7 +6479,7 @@ function claudeHost() {
|
|
|
6379
6479
|
|
|
6380
6480
|
// src/cli/lib/hosts/codex-host.ts
|
|
6381
6481
|
import os13 from "os";
|
|
6382
|
-
import
|
|
6482
|
+
import path22 from "path";
|
|
6383
6483
|
import { z as z6 } from "zod";
|
|
6384
6484
|
var CODEX = "codex";
|
|
6385
6485
|
var PLUGIN_CACHE_SUBDIR = "cache";
|
|
@@ -6463,7 +6563,7 @@ var pluginListingSchema = z6.object({
|
|
|
6463
6563
|
)
|
|
6464
6564
|
});
|
|
6465
6565
|
function codexPluginsRoot(projectDir, options) {
|
|
6466
|
-
if (options?.configDir !== void 0) return
|
|
6566
|
+
if (options?.configDir !== void 0) return path22.join(options.configDir, PLUGINS_SUBDIR);
|
|
6467
6567
|
return pluginsDir(CODEX, "global", projectDir);
|
|
6468
6568
|
}
|
|
6469
6569
|
async function isCodexCLIAvailable(options) {
|
|
@@ -6593,7 +6693,7 @@ async function codexListPlugins(projectDir, options) {
|
|
|
6593
6693
|
async function codexPluginsOrUnreadable(projectDir, options) {
|
|
6594
6694
|
const pluginsRoot = codexPluginsRoot(projectDir, options);
|
|
6595
6695
|
if (pluginsRoot === null) return { kind: "listed", plugins: [] };
|
|
6596
|
-
const cacheRoot2 =
|
|
6696
|
+
const cacheRoot2 = path22.join(pluginsRoot, PLUGIN_CACHE_SUBDIR);
|
|
6597
6697
|
let installed;
|
|
6598
6698
|
try {
|
|
6599
6699
|
installed = await codexPluginListing(options, projectDir);
|
|
@@ -6605,7 +6705,7 @@ async function codexPluginsOrUnreadable(projectDir, options) {
|
|
|
6605
6705
|
kind: "listed",
|
|
6606
6706
|
plugins: installed.map((plugin) => ({
|
|
6607
6707
|
pluginKey: plugin.pluginId,
|
|
6608
|
-
installPath:
|
|
6708
|
+
installPath: path22.join(cacheRoot2, plugin.marketplaceName, plugin.name, plugin.version),
|
|
6609
6709
|
enabled: plugin.enabled
|
|
6610
6710
|
}))
|
|
6611
6711
|
};
|
|
@@ -6915,7 +7015,7 @@ function formatInstallationDisplay(info) {
|
|
|
6915
7015
|
}
|
|
6916
7016
|
|
|
6917
7017
|
// src/cli/lib/plugins/plugin-validator.ts
|
|
6918
|
-
import
|
|
7018
|
+
import path23 from "path";
|
|
6919
7019
|
|
|
6920
7020
|
// src/cli/lib/validation-result.ts
|
|
6921
7021
|
function validResult() {
|
|
@@ -6947,15 +7047,15 @@ async function validatePluginStructure(pluginPath) {
|
|
|
6947
7047
|
if (!await directoryExists2(pluginPath)) {
|
|
6948
7048
|
return invalidResult(`Plugin directory does not exist: ${pluginPath}`);
|
|
6949
7049
|
}
|
|
6950
|
-
const pluginDir =
|
|
7050
|
+
const pluginDir = path23.join(pluginPath, PLUGIN_MANIFEST_DIR);
|
|
6951
7051
|
if (!await directoryExists2(pluginDir)) {
|
|
6952
7052
|
errors.push(`Missing ${PLUGIN_MANIFEST_DIR}/ directory`);
|
|
6953
7053
|
}
|
|
6954
|
-
const manifestPath =
|
|
7054
|
+
const manifestPath = path23.join(pluginDir, STANDARD_FILES.PLUGIN_JSON);
|
|
6955
7055
|
if (!await fileExists(manifestPath)) {
|
|
6956
7056
|
errors.push(`Missing ${PLUGIN_MANIFEST_DIR}/${STANDARD_FILES.PLUGIN_JSON}`);
|
|
6957
7057
|
}
|
|
6958
|
-
const readmePath =
|
|
7058
|
+
const readmePath = path23.join(pluginPath, STANDARD_FILES.README_MD);
|
|
6959
7059
|
if (!await fileExists(readmePath)) {
|
|
6960
7060
|
warnings.push("Missing README.md (recommended for documentation)");
|
|
6961
7061
|
}
|
|
@@ -6998,15 +7098,15 @@ async function validatePluginManifest(manifestPath) {
|
|
|
6998
7098
|
if (!manifest.description) {
|
|
6999
7099
|
warnings.push("Missing description field (recommended for discoverability)");
|
|
7000
7100
|
}
|
|
7001
|
-
const pluginDir =
|
|
7101
|
+
const pluginDir = path23.dirname(path23.dirname(manifestPath));
|
|
7002
7102
|
if (isNonEmptyString(manifest.skills)) {
|
|
7003
|
-
const skillsPath =
|
|
7103
|
+
const skillsPath = path23.join(pluginDir, manifest.skills);
|
|
7004
7104
|
if (!await directoryExists2(skillsPath)) {
|
|
7005
7105
|
errors.push(`Skills path does not exist: ${manifest.skills}`);
|
|
7006
7106
|
}
|
|
7007
7107
|
}
|
|
7008
7108
|
if (isNonEmptyString(manifest.agents)) {
|
|
7009
|
-
const agentsPath =
|
|
7109
|
+
const agentsPath = path23.join(pluginDir, manifest.agents);
|
|
7010
7110
|
if (!await directoryExists2(agentsPath)) {
|
|
7011
7111
|
errors.push(`Agents path does not exist: ${manifest.agents}`);
|
|
7012
7112
|
}
|
|
@@ -7075,14 +7175,14 @@ function prefixResult(result, prefix) {
|
|
|
7075
7175
|
async function validateEachFile(pluginPath, scannedDir, files, validate) {
|
|
7076
7176
|
const results = await Promise.all(
|
|
7077
7177
|
files.map(async (file) => {
|
|
7078
|
-
const filePath =
|
|
7079
|
-
return prefixResult(await validate(filePath),
|
|
7178
|
+
const filePath = path23.join(scannedDir, file);
|
|
7179
|
+
return prefixResult(await validate(filePath), path23.relative(pluginPath, filePath));
|
|
7080
7180
|
})
|
|
7081
7181
|
);
|
|
7082
7182
|
return mergeValidationResults(results);
|
|
7083
7183
|
}
|
|
7084
7184
|
async function validatePluginSkillFiles(pluginPath, skillsRelPath) {
|
|
7085
|
-
const skillsDir2 =
|
|
7185
|
+
const skillsDir2 = path23.join(pluginPath, skillsRelPath);
|
|
7086
7186
|
if (!await directoryExists2(skillsDir2)) return validResult();
|
|
7087
7187
|
const files = await glob(`**/${STANDARD_FILES.SKILL_MD}`, skillsDir2);
|
|
7088
7188
|
if (files.length === 0) {
|
|
@@ -7095,7 +7195,7 @@ async function validatePluginSkillFiles(pluginPath, skillsRelPath) {
|
|
|
7095
7195
|
return validateEachFile(pluginPath, skillsDir2, files, validateSkillFrontmatter);
|
|
7096
7196
|
}
|
|
7097
7197
|
async function validatePluginAgentFiles(pluginPath, agentsRelPath) {
|
|
7098
|
-
const agentsDir2 =
|
|
7198
|
+
const agentsDir2 = path23.join(pluginPath, agentsRelPath);
|
|
7099
7199
|
if (!await directoryExists2(agentsDir2)) return validResult();
|
|
7100
7200
|
const files = await glob(agentCodec("claude").listGlob, agentsDir2);
|
|
7101
7201
|
if (files.length === 0) {
|
|
@@ -7166,7 +7266,7 @@ async function listPluginDirNames(pluginsDir2) {
|
|
|
7166
7266
|
const dirChecks = await Promise.all(
|
|
7167
7267
|
allDirs.map(async (dirName) => ({
|
|
7168
7268
|
dirName,
|
|
7169
|
-
isPlugin: await directoryExists2(
|
|
7269
|
+
isPlugin: await directoryExists2(path23.join(pluginsDir2, dirName, PLUGIN_MANIFEST_DIR))
|
|
7170
7270
|
}))
|
|
7171
7271
|
);
|
|
7172
7272
|
return dirChecks.filter((c) => c.isPlugin).map((c) => c.dirName);
|
|
@@ -7174,7 +7274,7 @@ async function listPluginDirNames(pluginsDir2) {
|
|
|
7174
7274
|
async function validateEachPlugin(pluginsDir2, pluginDirs) {
|
|
7175
7275
|
const results = [];
|
|
7176
7276
|
for (const pluginName of pluginDirs) {
|
|
7177
|
-
const result = await validatePlugin(
|
|
7277
|
+
const result = await validatePlugin(path23.join(pluginsDir2, pluginName));
|
|
7178
7278
|
results.push({ name: pluginName, result });
|
|
7179
7279
|
}
|
|
7180
7280
|
return results;
|
|
@@ -7257,11 +7357,11 @@ function sanitizeSkillName(name) {
|
|
|
7257
7357
|
return name.replace(/\+/g, "-");
|
|
7258
7358
|
}
|
|
7259
7359
|
function isSingleFolderName(name) {
|
|
7260
|
-
return name !== "" && name !== "." && name !== ".." &&
|
|
7360
|
+
return name !== "" && name !== "." && name !== ".." && path24.basename(name) === name;
|
|
7261
7361
|
}
|
|
7262
7362
|
async function assertClearable(pluginDir, skillPath, skillName) {
|
|
7263
|
-
const skill = `Skill '${
|
|
7264
|
-
const file = `File: ${
|
|
7363
|
+
const skill = `Skill '${path24.basename(skillPath)}'`;
|
|
7364
|
+
const file = `File: ${path24.join(skillPath, STANDARD_FILES.SKILL_MD)}`;
|
|
7265
7365
|
if (!isSingleFolderName(skillName)) {
|
|
7266
7366
|
throw new Error(
|
|
7267
7367
|
`${skill} is named '${skillName}', which is not a single folder name, so its plugin cannot be built inside the output directory. ${file}`
|
|
@@ -7274,22 +7374,12 @@ async function assertClearable(pluginDir, skillPath, skillName) {
|
|
|
7274
7374
|
}
|
|
7275
7375
|
if (await holdsContentNoBuildMade(pluginDir)) {
|
|
7276
7376
|
throw new Error(
|
|
7277
|
-
`${skill} would be built into ${pluginDir}, which holds no ${
|
|
7377
|
+
`${skill} would be built into ${pluginDir}, which holds no ${path24.join(PLUGIN_MANIFEST_DIR, PLUGIN_MANIFEST_FILE)} and is not empty, so no earlier build made it and a rebuild would delete what it holds. Move its contents out, or build into another output directory. ${file}`
|
|
7278
7378
|
);
|
|
7279
7379
|
}
|
|
7280
7380
|
}
|
|
7281
|
-
async function isEarlierBuild(pluginDir) {
|
|
7282
|
-
return fileExists(getPluginManifestPath(pluginDir));
|
|
7283
|
-
}
|
|
7284
|
-
async function holdsContentNoBuildMade(pluginDir) {
|
|
7285
|
-
if (await isEarlierBuild(pluginDir)) return false;
|
|
7286
|
-
return !await isDirectoryEmpty(pluginDir);
|
|
7287
|
-
}
|
|
7288
|
-
async function clearEarlierBuild(pluginDir) {
|
|
7289
|
-
if (await isEarlierBuild(pluginDir)) await remove(pluginDir);
|
|
7290
|
-
}
|
|
7291
7381
|
async function readPluginSkillMetadata(skillPath) {
|
|
7292
|
-
const metadataPath =
|
|
7382
|
+
const metadataPath = path24.join(skillPath, STANDARD_FILES.METADATA_YAML);
|
|
7293
7383
|
if (!await fileExists(metadataPath)) {
|
|
7294
7384
|
return null;
|
|
7295
7385
|
}
|
|
@@ -7333,28 +7423,28 @@ This skill is automatically available when installed.
|
|
|
7333
7423
|
}
|
|
7334
7424
|
async function writeSkillFiles(skillPath, pluginSkillDir, skillMdContent) {
|
|
7335
7425
|
await ensureDir(pluginSkillDir);
|
|
7336
|
-
await writeFile(
|
|
7426
|
+
await writeFile(path24.join(pluginSkillDir, STANDARD_FILES.SKILL_MD), skillMdContent);
|
|
7337
7427
|
verbose(` Copied ${STANDARD_FILES.SKILL_MD}`);
|
|
7338
7428
|
for (const fileName of SKILL_CONTENT_FILES) {
|
|
7339
7429
|
if (fileName === STANDARD_FILES.SKILL_MD) continue;
|
|
7340
|
-
const sourcePath =
|
|
7430
|
+
const sourcePath = path24.join(skillPath, fileName);
|
|
7341
7431
|
if (await fileExists(sourcePath)) {
|
|
7342
7432
|
const content = await readFile(sourcePath);
|
|
7343
|
-
await writeFile(
|
|
7433
|
+
await writeFile(path24.join(pluginSkillDir, fileName), content);
|
|
7344
7434
|
verbose(` Copied ${fileName}`);
|
|
7345
7435
|
}
|
|
7346
7436
|
}
|
|
7347
7437
|
for (const dirName of SKILL_CONTENT_DIRS) {
|
|
7348
|
-
const sourceDir2 =
|
|
7438
|
+
const sourceDir2 = path24.join(skillPath, dirName);
|
|
7349
7439
|
if (await fileExists(sourceDir2)) {
|
|
7350
|
-
await copy(sourceDir2,
|
|
7440
|
+
await copy(sourceDir2, path24.join(pluginSkillDir, dirName));
|
|
7351
7441
|
verbose(` Copied ${dirName}/`);
|
|
7352
7442
|
}
|
|
7353
7443
|
}
|
|
7354
7444
|
}
|
|
7355
7445
|
async function readSkillMdToBuild(skillPath) {
|
|
7356
|
-
const dirBasename =
|
|
7357
|
-
const skillMdPath =
|
|
7446
|
+
const dirBasename = path24.basename(skillPath);
|
|
7447
|
+
const skillMdPath = path24.join(skillPath, STANDARD_FILES.SKILL_MD);
|
|
7358
7448
|
if (!await fileExists(skillMdPath)) {
|
|
7359
7449
|
throw new Error(
|
|
7360
7450
|
`Skill '${dirBasename}' is missing required ${STANDARD_FILES.SKILL_MD} file. Expected at: ${skillMdPath}`
|
|
@@ -7373,7 +7463,7 @@ async function compileSkillPlugin(options) {
|
|
|
7373
7463
|
const { skillPath, outputDir, skillName: overrideName } = options;
|
|
7374
7464
|
const { skillMdContent, frontmatter } = await readSkillMdToBuild(skillPath);
|
|
7375
7465
|
const skillName = overrideName ?? sanitizeSkillName(frontmatter.name);
|
|
7376
|
-
const pluginDir =
|
|
7466
|
+
const pluginDir = path24.join(outputDir, skillName);
|
|
7377
7467
|
await assertClearable(pluginDir, skillPath, skillName);
|
|
7378
7468
|
verbose(`Compiling skill plugin: ${skillName} from ${skillPath}`);
|
|
7379
7469
|
const metadata = await readPluginSkillMetadata(skillPath);
|
|
@@ -7390,11 +7480,11 @@ async function compileSkillPlugin(options) {
|
|
|
7390
7480
|
await writeContentHash(pluginDir, await computeSkillFolderHash(skillPath), getPluginManifestPath);
|
|
7391
7481
|
await writeSkillFiles(
|
|
7392
7482
|
skillPath,
|
|
7393
|
-
|
|
7483
|
+
path24.join(pluginDir, STANDARD_DIRS.SKILLS, skillName),
|
|
7394
7484
|
skillMdContent
|
|
7395
7485
|
);
|
|
7396
7486
|
const readme = generateReadme(skillName, frontmatter);
|
|
7397
|
-
await writeFile(
|
|
7487
|
+
await writeFile(path24.join(pluginDir, STANDARD_FILES.README_MD), readme);
|
|
7398
7488
|
verbose(" Generated README.md");
|
|
7399
7489
|
const manifest = manifestAt(
|
|
7400
7490
|
versionAfterRebuild(earlierBuild, await computeShippedHash(pluginDir))
|
|
@@ -7412,7 +7502,7 @@ async function compileAllSkillPlugins(skillsDir2, outputDir) {
|
|
|
7412
7502
|
const failed = [];
|
|
7413
7503
|
const skillMdFiles = await glob(`**/${STANDARD_FILES.SKILL_MD}`, skillsDir2);
|
|
7414
7504
|
for (const skillMdFile of skillMdFiles) {
|
|
7415
|
-
const skillPath =
|
|
7505
|
+
const skillPath = path24.join(skillsDir2, path24.dirname(skillMdFile));
|
|
7416
7506
|
try {
|
|
7417
7507
|
const result = await compileSkillPlugin({
|
|
7418
7508
|
skillPath,
|
|
@@ -7422,7 +7512,7 @@ async function compileAllSkillPlugins(skillsDir2, outputDir) {
|
|
|
7422
7512
|
log(` [OK] ${result.skillName}`);
|
|
7423
7513
|
} catch (error) {
|
|
7424
7514
|
const errorMessage = getErrorMessage(error);
|
|
7425
|
-
const dirBasename =
|
|
7515
|
+
const dirBasename = path24.basename(skillPath);
|
|
7426
7516
|
failed.push(dirBasename);
|
|
7427
7517
|
warn(`Failed to compile skill from '${dirBasename}': ${errorMessage}`);
|
|
7428
7518
|
}
|
|
@@ -7438,16 +7528,24 @@ Compiled ${plural(results.length, "skill plugin")}:`);
|
|
|
7438
7528
|
}
|
|
7439
7529
|
|
|
7440
7530
|
// src/cli/lib/skills/local-skill-loader.ts
|
|
7441
|
-
import
|
|
7442
|
-
|
|
7443
|
-
const
|
|
7531
|
+
import path25 from "path";
|
|
7532
|
+
function copiedInSkillsAt(root) {
|
|
7533
|
+
const scope = isHomeDirectory(root) ? "global" : "project";
|
|
7534
|
+
const provider = providerInUse(root);
|
|
7535
|
+
return {
|
|
7536
|
+
dir: skillsDir(provider, scope, root),
|
|
7537
|
+
pathPrefix: skillsPathPrefix(provider, scope, root)
|
|
7538
|
+
};
|
|
7539
|
+
}
|
|
7540
|
+
async function discoverLocalSkills(root) {
|
|
7541
|
+
const { dir: localSkillsPath, pathPrefix } = copiedInSkillsAt(root);
|
|
7444
7542
|
if (!await directoryExists2(localSkillsPath)) {
|
|
7445
7543
|
verbose(`Local skills directory not found: ${localSkillsPath}`);
|
|
7446
7544
|
return null;
|
|
7447
7545
|
}
|
|
7448
7546
|
const skillDirs = await listDirectories(localSkillsPath);
|
|
7449
7547
|
const extracted = await Promise.all(
|
|
7450
|
-
skillDirs.map((skillDirName) => extractLocalSkill(localSkillsPath, skillDirName))
|
|
7548
|
+
skillDirs.map((skillDirName) => extractLocalSkill(localSkillsPath, pathPrefix, skillDirName))
|
|
7451
7549
|
);
|
|
7452
7550
|
const skills = extracted.filter((skill) => skill !== null);
|
|
7453
7551
|
verbose(`Discovered ${plural(skills.length, "local skill")} from ${localSkillsPath}`);
|
|
@@ -7456,10 +7554,10 @@ async function discoverLocalSkills(projectDir) {
|
|
|
7456
7554
|
localSkillsPath
|
|
7457
7555
|
};
|
|
7458
7556
|
}
|
|
7459
|
-
async function extractLocalSkill(localSkillsPath, skillDirName) {
|
|
7460
|
-
const skillDir =
|
|
7461
|
-
const metadataPath =
|
|
7462
|
-
const skillMdPath =
|
|
7557
|
+
async function extractLocalSkill(localSkillsPath, pathPrefix, skillDirName) {
|
|
7558
|
+
const skillDir = path25.join(localSkillsPath, skillDirName);
|
|
7559
|
+
const metadataPath = path25.join(skillDir, STANDARD_FILES.METADATA_YAML);
|
|
7560
|
+
const skillMdPath = path25.join(skillDir, STANDARD_FILES.SKILL_MD);
|
|
7463
7561
|
if (!await fileExists(metadataPath)) {
|
|
7464
7562
|
verbose(`Skipping local skill '${skillDirName}': No metadata.yaml found`);
|
|
7465
7563
|
return null;
|
|
@@ -7488,8 +7586,8 @@ async function extractLocalSkill(localSkillsPath, skillDirName) {
|
|
|
7488
7586
|
verbose(`Skipping local skill '${skillDirName}': invalid SKILL.md frontmatter`);
|
|
7489
7587
|
return null;
|
|
7490
7588
|
}
|
|
7491
|
-
const relativePath = `${
|
|
7492
|
-
const absolutePath =
|
|
7589
|
+
const relativePath = `${pathPrefix}/${skillDirName}/`;
|
|
7590
|
+
const absolutePath = path25.join(localSkillsPath, skillDirName) + path25.sep;
|
|
7493
7591
|
const skillId = frontmatter.name;
|
|
7494
7592
|
const extracted = {
|
|
7495
7593
|
id: skillId,
|
|
@@ -7512,7 +7610,7 @@ async function extractLocalSkill(localSkillsPath, skillDirName) {
|
|
|
7512
7610
|
}
|
|
7513
7611
|
|
|
7514
7612
|
// src/cli/lib/skills/unresolved-skill-entries.ts
|
|
7515
|
-
import
|
|
7613
|
+
import path26 from "path";
|
|
7516
7614
|
async function findUnusableSavedSkillMetadata(savedSkills, projectDir) {
|
|
7517
7615
|
const verdicts = await Promise.all(
|
|
7518
7616
|
savedSkills.map((saved) => unusableMetadataOf(saved, projectDir))
|
|
@@ -7531,11 +7629,11 @@ function claimsLocalCopy(saved) {
|
|
|
7531
7629
|
}
|
|
7532
7630
|
function installedMetadataPath(saved, projectDir) {
|
|
7533
7631
|
const { skillsDir: skillsDir2 } = resolveInstallPaths(projectDir, saved.scope);
|
|
7534
|
-
return
|
|
7632
|
+
return path26.join(skillsDir2, saved.id, STANDARD_FILES.METADATA_YAML);
|
|
7535
7633
|
}
|
|
7536
7634
|
|
|
7537
7635
|
// src/cli/lib/skills/local-skill-mover.ts
|
|
7538
|
-
import
|
|
7636
|
+
import path27 from "path";
|
|
7539
7637
|
var THE_DIRECTORY_ITSELF = ".";
|
|
7540
7638
|
function validateSkillId(skillId) {
|
|
7541
7639
|
return !(skillId.length === 0 || skillId === THE_DIRECTORY_ITSELF || skillId.includes("\0") || skillId.includes("..") || skillId.includes("/") || skillId.includes("\\"));
|
|
@@ -7545,8 +7643,8 @@ async function deleteLocalSkill(projectDir, skillId, scope = "project") {
|
|
|
7545
7643
|
warn(`Invalid skill ID for deletion: '${skillId}'`);
|
|
7546
7644
|
return;
|
|
7547
7645
|
}
|
|
7548
|
-
const skillsDir2 =
|
|
7549
|
-
const skillPath =
|
|
7646
|
+
const skillsDir2 = path27.resolve(resolveInstallPaths(projectDir, scope).skillsDir);
|
|
7647
|
+
const skillPath = path27.resolve(skillsDir2, skillId);
|
|
7550
7648
|
if (!isPathWithin(skillPath, skillsDir2)) {
|
|
7551
7649
|
warn(`Skill ID '${skillId}' resolves outside the skills directory.`);
|
|
7552
7650
|
return;
|
|
@@ -7564,10 +7662,10 @@ async function migrateLocalSkillScope(skillId, fromScope, projectDir) {
|
|
|
7564
7662
|
return;
|
|
7565
7663
|
}
|
|
7566
7664
|
const toScope = fromScope === "global" ? "project" : "global";
|
|
7567
|
-
const fromSkillsDir =
|
|
7568
|
-
const toSkillsDir =
|
|
7569
|
-
const fromPath =
|
|
7570
|
-
const toPath =
|
|
7665
|
+
const fromSkillsDir = path27.resolve(resolveInstallPaths(projectDir, fromScope).skillsDir);
|
|
7666
|
+
const toSkillsDir = path27.resolve(resolveInstallPaths(projectDir, toScope).skillsDir);
|
|
7667
|
+
const fromPath = path27.resolve(fromSkillsDir, skillId);
|
|
7668
|
+
const toPath = path27.resolve(toSkillsDir, skillId);
|
|
7571
7669
|
if (!isPathWithin(fromPath, fromSkillsDir)) {
|
|
7572
7670
|
warn(`Skill ID '${skillId}' resolves outside the source skills directory.`);
|
|
7573
7671
|
return;
|
|
@@ -7594,7 +7692,7 @@ async function migrateLocalSkillScope(skillId, fromScope, projectDir) {
|
|
|
7594
7692
|
|
|
7595
7693
|
// src/cli/lib/matrix/matrix-loader.ts
|
|
7596
7694
|
import { parse as parseYaml5 } from "yaml";
|
|
7597
|
-
import
|
|
7695
|
+
import path28 from "path";
|
|
7598
7696
|
async function loadSkillCategories(configPath) {
|
|
7599
7697
|
const data = await loadConfig(configPath, skillCategoriesFileSchema);
|
|
7600
7698
|
if (!data) {
|
|
@@ -7630,13 +7728,13 @@ async function extractAllSkills(skillsDir2) {
|
|
|
7630
7728
|
return skills;
|
|
7631
7729
|
}
|
|
7632
7730
|
async function extractSkill(skillsDir2, metadataFile) {
|
|
7633
|
-
const skillDir =
|
|
7634
|
-
const skillMdPath =
|
|
7731
|
+
const skillDir = path28.dirname(metadataFile);
|
|
7732
|
+
const skillMdPath = path28.join(skillsDir2, skillDir, STANDARD_FILES.SKILL_MD);
|
|
7635
7733
|
if (!await fileExists(skillMdPath)) {
|
|
7636
7734
|
verbose(`Skipping ${metadataFile}: No ${STANDARD_FILES.SKILL_MD} found`);
|
|
7637
7735
|
return null;
|
|
7638
7736
|
}
|
|
7639
|
-
const metadata = await readMatrixMetadataOrWarn(metadataFile,
|
|
7737
|
+
const metadata = await readMatrixMetadataOrWarn(metadataFile, path28.join(skillsDir2, metadataFile));
|
|
7640
7738
|
if (!metadata) return null;
|
|
7641
7739
|
const frontmatter = parseFrontmatterOrWarn(skillDir, skillMdPath, await readFile(skillMdPath));
|
|
7642
7740
|
if (!frontmatter) return null;
|
|
@@ -7689,7 +7787,7 @@ function parseFrontmatterOrWarn(skillDir, skillMdPath, skillMdContent) {
|
|
|
7689
7787
|
const unreadable = unreadableFrontmatter(skillMdContent);
|
|
7690
7788
|
if (unreadable !== void 0) {
|
|
7691
7789
|
warn(
|
|
7692
|
-
`Skipping '${
|
|
7790
|
+
`Skipping '${path28.join(skillDir, STANDARD_FILES.SKILL_MD)}': unparseable ${STANDARD_FILES.SKILL_MD} frontmatter at ${skillMdPath} \u2014 ${unreadable}`
|
|
7693
7791
|
);
|
|
7694
7792
|
}
|
|
7695
7793
|
return null;
|
|
@@ -9800,7 +9898,7 @@ async function loadAndMergeFromBasePath(basePath, source) {
|
|
|
9800
9898
|
const skillsDirRelPath = sourceProjectConfig?.skillsDir ?? SKILLS_DIR_PATH;
|
|
9801
9899
|
const stacksRelFile = sourceProjectConfig?.stacksFile;
|
|
9802
9900
|
const { categories, sourceRules } = await loadSourceTaxonomy(basePath);
|
|
9803
|
-
const skillsDir2 =
|
|
9901
|
+
const skillsDir2 = path29.join(basePath, skillsDirRelPath);
|
|
9804
9902
|
verbose(`Skills from source: ${skillsDir2}`);
|
|
9805
9903
|
const skills = await extractAllSkills(skillsDir2);
|
|
9806
9904
|
await refuseCatalogueCollisions(basePath, source, skills);
|
|
@@ -9823,7 +9921,7 @@ async function loadSourceTaxonomy(basePath) {
|
|
|
9823
9921
|
return { categories, sourceRules };
|
|
9824
9922
|
}
|
|
9825
9923
|
async function loadSourceCategories(basePath) {
|
|
9826
|
-
const categoriesPath =
|
|
9924
|
+
const categoriesPath = path29.join(basePath, SKILL_CATEGORIES_PATH);
|
|
9827
9925
|
if (!await fileExists(categoriesPath)) return void 0;
|
|
9828
9926
|
const categories = await loadSkillCategories(categoriesPath);
|
|
9829
9927
|
verbose(
|
|
@@ -9832,7 +9930,7 @@ async function loadSourceCategories(basePath) {
|
|
|
9832
9930
|
return categories;
|
|
9833
9931
|
}
|
|
9834
9932
|
async function loadSourceRules(basePath) {
|
|
9835
|
-
const rulesPath =
|
|
9933
|
+
const rulesPath = path29.join(basePath, SKILL_RULES_PATH);
|
|
9836
9934
|
if (!await fileExists(rulesPath)) return void 0;
|
|
9837
9935
|
const rules = await loadSkillRules(rulesPath);
|
|
9838
9936
|
verbose(`Loaded source rules: ${rulesPath}`);
|
|
@@ -9847,11 +9945,11 @@ async function refuseCatalogueCollisions(basePath, source, skills) {
|
|
|
9847
9945
|
throw new Error(catalogueCollisionError(collidingIds, source));
|
|
9848
9946
|
}
|
|
9849
9947
|
function catalogueCollisionError(collidingIds, source) {
|
|
9850
|
-
const
|
|
9851
|
-
const unlisted = collidingIds.length -
|
|
9948
|
+
const listed2 = collidingIds.slice(0, MAX_REPORTED_COLLISIONS).map((id) => ` ${id}`);
|
|
9949
|
+
const unlisted = collidingIds.length - listed2.length;
|
|
9852
9950
|
return [
|
|
9853
9951
|
`Marketplace '${source}' ships ${collidingIds.length} skill id(s) the public catalogue already owns:`,
|
|
9854
|
-
...
|
|
9952
|
+
...listed2,
|
|
9855
9953
|
...unlisted > 0 ? [` ... and ${unlisted} more`] : [],
|
|
9856
9954
|
`A skill id is the directory the skill installs into, so these would shadow the public catalogue's own skills. Every id must carry its marketplace's name as a namespace \u2014 '<marketplace>-<id>'. Rename each skill and the 'name' in its SKILL.md, then re-run 'build marketplace', which refuses the same ids before they are published.`
|
|
9857
9955
|
].join("\n");
|
|
@@ -9940,7 +10038,7 @@ function declaresCategory(matrix2, category) {
|
|
|
9940
10038
|
return category !== LOCAL_PSEUDO_CATEGORY && matrix2.categories[category] !== void 0;
|
|
9941
10039
|
}
|
|
9942
10040
|
function undeclaredCategoryRefusal(metadata, category) {
|
|
9943
|
-
const metadataPath =
|
|
10041
|
+
const metadataPath = path29.join(metadata.path, STANDARD_FILES.METADATA_YAML);
|
|
9944
10042
|
return `Skipping local skill '${metadata.id}': ${METADATA_KEYS.CATEGORY} '${category}' is not one this installation declares, so the skill belongs in no grid tab and can be given to no sub-agent. Set ${METADATA_KEYS.CATEGORY} in ${metadataPath} to a category that already exists \u2014 a skill is placed in the taxonomy, it does not extend it.`;
|
|
9945
10043
|
}
|
|
9946
10044
|
function mergeLocalSkillsIntoMatrix(matrix2, localResult) {
|
|
@@ -10076,15 +10174,14 @@ export {
|
|
|
10076
10174
|
skippedUnknownAgents,
|
|
10077
10175
|
carriedSkillsWritten,
|
|
10078
10176
|
SHARED_CONFIG_APPLY,
|
|
10079
|
-
|
|
10080
|
-
projectCopyMovedToGlobal,
|
|
10081
|
-
registeredProjectsRewritten,
|
|
10177
|
+
registeredProjectsRecompiled,
|
|
10082
10178
|
sharedConfigNeedsTerminal,
|
|
10083
10179
|
nothingInstalledToApplyTo,
|
|
10084
10180
|
uninstallNeedsTerminal,
|
|
10085
10181
|
addMarketplaceInTheEditor,
|
|
10086
10182
|
SHARED_CONFIG_ARRIVALS,
|
|
10087
10183
|
keptAsInstalledGlobally,
|
|
10184
|
+
subAgentChanged,
|
|
10088
10185
|
addedToGlobalSubAgents,
|
|
10089
10186
|
authoredHereKept,
|
|
10090
10187
|
unplaceableKept,
|
|
@@ -10094,11 +10191,10 @@ export {
|
|
|
10094
10191
|
uninstallSkillMetadataUnreadable,
|
|
10095
10192
|
recreateConfigFrom,
|
|
10096
10193
|
providerArgument,
|
|
10194
|
+
configUnreadableError,
|
|
10097
10195
|
registeredProjectsUpdateFailed,
|
|
10098
10196
|
unmarkedAgentsKept,
|
|
10099
|
-
|
|
10100
|
-
localSkillsRemoval,
|
|
10101
|
-
compiledAgentsRemoval,
|
|
10197
|
+
configFileRemoved,
|
|
10102
10198
|
scopeNoun,
|
|
10103
10199
|
scopeLabel,
|
|
10104
10200
|
layoutIsCurrent,
|
|
@@ -10106,6 +10202,7 @@ export {
|
|
|
10106
10202
|
GlobalPairWriteViolation,
|
|
10107
10203
|
withGateToken,
|
|
10108
10204
|
assertGateToken,
|
|
10205
|
+
isPathWithin,
|
|
10109
10206
|
readFile,
|
|
10110
10207
|
readFileSafe,
|
|
10111
10208
|
readFileOptional,
|
|
@@ -10135,11 +10232,14 @@ export {
|
|
|
10135
10232
|
validateSkillMetadata,
|
|
10136
10233
|
splitMetadataValidationIssues,
|
|
10137
10234
|
ConfigDefaultExportError,
|
|
10235
|
+
NO_VALID_DEFAULT_EXPORT,
|
|
10236
|
+
configLoadFailure,
|
|
10138
10237
|
loadConfig,
|
|
10139
10238
|
getProjectConfigPath,
|
|
10140
10239
|
getInstalledConfigPath,
|
|
10141
10240
|
resolveInstallPaths,
|
|
10142
10241
|
providerToNameAt,
|
|
10242
|
+
initProviderToNameAt,
|
|
10143
10243
|
isHomeDirectory,
|
|
10144
10244
|
SOURCE_ENV_VAR,
|
|
10145
10245
|
readSourceRepoConfig,
|
|
@@ -10150,11 +10250,8 @@ export {
|
|
|
10150
10250
|
resolvePrimarySourceEntry,
|
|
10151
10251
|
MarketplaceRefusedError,
|
|
10152
10252
|
isLocalSource,
|
|
10153
|
-
typedEntries,
|
|
10154
|
-
typedKeys,
|
|
10155
|
-
typedFromEntries,
|
|
10156
|
-
typedValues,
|
|
10157
10253
|
normalizeStackRecord,
|
|
10254
|
+
loadStackById,
|
|
10158
10255
|
defaultUsageGuidance,
|
|
10159
10256
|
resolveAgentConfigToSkills,
|
|
10160
10257
|
getStackSkillIds,
|
|
@@ -10186,8 +10283,8 @@ export {
|
|
|
10186
10283
|
generateConfigSource,
|
|
10187
10284
|
refuseUnwritableStack,
|
|
10188
10285
|
generateBlankGlobalConfigSource,
|
|
10189
|
-
typedEntries2,
|
|
10190
|
-
typedKeys2,
|
|
10286
|
+
typedEntries2 as typedEntries,
|
|
10287
|
+
typedKeys2 as typedKeys,
|
|
10191
10288
|
isScopePairCompatible,
|
|
10192
10289
|
splitConfigByScope,
|
|
10193
10290
|
seedToInstallSelection,
|
|
@@ -10201,9 +10298,12 @@ export {
|
|
|
10201
10298
|
loadSkillsFromDir,
|
|
10202
10299
|
getCurrentDate,
|
|
10203
10300
|
computeStringHash,
|
|
10204
|
-
|
|
10301
|
+
computeShippedHash,
|
|
10302
|
+
readEarlierBuild,
|
|
10303
|
+
versionAfterRebuild,
|
|
10205
10304
|
writeContentHash,
|
|
10206
10305
|
readForkedFromMetadata,
|
|
10306
|
+
readLocalSkillMetadata,
|
|
10207
10307
|
validateSkillPath,
|
|
10208
10308
|
copySkillsToLocalFlattened,
|
|
10209
10309
|
getUserPluginsDir,
|
|
@@ -10216,6 +10316,8 @@ export {
|
|
|
10216
10316
|
writePluginManifest,
|
|
10217
10317
|
buildMarketplacePluginRef,
|
|
10218
10318
|
parseMarketplacePluginRef,
|
|
10319
|
+
holdsContentNoBuildMade,
|
|
10320
|
+
clearEarlierBuild,
|
|
10219
10321
|
getInstallationInfo,
|
|
10220
10322
|
getInstallationsByProvider,
|
|
10221
10323
|
formatInstallationDisplay,
|
|
@@ -10248,6 +10350,8 @@ export {
|
|
|
10248
10350
|
validateSkillIdNamespace,
|
|
10249
10351
|
writeMarketplace,
|
|
10250
10352
|
getMarketplaceStats,
|
|
10353
|
+
MarketplaceUnreachableError,
|
|
10354
|
+
askingEachMarketplaceItself,
|
|
10251
10355
|
MarketplaceNameRefusedError,
|
|
10252
10356
|
fetchMarketplace,
|
|
10253
10357
|
isLocalOnlySkill,
|
|
@@ -10271,4 +10375,4 @@ export {
|
|
|
10271
10375
|
executeMigration,
|
|
10272
10376
|
keepsGlobalInstall
|
|
10273
10377
|
};
|
|
10274
|
-
//# sourceMappingURL=chunk-
|
|
10378
|
+
//# sourceMappingURL=chunk-VILFCMRN.js.map
|