agents-inc 0.165.0 → 0.167.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 +23 -0
- package/dist/{chunk-B5UUHBAM.js → chunk-25MPBIK3.js} +3 -3
- package/dist/{chunk-VPJUCVU7.js → chunk-2VUYFTUB.js} +6 -6
- package/dist/{chunk-BGU25XAY.js → chunk-4NDBUJHK.js} +8 -8
- package/dist/{chunk-5M3PQNXI.js → chunk-6L75SQZU.js} +2 -2
- package/dist/{chunk-YNOOZFIB.js → chunk-6LF4CQBY.js} +2 -2
- package/dist/{chunk-UBSSIIWD.js → chunk-7JNJ52CD.js} +4 -4
- package/dist/{chunk-IM45LLQX.js → chunk-A4KDXNOT.js} +47 -137
- package/dist/chunk-A4KDXNOT.js.map +1 -0
- package/dist/{chunk-6SW6SB7H.js → chunk-DAIEQJIF.js} +3 -3
- package/dist/{chunk-AQXKAPCD.js → chunk-ENGYJCTF.js} +1 -3
- package/dist/{chunk-AQXKAPCD.js.map → chunk-ENGYJCTF.js.map} +1 -1
- package/dist/{chunk-6AIZPSEI.js → chunk-G4JK7WVO.js} +15 -16
- package/dist/chunk-G4JK7WVO.js.map +1 -0
- package/dist/{chunk-WTANOSXK.js → chunk-G6UREQ4V.js} +9 -9
- package/dist/chunk-G6UREQ4V.js.map +1 -0
- package/dist/{chunk-V5CWACR5.js → chunk-GE3WKJ6Q.js} +4 -4
- package/dist/{chunk-V5CWACR5.js.map → chunk-GE3WKJ6Q.js.map} +1 -1
- package/dist/{chunk-JV4TKXEN.js → chunk-HHIYT3PI.js} +4 -4
- package/dist/{chunk-WIFIAQZU.js → chunk-HWEKHVLE.js} +6 -6
- package/dist/{chunk-5P26XBZO.js → chunk-JQRJQ4SS.js} +3 -3
- package/dist/{chunk-Y5SNGMB7.js → chunk-LFWLEDUG.js} +6 -6
- package/dist/{chunk-TRTVOVHR.js → chunk-MAWNVT2C.js} +4 -4
- package/dist/{chunk-57KU6SPH.js → chunk-MPTNC32T.js} +3 -3
- package/dist/{chunk-MBUGQI2M.js → chunk-NBXXFIIW.js} +3 -3
- package/dist/{chunk-42TNV2TK.js → chunk-PMJWD27C.js} +3 -3
- package/dist/{chunk-X2KUI7V3.js → chunk-PNB3524H.js} +5 -5
- package/dist/{chunk-IVNKU4DM.js → chunk-PXWG7KFO.js} +2 -2
- package/dist/chunk-PXWG7KFO.js.map +1 -0
- package/dist/{chunk-LXXGZAD3.js → chunk-QHDPLLK6.js} +3 -3
- package/dist/{chunk-TV5Y53R2.js → chunk-RAHSOJQ2.js} +2 -2
- package/dist/{chunk-CTUJO23Z.js → chunk-RZDXDMT6.js} +2 -2
- package/dist/{chunk-PSX7CT6V.js → chunk-SAYZWCH6.js} +2 -2
- package/dist/{chunk-MWDY76MT.js → chunk-SCOQ34YM.js} +2 -2
- package/dist/{chunk-4C7GL4F7.js → chunk-SXVHSOTH.js} +4 -4
- package/dist/{chunk-E6CHHXGY.js → chunk-T6UWJAB3.js} +2 -2
- package/dist/{chunk-F2ZWFWTP.js → chunk-TODCQFRB.js} +2 -2
- package/dist/{chunk-CEBDGZID.js → chunk-TTY6DPJN.js} +3 -3
- package/dist/{chunk-CBMAO6OP.js → chunk-TZ2YJJKK.js} +5 -5
- package/dist/{chunk-WSGX4IWC.js → chunk-V3I7VQ7N.js} +4 -4
- package/dist/{chunk-GKPW33FP.js → chunk-V5WXIM2F.js} +2 -2
- package/dist/{chunk-6CY6PW5X.js → chunk-VAPTVR3J.js} +3 -3
- package/dist/{chunk-CK5RM3DJ.js → chunk-WVUDLKIO.js} +2 -2
- package/dist/{chunk-HR4YDSJK.js → chunk-WWIFNPJG.js} +12 -12
- package/dist/{chunk-P3KJCYSR.js → chunk-XZEVWPX6.js} +7 -7
- package/dist/{chunk-AAWZED5M.js → chunk-Y3VIRVVE.js} +10 -58
- package/dist/chunk-Y3VIRVVE.js.map +1 -0
- package/dist/{chunk-XATIKM3P.js → chunk-Y47EV74W.js} +7 -7
- package/dist/{chunk-UR3RRTPO.js → chunk-ZR4YPKXQ.js} +4 -4
- package/dist/{chunk-UCORXS4D.js → chunk-ZXKBERQU.js} +2 -2
- package/dist/commands/build/marketplace.js +6 -6
- package/dist/commands/build/plugins.js +8 -8
- package/dist/commands/compile.js +14 -15
- package/dist/commands/compile.js.map +1 -1
- package/dist/commands/doctor.js +59 -156
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/edit.js +40 -41
- package/dist/commands/edit.js.map +1 -1
- package/dist/commands/eject.js +12 -13
- package/dist/commands/eject.js.map +1 -1
- package/dist/commands/init.js +39 -39
- package/dist/commands/list.js +9 -9
- package/dist/commands/new/marketplace.js +6 -6
- package/dist/commands/search.js +11 -11
- package/dist/commands/share.js +11 -12
- package/dist/commands/share.js.map +1 -1
- package/dist/commands/uninstall.js +39 -69
- package/dist/commands/uninstall.js.map +1 -1
- package/dist/commands/update.js +8 -9
- package/dist/commands/update.js.map +1 -1
- package/dist/components/common/removal-plan-confirm.js +2 -2
- package/dist/components/common/select-list.js +2 -2
- package/dist/components/wizard/category-grid.js +4 -4
- package/dist/components/wizard/checkbox-grid.js +4 -4
- package/dist/components/wizard/domain-selection.js +9 -9
- package/dist/components/wizard/run-wizard-session.js +26 -26
- package/dist/components/wizard/scroll-affordance.js +2 -2
- package/dist/components/wizard/skill-agent-summary.js +5 -5
- package/dist/components/wizard/source-grid.js +5 -5
- package/dist/components/wizard/stack-selection.js +7 -7
- package/dist/components/wizard/step-agents.js +8 -8
- package/dist/components/wizard/step-build.js +7 -7
- package/dist/components/wizard/step-confirm.js +9 -9
- package/dist/components/wizard/step-sources.js +8 -8
- package/dist/components/wizard/step-stack.js +8 -8
- package/dist/components/wizard/summary-panel.js +8 -8
- package/dist/components/wizard/toast.js +2 -2
- package/dist/components/wizard/wizard-layout.js +12 -12
- package/dist/components/wizard/wizard-tabs.js +2 -2
- package/dist/components/wizard/wizard.js +25 -25
- package/dist/hooks/init.js +50 -40
- package/dist/hooks/init.js.map +1 -1
- package/dist/load-agent-defs-3C27ENC7.js +14 -0
- package/dist/recompile-project-agents-DGNBCU3N.js +18 -0
- package/dist/{source-loader-RWZAYJ7E.js → source-loader-7KZ3MD5O.js} +4 -4
- package/dist/stores/wizard-store.js +4 -4
- package/package.json +1 -1
- package/src/schemas/project-config.schema.json +1 -1
- package/src/schemas/project-source-config.schema.json +1 -1
- package/dist/chunk-6AIZPSEI.js.map +0 -1
- package/dist/chunk-AAWZED5M.js.map +0 -1
- package/dist/chunk-IM45LLQX.js.map +0 -1
- package/dist/chunk-IVNKU4DM.js.map +0 -1
- package/dist/chunk-WTANOSXK.js.map +0 -1
- package/dist/load-agent-defs-JHLE6MAE.js +0 -14
- package/dist/recompile-project-agents-ZPP5NOLZ.js +0 -18
- /package/dist/{chunk-B5UUHBAM.js.map → chunk-25MPBIK3.js.map} +0 -0
- /package/dist/{chunk-VPJUCVU7.js.map → chunk-2VUYFTUB.js.map} +0 -0
- /package/dist/{chunk-BGU25XAY.js.map → chunk-4NDBUJHK.js.map} +0 -0
- /package/dist/{chunk-5M3PQNXI.js.map → chunk-6L75SQZU.js.map} +0 -0
- /package/dist/{chunk-YNOOZFIB.js.map → chunk-6LF4CQBY.js.map} +0 -0
- /package/dist/{chunk-UBSSIIWD.js.map → chunk-7JNJ52CD.js.map} +0 -0
- /package/dist/{chunk-6SW6SB7H.js.map → chunk-DAIEQJIF.js.map} +0 -0
- /package/dist/{chunk-JV4TKXEN.js.map → chunk-HHIYT3PI.js.map} +0 -0
- /package/dist/{chunk-WIFIAQZU.js.map → chunk-HWEKHVLE.js.map} +0 -0
- /package/dist/{chunk-5P26XBZO.js.map → chunk-JQRJQ4SS.js.map} +0 -0
- /package/dist/{chunk-Y5SNGMB7.js.map → chunk-LFWLEDUG.js.map} +0 -0
- /package/dist/{chunk-TRTVOVHR.js.map → chunk-MAWNVT2C.js.map} +0 -0
- /package/dist/{chunk-57KU6SPH.js.map → chunk-MPTNC32T.js.map} +0 -0
- /package/dist/{chunk-MBUGQI2M.js.map → chunk-NBXXFIIW.js.map} +0 -0
- /package/dist/{chunk-42TNV2TK.js.map → chunk-PMJWD27C.js.map} +0 -0
- /package/dist/{chunk-X2KUI7V3.js.map → chunk-PNB3524H.js.map} +0 -0
- /package/dist/{chunk-LXXGZAD3.js.map → chunk-QHDPLLK6.js.map} +0 -0
- /package/dist/{chunk-TV5Y53R2.js.map → chunk-RAHSOJQ2.js.map} +0 -0
- /package/dist/{chunk-CTUJO23Z.js.map → chunk-RZDXDMT6.js.map} +0 -0
- /package/dist/{chunk-PSX7CT6V.js.map → chunk-SAYZWCH6.js.map} +0 -0
- /package/dist/{chunk-MWDY76MT.js.map → chunk-SCOQ34YM.js.map} +0 -0
- /package/dist/{chunk-4C7GL4F7.js.map → chunk-SXVHSOTH.js.map} +0 -0
- /package/dist/{chunk-E6CHHXGY.js.map → chunk-T6UWJAB3.js.map} +0 -0
- /package/dist/{chunk-F2ZWFWTP.js.map → chunk-TODCQFRB.js.map} +0 -0
- /package/dist/{chunk-CEBDGZID.js.map → chunk-TTY6DPJN.js.map} +0 -0
- /package/dist/{chunk-CBMAO6OP.js.map → chunk-TZ2YJJKK.js.map} +0 -0
- /package/dist/{chunk-WSGX4IWC.js.map → chunk-V3I7VQ7N.js.map} +0 -0
- /package/dist/{chunk-GKPW33FP.js.map → chunk-V5WXIM2F.js.map} +0 -0
- /package/dist/{chunk-6CY6PW5X.js.map → chunk-VAPTVR3J.js.map} +0 -0
- /package/dist/{chunk-CK5RM3DJ.js.map → chunk-WVUDLKIO.js.map} +0 -0
- /package/dist/{chunk-HR4YDSJK.js.map → chunk-WWIFNPJG.js.map} +0 -0
- /package/dist/{chunk-P3KJCYSR.js.map → chunk-XZEVWPX6.js.map} +0 -0
- /package/dist/{chunk-XATIKM3P.js.map → chunk-Y47EV74W.js.map} +0 -0
- /package/dist/{chunk-UR3RRTPO.js.map → chunk-ZR4YPKXQ.js.map} +0 -0
- /package/dist/{chunk-UCORXS4D.js.map → chunk-ZXKBERQU.js.map} +0 -0
- /package/dist/{load-agent-defs-JHLE6MAE.js.map → load-agent-defs-3C27ENC7.js.map} +0 -0
- /package/dist/{recompile-project-agents-ZPP5NOLZ.js.map → recompile-project-agents-DGNBCU3N.js.map} +0 -0
- /package/dist/{source-loader-RWZAYJ7E.js.map → source-loader-7KZ3MD5O.js.map} +0 -0
package/dist/commands/doctor.js
CHANGED
|
@@ -1,47 +1,43 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
unofferablePlacementsFound
|
|
4
|
-
} from "../chunk-
|
|
4
|
+
} from "../chunk-PXWG7KFO.js";
|
|
5
5
|
import {
|
|
6
6
|
detectProject,
|
|
7
7
|
loadSource
|
|
8
|
-
} from "../chunk-
|
|
9
|
-
import "../chunk-
|
|
10
|
-
import "../chunk-
|
|
11
|
-
import "../chunk-
|
|
8
|
+
} from "../chunk-G6UREQ4V.js";
|
|
9
|
+
import "../chunk-HWEKHVLE.js";
|
|
10
|
+
import "../chunk-PMJWD27C.js";
|
|
11
|
+
import "../chunk-ZR4YPKXQ.js";
|
|
12
12
|
import {
|
|
13
13
|
filterExcludedEntries,
|
|
14
14
|
listAgentFilesOf,
|
|
15
15
|
listAgentMdFiles,
|
|
16
16
|
splitAgentsByProvenance
|
|
17
|
-
} from "../chunk-
|
|
17
|
+
} from "../chunk-GE3WKJ6Q.js";
|
|
18
18
|
import {
|
|
19
19
|
ambiguityFinding
|
|
20
|
-
} from "../chunk-
|
|
20
|
+
} from "../chunk-NBXXFIIW.js";
|
|
21
21
|
import {
|
|
22
22
|
BaseCommand,
|
|
23
23
|
EXIT_CODES
|
|
24
|
-
} from "../chunk-
|
|
25
|
-
import "../chunk-
|
|
26
|
-
import "../chunk-
|
|
24
|
+
} from "../chunk-Y3VIRVVE.js";
|
|
25
|
+
import "../chunk-VAPTVR3J.js";
|
|
26
|
+
import "../chunk-RZDXDMT6.js";
|
|
27
27
|
import {
|
|
28
28
|
ConfigDefaultExportError,
|
|
29
29
|
MarketplaceManifestRequiredError,
|
|
30
30
|
MarketplaceNameRefusedError,
|
|
31
|
-
REGISTRY_IS_NOT_AN_INVENTORY,
|
|
32
31
|
SOURCE_ENV_VAR,
|
|
33
32
|
agentCodec,
|
|
34
33
|
agentYamlGenerationSchema,
|
|
35
|
-
bothSourceFoldersPresent,
|
|
36
34
|
checkMatrixHealth,
|
|
37
|
-
compiledAgentNamesTheOtherFolder,
|
|
38
35
|
configDirsInPlay,
|
|
39
36
|
declaresNoContent,
|
|
40
37
|
directoryExists,
|
|
41
38
|
discoverLocalSkills,
|
|
42
39
|
fileExists,
|
|
43
40
|
findConfigLoadFailures,
|
|
44
|
-
folderBeingRead,
|
|
45
41
|
formatZodErrors,
|
|
46
42
|
getErrorMessage,
|
|
47
43
|
getInstalledConfigPath,
|
|
@@ -58,7 +54,6 @@ import {
|
|
|
58
54
|
isLocalSource,
|
|
59
55
|
isRecord,
|
|
60
56
|
layoutIsCurrent,
|
|
61
|
-
layoutIsLegacy,
|
|
62
57
|
listDirectories,
|
|
63
58
|
listRegisteredPluginInstalls,
|
|
64
59
|
loadConfig,
|
|
@@ -78,7 +73,6 @@ import {
|
|
|
78
73
|
relativeConfigPath,
|
|
79
74
|
resolveInstallPaths,
|
|
80
75
|
resolvePrimarySourceEntry,
|
|
81
|
-
resolveSourceDir,
|
|
82
76
|
scopeLabel,
|
|
83
77
|
scopeNoun,
|
|
84
78
|
skillCategoriesFileSchema,
|
|
@@ -89,7 +83,6 @@ import {
|
|
|
89
83
|
splitMetadataValidationIssues,
|
|
90
84
|
stackConfigValidationSchema,
|
|
91
85
|
stacksConfigSchema,
|
|
92
|
-
unusedSourceFolderName,
|
|
93
86
|
validResult,
|
|
94
87
|
validateAgentFrontmatter,
|
|
95
88
|
validateAllPlugins,
|
|
@@ -97,12 +90,11 @@ import {
|
|
|
97
90
|
validateProjectConfig,
|
|
98
91
|
validateSkillFrontmatter,
|
|
99
92
|
validateSkillMetadata
|
|
100
|
-
} from "../chunk-
|
|
93
|
+
} from "../chunk-A4KDXNOT.js";
|
|
101
94
|
import {
|
|
102
95
|
matrix
|
|
103
|
-
} from "../chunk-
|
|
96
|
+
} from "../chunk-V5WXIM2F.js";
|
|
104
97
|
import {
|
|
105
|
-
CLAUDE_DIR,
|
|
106
98
|
CLI_INVOKE_COMMAND,
|
|
107
99
|
DEFAULT_BRANDING,
|
|
108
100
|
DIRS,
|
|
@@ -113,77 +105,23 @@ import {
|
|
|
113
105
|
SKILL_CATEGORIES_PATH,
|
|
114
106
|
SKILL_RULES_PATH,
|
|
115
107
|
STACKS_FILE_PATH,
|
|
116
|
-
STANDARD_DIRS,
|
|
117
108
|
STANDARD_FILES,
|
|
118
109
|
UI_SYMBOLS,
|
|
119
110
|
effectivelyExcludedSkillIds
|
|
120
|
-
} from "../chunk-
|
|
111
|
+
} from "../chunk-ENGYJCTF.js";
|
|
121
112
|
import "../chunk-OI2H6M5I.js";
|
|
122
113
|
|
|
123
114
|
// src/cli/commands/doctor.ts
|
|
124
115
|
import os2 from "os";
|
|
125
|
-
import
|
|
126
|
-
|
|
127
|
-
// src/cli/lib/installation/layout-findings.ts
|
|
128
|
-
import path from "path";
|
|
129
|
-
async function layoutFindingFor(scope) {
|
|
130
|
-
const { move } = scope;
|
|
131
|
-
const label = scopeLabel(scope.kind);
|
|
132
|
-
if (move === null) {
|
|
133
|
-
return { status: "pass", message: layoutIsCurrent(label, scope.relName), details: [] };
|
|
134
|
-
}
|
|
135
|
-
const whichLayout = layoutStatement(scope, move, label);
|
|
136
|
-
const faults = await faultsFor(scope, move);
|
|
137
|
-
const [worst, ...rest] = faults;
|
|
138
|
-
if (worst === void 0) return { ...whichLayout, details: [] };
|
|
139
|
-
return {
|
|
140
|
-
status: "fail",
|
|
141
|
-
message: `${label}: ${worst}`,
|
|
142
|
-
details: [...rest.map((fault) => `${label}: ${fault}`), whichLayout.message]
|
|
143
|
-
};
|
|
144
|
-
}
|
|
145
|
-
function layoutStatement(scope, move, label) {
|
|
146
|
-
if (!scope.legacy) return { status: "pass", message: layoutIsCurrent(label, move.to.relName) };
|
|
147
|
-
return { status: "warn", message: layoutIsLegacy(label, move.from.relName, move.to.relName) };
|
|
148
|
-
}
|
|
149
|
-
async function faultsFor(scope, move) {
|
|
150
|
-
const staleAgents = await compiledAgentsNamingTheOtherFolder(scope);
|
|
151
|
-
return [...rivalFolderFault(scope, move), ...staleAgents];
|
|
152
|
-
}
|
|
153
|
-
function rivalFolderFault(scope, move) {
|
|
154
|
-
if (!scope.both) return [];
|
|
155
|
-
return [
|
|
156
|
-
bothSourceFoldersPresent(move.from.relName, move.to.relName, folderBeingRead(scope, move))
|
|
157
|
-
];
|
|
158
|
-
}
|
|
159
|
-
async function compiledAgentsNamingTheOtherFolder(scope) {
|
|
160
|
-
const unused = unusedSourceFolderName(scope.root, scope.provider);
|
|
161
|
-
if (unused === null) return [];
|
|
162
|
-
const agentsDir = path.join(scope.root, CLAUDE_DIR, STANDARD_DIRS.AGENTS);
|
|
163
|
-
const files = await listAgentMdFiles(agentsDir);
|
|
164
|
-
const named = await Promise.all(
|
|
165
|
-
files.map(async (file) => ({
|
|
166
|
-
file,
|
|
167
|
-
names: await namesFolder(path.join(agentsDir, file), unused)
|
|
168
|
-
}))
|
|
169
|
-
);
|
|
170
|
-
return named.filter((entry) => entry.names).map((entry) => compiledAgentNamesTheOtherFolder(entry.file, unused));
|
|
171
|
-
}
|
|
172
|
-
async function namesFolder(agentPath, folder) {
|
|
173
|
-
try {
|
|
174
|
-
return (await readFile(agentPath)).includes(folder);
|
|
175
|
-
} catch {
|
|
176
|
-
return false;
|
|
177
|
-
}
|
|
178
|
-
}
|
|
116
|
+
import path3 from "path";
|
|
179
117
|
|
|
180
118
|
// src/cli/lib/source-validator.ts
|
|
181
|
-
import
|
|
119
|
+
import path from "path";
|
|
182
120
|
import { parse as parseYaml } from "yaml";
|
|
183
121
|
import "zod";
|
|
184
122
|
async function isSourceRepo(dir) {
|
|
185
123
|
const sourceConfig = await loadSourceRepoConfig(dir);
|
|
186
|
-
return directoryExists(
|
|
124
|
+
return directoryExists(path.join(dir, sourceConfig?.skillsDir ?? SKILLS_DIR_PATH));
|
|
187
125
|
}
|
|
188
126
|
function isSnakeCase(key) {
|
|
189
127
|
return /[a-z]_[a-z]/.test(key);
|
|
@@ -207,10 +145,10 @@ function checkDirNameMatchesSkillId(skillId, relPath, dirName) {
|
|
|
207
145
|
];
|
|
208
146
|
}
|
|
209
147
|
async function checkSkillDirName(skillsDir2, skillsDirRelPath, skillDir) {
|
|
210
|
-
const dirName =
|
|
211
|
-
const skillMdRelPath =
|
|
148
|
+
const dirName = path.basename(skillDir);
|
|
149
|
+
const skillMdRelPath = path.join(skillsDirRelPath, skillDir, STANDARD_FILES.SKILL_MD);
|
|
212
150
|
try {
|
|
213
|
-
const content = await readFile(
|
|
151
|
+
const content = await readFile(path.join(skillsDir2, skillDir, STANDARD_FILES.SKILL_MD));
|
|
214
152
|
const frontmatter = parseFrontmatter(content, skillMdRelPath);
|
|
215
153
|
if (frontmatter === null) {
|
|
216
154
|
return [
|
|
@@ -235,18 +173,18 @@ async function checkSkillDirName(skillsDir2, skillsDirRelPath, skillDir) {
|
|
|
235
173
|
function validateSkillFilePairs(skillMdDirs, metadataDirs, skillsDir2) {
|
|
236
174
|
const missingMetadata = [...skillMdDirs].filter((dir) => !metadataDirs.has(dir)).map((dir) => ({
|
|
237
175
|
severity: "error",
|
|
238
|
-
file:
|
|
176
|
+
file: path.join(skillsDir2, dir),
|
|
239
177
|
message: `Missing ${STANDARD_FILES.METADATA_YAML} \u2014 skill directory has ${STANDARD_FILES.SKILL_MD} but no metadata`
|
|
240
178
|
}));
|
|
241
179
|
const missingSkillMd = [...metadataDirs].filter((dir) => !skillMdDirs.has(dir)).map((dir) => ({
|
|
242
180
|
severity: "error",
|
|
243
|
-
file:
|
|
181
|
+
file: path.join(skillsDir2, dir),
|
|
244
182
|
message: `Missing ${STANDARD_FILES.SKILL_MD} \u2014 skill directory has ${STANDARD_FILES.METADATA_YAML} but no SKILL.md`
|
|
245
183
|
}));
|
|
246
184
|
return [...missingMetadata, ...missingSkillMd];
|
|
247
185
|
}
|
|
248
186
|
async function validateSource(sourcePath, reader = "author") {
|
|
249
|
-
const resolvedPath =
|
|
187
|
+
const resolvedPath = path.isAbsolute(sourcePath) ? sourcePath : path.resolve(sourcePath);
|
|
250
188
|
if (!await directoryExists(resolvedPath)) {
|
|
251
189
|
return buildResult(
|
|
252
190
|
[{ severity: "error", file: resolvedPath, message: "Marketplace directory does not exist" }],
|
|
@@ -255,7 +193,7 @@ async function validateSource(sourcePath, reader = "author") {
|
|
|
255
193
|
}
|
|
256
194
|
const sourceProjectConfig = await loadSourceRepoConfig(resolvedPath);
|
|
257
195
|
const skillsDirRelPath = sourceProjectConfig?.skillsDir ?? SKILLS_DIR_PATH;
|
|
258
|
-
const skillsDir2 =
|
|
196
|
+
const skillsDir2 = path.join(resolvedPath, skillsDirRelPath);
|
|
259
197
|
if (!await directoryExists(skillsDir2)) {
|
|
260
198
|
return buildResult(
|
|
261
199
|
[{ severity: "error", file: skillsDir2, message: "Skills directory does not exist" }],
|
|
@@ -264,10 +202,10 @@ async function validateSource(sourcePath, reader = "author") {
|
|
|
264
202
|
}
|
|
265
203
|
const skillMdFiles = await glob(`**/${STANDARD_FILES.SKILL_MD}`, skillsDir2);
|
|
266
204
|
const metadataFiles = await glob(`**/${STANDARD_FILES.METADATA_YAML}`, skillsDir2);
|
|
267
|
-
const skillMdDirs = new Set(skillMdFiles.map((f) =>
|
|
268
|
-
const metadataDirs = new Set(metadataFiles.map((f) =>
|
|
205
|
+
const skillMdDirs = new Set(skillMdFiles.map((f) => path.dirname(f)));
|
|
206
|
+
const metadataDirs = new Set(metadataFiles.map((f) => path.dirname(f)));
|
|
269
207
|
const pairIssues = validateSkillFilePairs(skillMdDirs, metadataDirs, skillsDir2);
|
|
270
|
-
const validMetadataFiles = metadataFiles.filter((f) => skillMdDirs.has(
|
|
208
|
+
const validMetadataFiles = metadataFiles.filter((f) => skillMdDirs.has(path.dirname(f)));
|
|
271
209
|
const skillIssues = await validateSkillsInTurn(skillsDir2, skillsDirRelPath, validMetadataFiles);
|
|
272
210
|
const crossReferenceIssues = await checkCrossReferences(resolvedPath, reader);
|
|
273
211
|
const extraIssues = await Promise.all([
|
|
@@ -291,10 +229,10 @@ function yamlParseFailure(error) {
|
|
|
291
229
|
return `Failed to parse YAML: ${getErrorMessage(error)}`;
|
|
292
230
|
}
|
|
293
231
|
async function validateOneSkill(skillsDir2, skillsDirRelPath, metadataFile) {
|
|
294
|
-
const relPath =
|
|
232
|
+
const relPath = path.join(skillsDirRelPath, metadataFile);
|
|
295
233
|
let rawMetadata;
|
|
296
234
|
try {
|
|
297
|
-
rawMetadata = parseYaml(await readFile(
|
|
235
|
+
rawMetadata = parseYaml(await readFile(path.join(skillsDir2, metadataFile)));
|
|
298
236
|
} catch (error) {
|
|
299
237
|
return [{ severity: "error", file: relPath, message: yamlParseFailure(error) }];
|
|
300
238
|
}
|
|
@@ -302,7 +240,7 @@ async function validateOneSkill(skillsDir2, skillsDirRelPath, metadataFile) {
|
|
|
302
240
|
...checkSnakeCaseKeys(rawMetadata, relPath),
|
|
303
241
|
...checkMetadataSchema(rawMetadata, relPath),
|
|
304
242
|
// Independent of metadata validity — the id lives in SKILL.md frontmatter
|
|
305
|
-
...await checkSkillDirName(skillsDir2, skillsDirRelPath,
|
|
243
|
+
...await checkSkillDirName(skillsDir2, skillsDirRelPath, path.dirname(metadataFile))
|
|
306
244
|
];
|
|
307
245
|
}
|
|
308
246
|
function checkMetadataSchema(rawMetadata, relPath) {
|
|
@@ -314,7 +252,7 @@ function checkMetadataSchema(rawMetadata, relPath) {
|
|
|
314
252
|
...warnings.map((message) => ({ severity: "warning", file: relPath, message }))
|
|
315
253
|
];
|
|
316
254
|
}
|
|
317
|
-
var MARKETPLACE_MANIFEST_PATH =
|
|
255
|
+
var MARKETPLACE_MANIFEST_PATH = path.join(PLUGIN_MANIFEST_DIR, MARKETPLACE_JSON);
|
|
318
256
|
var MANIFEST_REQUIRED_SEVERITY = {
|
|
319
257
|
author: "warning",
|
|
320
258
|
consumer: "error"
|
|
@@ -387,7 +325,7 @@ function consumedMarketplaceMessage(marketplacePath, details) {
|
|
|
387
325
|
return `Marketplace '${marketplacePath}': ${details}. Nothing to fix here \u2014 the rule is that marketplace's, not this project's`;
|
|
388
326
|
}
|
|
389
327
|
async function validateStacks(resolvedPath) {
|
|
390
|
-
const stacksDir =
|
|
328
|
+
const stacksDir = path.join(resolvedPath, DIRS.stacks);
|
|
391
329
|
if (!await directoryExists(stacksDir)) return [];
|
|
392
330
|
const [skillMetaIssues, configIssues] = await Promise.all([
|
|
393
331
|
validateYamlFiles({
|
|
@@ -406,7 +344,7 @@ async function validateStacks(resolvedPath) {
|
|
|
406
344
|
return [...skillMetaIssues, ...configIssues];
|
|
407
345
|
}
|
|
408
346
|
async function validateAgents(resolvedPath) {
|
|
409
|
-
const agentsDir =
|
|
347
|
+
const agentsDir = path.join(resolvedPath, DIRS.agents);
|
|
410
348
|
if (!await directoryExists(agentsDir)) return [];
|
|
411
349
|
return validateYamlFiles({
|
|
412
350
|
baseDir: agentsDir,
|
|
@@ -432,10 +370,10 @@ async function validateYamlFiles(scan) {
|
|
|
432
370
|
return issues;
|
|
433
371
|
}
|
|
434
372
|
async function validateYamlFile(scan, relFile) {
|
|
435
|
-
const displayPath =
|
|
373
|
+
const displayPath = path.join(scan.relBaseDir, relFile);
|
|
436
374
|
let parsed;
|
|
437
375
|
try {
|
|
438
|
-
parsed = parseYaml(await readFile(
|
|
376
|
+
parsed = parseYaml(await readFile(path.join(scan.baseDir, relFile)));
|
|
439
377
|
} catch (error) {
|
|
440
378
|
return [{ severity: "error", file: displayPath, message: yamlParseFailure(error) }];
|
|
441
379
|
}
|
|
@@ -448,7 +386,7 @@ async function validateYamlFile(scan, relFile) {
|
|
|
448
386
|
}));
|
|
449
387
|
}
|
|
450
388
|
async function validateTsConfig(resolvedPath, relConfigPath, schema) {
|
|
451
|
-
const absPath =
|
|
389
|
+
const absPath = path.join(resolvedPath, relConfigPath);
|
|
452
390
|
if (!await fileExists(absPath)) return [];
|
|
453
391
|
try {
|
|
454
392
|
const loaded = await loadConfig(absPath, schema);
|
|
@@ -478,7 +416,7 @@ function buildResult(issues, skillCount) {
|
|
|
478
416
|
|
|
479
417
|
// src/cli/lib/content-validator.ts
|
|
480
418
|
import os from "os";
|
|
481
|
-
import
|
|
419
|
+
import path2 from "path";
|
|
482
420
|
import { partition } from "remeda";
|
|
483
421
|
var CWD_SOURCE_NAME = "current directory";
|
|
484
422
|
var AGENT_FILE_EXTENSION = ".md";
|
|
@@ -496,8 +434,8 @@ function mergeValidations(parts) {
|
|
|
496
434
|
function displayDir(absolutePath) {
|
|
497
435
|
const home = os.homedir();
|
|
498
436
|
if (absolutePath === home) return "~";
|
|
499
|
-
if (absolutePath.startsWith(home +
|
|
500
|
-
return `~${
|
|
437
|
+
if (absolutePath.startsWith(home + path2.sep)) {
|
|
438
|
+
return `~${path2.sep}${path2.relative(home, absolutePath)}`;
|
|
501
439
|
}
|
|
502
440
|
return absolutePath;
|
|
503
441
|
}
|
|
@@ -552,7 +490,7 @@ async function localSourcesToValidate(projectDir, registered) {
|
|
|
552
490
|
return [...local, { name: CWD_SOURCE_NAME, url: projectDir }];
|
|
553
491
|
}
|
|
554
492
|
function isCwdMarketplace(projectDir, source) {
|
|
555
|
-
return
|
|
493
|
+
return path2.resolve(projectDir, source.url) === projectDir;
|
|
556
494
|
}
|
|
557
495
|
function readerFor(projectDir, source) {
|
|
558
496
|
return isCwdMarketplace(projectDir, source) ? "author" : "consumer";
|
|
@@ -621,7 +559,7 @@ async function findPluginDirectories(pluginsDir) {
|
|
|
621
559
|
const checks = await Promise.all(
|
|
622
560
|
entries.map(async (name) => ({
|
|
623
561
|
name,
|
|
624
|
-
isPlugin: await directoryExists(
|
|
562
|
+
isPlugin: await directoryExists(path2.join(pluginsDir, name, PLUGIN_MANIFEST_DIR))
|
|
625
563
|
}))
|
|
626
564
|
);
|
|
627
565
|
return checks.filter((check) => check.isPlugin).map((check) => check.name);
|
|
@@ -681,7 +619,7 @@ async function listAcrossScopes(dirs, listEntries) {
|
|
|
681
619
|
async function listDisplayPaths(dir, listEntries) {
|
|
682
620
|
if (!await directoryExists(dir)) return [];
|
|
683
621
|
const entries = await listEntries(dir);
|
|
684
|
-
return entries.map((entry) => displayDir(
|
|
622
|
+
return entries.map((entry) => displayDir(path2.join(dir, entry)));
|
|
685
623
|
}
|
|
686
624
|
async function validateSkillsDirectory(skillsDir2, configuredIds) {
|
|
687
625
|
if (!await directoryExists(skillsDir2)) return NOTHING_VALIDATED;
|
|
@@ -696,7 +634,7 @@ async function validateSkillsDirectory(skillsDir2, configuredIds) {
|
|
|
696
634
|
const [ours, foreign] = partition(judged, (entry) => entry.ours);
|
|
697
635
|
const results = await Promise.all(
|
|
698
636
|
ours.map(async ({ name }) => {
|
|
699
|
-
const skillDir =
|
|
637
|
+
const skillDir = path2.join(skillsDir2, name);
|
|
700
638
|
return toIssues(displayDir(skillDir), await validateInstalledSkill(skillDir));
|
|
701
639
|
})
|
|
702
640
|
);
|
|
@@ -711,10 +649,10 @@ async function isOurSkillDirectory(skillsDir2, name, configuredIds) {
|
|
|
711
649
|
return carriesOurProvenance(skillsDir2, name);
|
|
712
650
|
}
|
|
713
651
|
async function carriesOurProvenance(skillsDir2, name) {
|
|
714
|
-
return await readForkedFromMetadata(
|
|
652
|
+
return await readForkedFromMetadata(path2.join(skillsDir2, name)) !== null;
|
|
715
653
|
}
|
|
716
654
|
function foreignSkillNote(skillsDir2, name) {
|
|
717
|
-
return `${displayDir(
|
|
655
|
+
return `${displayDir(path2.join(skillsDir2, name))} \u2014 not installed by this CLI and named by no configuration here: not validated`;
|
|
718
656
|
}
|
|
719
657
|
async function validateAgentsDirectory(agentsDir) {
|
|
720
658
|
if (!await directoryExists(agentsDir)) return NOTHING_VALIDATED;
|
|
@@ -722,7 +660,7 @@ async function validateAgentsDirectory(agentsDir) {
|
|
|
722
660
|
if (agentFiles.length === 0) return NOTHING_VALIDATED;
|
|
723
661
|
const results = await Promise.all(
|
|
724
662
|
agentFiles.map(async (fileName) => {
|
|
725
|
-
const agentPath =
|
|
663
|
+
const agentPath = path2.join(agentsDir, fileName);
|
|
726
664
|
return toIssues(displayDir(agentPath), await validateAgentFrontmatter(agentPath));
|
|
727
665
|
})
|
|
728
666
|
);
|
|
@@ -742,7 +680,7 @@ async function validateInstalledSkill(skillDir) {
|
|
|
742
680
|
return mergeValidationResults([skillMd, metadata]);
|
|
743
681
|
}
|
|
744
682
|
async function validateSkillFile(skillDir, fileName, validate) {
|
|
745
|
-
const filePath =
|
|
683
|
+
const filePath = path2.join(skillDir, fileName);
|
|
746
684
|
if (!await fileExists(filePath)) return invalidResult(`Missing ${fileName}`);
|
|
747
685
|
return validate(filePath);
|
|
748
686
|
}
|
|
@@ -945,7 +883,7 @@ async function agentCompileCheck(agent, hosts, agentsDirs) {
|
|
|
945
883
|
return { name: agent.name, provider, state: "unrenderable" };
|
|
946
884
|
}
|
|
947
885
|
const file = `${agent.name}${agentCodec(provider).extension}`;
|
|
948
|
-
const compiled = await fileExists(
|
|
886
|
+
const compiled = await fileExists(path3.join(agentsDirs[agent.scope], file));
|
|
949
887
|
return { name: agent.name, provider, state: compiled ? "compiled" : "missing" };
|
|
950
888
|
}
|
|
951
889
|
async function checkNoOrphans(config, projectDir) {
|
|
@@ -992,7 +930,7 @@ async function checkNoOrphans(config, projectDir) {
|
|
|
992
930
|
};
|
|
993
931
|
}
|
|
994
932
|
function orphanedAgentNames(mdFiles, knownAgents, codec) {
|
|
995
|
-
return mdFiles.map((fileName) =>
|
|
933
|
+
return mdFiles.map((fileName) => path3.basename(fileName, codec.extension)).filter((agentName) => !knownAgents.has(agentName));
|
|
996
934
|
}
|
|
997
935
|
async function checkUnownedInstallation(projectDir) {
|
|
998
936
|
const { skills, agents } = await listInstalledArtifacts(projectDir);
|
|
@@ -1046,7 +984,7 @@ async function checkSkillsInstalled(config, projectDir) {
|
|
|
1046
984
|
async function ejectedSkillCheck(skill, projectDir) {
|
|
1047
985
|
const provider = providerInUse(installBaseDir(projectDir, skill.scope));
|
|
1048
986
|
const dir = skillsDir(provider, skill.scope, projectDir);
|
|
1049
|
-
const installed = await fileExists(
|
|
987
|
+
const installed = await fileExists(path3.join(dir, skill.id, STANDARD_FILES.SKILL_MD));
|
|
1050
988
|
return {
|
|
1051
989
|
id: skill.id,
|
|
1052
990
|
installed,
|
|
@@ -1312,21 +1250,13 @@ async function recreateConfigTips(contentResults, projectDir) {
|
|
|
1312
1250
|
);
|
|
1313
1251
|
}
|
|
1314
1252
|
var LAYOUT_ROW_NAME = "Layout";
|
|
1315
|
-
function toLayoutResult(
|
|
1253
|
+
function toLayoutResult(scope) {
|
|
1316
1254
|
return {
|
|
1317
1255
|
kind: "layout",
|
|
1318
|
-
status:
|
|
1319
|
-
message:
|
|
1320
|
-
details: finding.details
|
|
1256
|
+
status: "pass",
|
|
1257
|
+
message: layoutIsCurrent(scopeLabel(scope.kind), scope.relName)
|
|
1321
1258
|
};
|
|
1322
1259
|
}
|
|
1323
|
-
async function registeredProjectsOnTheOldFolder(home) {
|
|
1324
|
-
const loaded = await loadInstalledConfig(home).catch(() => null);
|
|
1325
|
-
return (loaded?.config.projects ?? []).filter(isOnTheLegacySourceFolder);
|
|
1326
|
-
}
|
|
1327
|
-
function isOnTheLegacySourceFolder(dir) {
|
|
1328
|
-
return resolveSourceDir(dir, providerInUse(dir)).legacy;
|
|
1329
|
-
}
|
|
1330
1260
|
var PLACEMENTS_ROW_NAME = "Placements Offered";
|
|
1331
1261
|
async function checkOfferedPlacements(projectDir) {
|
|
1332
1262
|
const findings = await everythingThatWouldStopACommandActing(projectDir);
|
|
@@ -1492,47 +1422,20 @@ var Doctor = class _Doctor extends BaseCommand {
|
|
|
1492
1422
|
];
|
|
1493
1423
|
}
|
|
1494
1424
|
/**
|
|
1495
|
-
* One `Layout` row per scope in play
|
|
1496
|
-
* still on the old folder.
|
|
1425
|
+
* One `Layout` row per scope in play.
|
|
1497
1426
|
*
|
|
1498
|
-
* Per scope rather than per machine: a project and the global installation
|
|
1499
|
-
*
|
|
1427
|
+
* Per scope rather than per machine: a project and the global installation are two
|
|
1428
|
+
* installations, and one row for the two can only name one of their folders.
|
|
1500
1429
|
*
|
|
1501
1430
|
* Printed right under `Config Valid`, because every row below it is read out of a config file
|
|
1502
|
-
*
|
|
1503
|
-
* report may have read from either one.
|
|
1431
|
+
* in the folder this row names.
|
|
1504
1432
|
*/
|
|
1505
1433
|
async reportLayout(projectDir) {
|
|
1506
|
-
const
|
|
1507
|
-
const
|
|
1508
|
-
scopes.map(async (scope) => toLayoutResult(await layoutFindingFor(scope)))
|
|
1509
|
-
);
|
|
1510
|
-
const withRegistry = await this.appendRegistryList(projectDir, rows);
|
|
1511
|
-
for (const row of withRegistry) {
|
|
1434
|
+
const rows = (await sourceScopesInPlay(projectDir)).map(toLayoutResult);
|
|
1435
|
+
for (const row of rows) {
|
|
1512
1436
|
this.logCheck(LAYOUT_ROW_NAME, row);
|
|
1513
1437
|
}
|
|
1514
|
-
return
|
|
1515
|
-
}
|
|
1516
|
-
/**
|
|
1517
|
-
* The registered projects still on the old folder, added to the LAST row, and only at HOME.
|
|
1518
|
-
*
|
|
1519
|
-
* At home because that is where the registry lives, and the move a legacy project needs is made
|
|
1520
|
-
* by hand in that project — a list of other people's projects printed inside one of them is a
|
|
1521
|
-
* list nobody standing there can act on. The caveat travels with it: the registry holds a
|
|
1522
|
-
* fraction of the installations on a machine, so a list printed without it reads as an
|
|
1523
|
-
* inventory.
|
|
1524
|
-
*/
|
|
1525
|
-
async appendRegistryList(projectDir, rows) {
|
|
1526
|
-
const last = rows.at(-1);
|
|
1527
|
-
if (!isHomeDirectory(projectDir) || last === void 0) return rows;
|
|
1528
|
-
const legacyProjects = await registeredProjectsOnTheOldFolder(projectDir);
|
|
1529
|
-
if (legacyProjects.length === 0) return rows;
|
|
1530
|
-
const detailed = {
|
|
1531
|
-
...last,
|
|
1532
|
-
status: last.status === "fail" ? "fail" : "warn",
|
|
1533
|
-
details: [...last.details ?? [], REGISTRY_IS_NOT_AN_INVENTORY, ...legacyProjects]
|
|
1534
|
-
};
|
|
1535
|
-
return [...rows.slice(0, -1), detailed];
|
|
1438
|
+
return rows;
|
|
1536
1439
|
}
|
|
1537
1440
|
/**
|
|
1538
1441
|
* The orphan row, and which question it can answer. With a config it names the compiled
|