@agents-inc/cli 0.86.0 → 0.87.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 +10 -0
- package/dist/chunk-5UJJQFET.js +564 -0
- package/dist/chunk-5UJJQFET.js.map +1 -0
- package/dist/{chunk-GED2F75H.js → chunk-7FFNNDJQ.js} +176 -120
- package/dist/chunk-7FFNNDJQ.js.map +1 -0
- package/dist/{chunk-BV2MIQ3O.js → chunk-I5AZKNNL.js} +1 -1
- package/dist/chunk-I5AZKNNL.js.map +1 -0
- package/dist/chunk-J6PI73YV.js +68 -0
- package/dist/chunk-J6PI73YV.js.map +1 -0
- package/dist/commands/compile.js +26 -20
- package/dist/commands/compile.js.map +1 -1
- package/dist/commands/diff.js +681 -82
- package/dist/commands/diff.js.map +1 -1
- package/dist/commands/doctor.js +30 -58
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/edit.js +164 -32
- package/dist/commands/edit.js.map +1 -1
- package/dist/commands/eject.js +177 -27
- package/dist/commands/eject.js.map +1 -1
- package/dist/commands/import/skill.js +197 -33
- package/dist/commands/import/skill.js.map +1 -1
- package/dist/commands/info.js +41 -34
- package/dist/commands/info.js.map +1 -1
- package/dist/commands/init.js +3 -6
- package/dist/commands/new/agent.js +140 -44
- package/dist/commands/new/agent.js.map +1 -1
- package/dist/commands/new/marketplace.js +4 -4
- package/dist/commands/new/marketplace.js.map +1 -1
- package/dist/commands/new/skill.js +194 -30
- package/dist/commands/new/skill.js.map +1 -1
- package/dist/commands/outdated.js +1 -3
- package/dist/commands/outdated.js.map +1 -1
- package/dist/commands/search.js +162 -65
- package/dist/commands/search.js.map +1 -1
- package/dist/commands/uninstall.js +259 -62
- package/dist/commands/uninstall.js.map +1 -1
- package/dist/commands/update.js +232 -163
- package/dist/commands/update.js.map +1 -1
- package/dist/components/skill-search/skill-search.js +1 -1
- package/dist/hooks/init.js +2 -4
- package/dist/hooks/init.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-BV2MIQ3O.js.map +0 -1
- package/dist/chunk-DCVCFBQ7.js +0 -1800
- package/dist/chunk-DCVCFBQ7.js.map +0 -1
- package/dist/chunk-GED2F75H.js.map +0 -1
- package/dist/chunk-O5ZWS26C.js +0 -166
- package/dist/chunk-O5ZWS26C.js.map +0 -1
- package/dist/chunk-XQK4S22C.js +0 -202
- package/dist/chunk-XQK4S22C.js.map +0 -1
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
buildCategoryEntry,
|
|
4
|
+
formatTsExport,
|
|
5
|
+
generateSkillCategoriesTs,
|
|
6
|
+
generateSkillRulesTs,
|
|
7
|
+
toTitleCase
|
|
8
|
+
} from "../../chunk-J6PI73YV.js";
|
|
7
9
|
import {
|
|
8
10
|
LOCAL_DEFAULTS,
|
|
11
|
+
computeSkillFolderHash,
|
|
9
12
|
detectInstallation,
|
|
13
|
+
loadConfig,
|
|
10
14
|
loadConfigTypesDataInBackground,
|
|
11
15
|
regenerateConfigTypes,
|
|
12
16
|
resolveAuthor
|
|
@@ -19,15 +23,21 @@ import {
|
|
|
19
23
|
} from "../../chunk-MMTMXLI4.js";
|
|
20
24
|
import {
|
|
21
25
|
directoryExists,
|
|
26
|
+
ensureDir,
|
|
22
27
|
fileExists,
|
|
23
|
-
getErrorMessage
|
|
28
|
+
getErrorMessage,
|
|
29
|
+
verbose,
|
|
30
|
+
writeFile
|
|
24
31
|
} from "../../chunk-NUU3U43A.js";
|
|
25
32
|
import "../../chunk-6XWHJHNZ.js";
|
|
26
33
|
import {
|
|
27
34
|
CLI_BIN_NAME,
|
|
35
|
+
KEBAB_CASE_PATTERN,
|
|
28
36
|
LOCAL_SKILLS_PATH,
|
|
29
37
|
PLUGIN_MANIFEST_DIR,
|
|
30
38
|
SKILLS_DIR_PATH,
|
|
39
|
+
SKILL_CATEGORIES_PATH,
|
|
40
|
+
SKILL_RULES_PATH,
|
|
31
41
|
STANDARD_FILES
|
|
32
42
|
} from "../../chunk-6PGL2XMY.js";
|
|
33
43
|
import "../../chunk-NPMMU4GY.js";
|
|
@@ -78,7 +88,30 @@ var NewSkill = class _NewSkill extends BaseCommand {
|
|
|
78
88
|
async run() {
|
|
79
89
|
const { args, flags } = await this.parse(_NewSkill);
|
|
80
90
|
const projectDir = process.cwd();
|
|
81
|
-
|
|
91
|
+
await this.ensureInstallation(projectDir, flags.output);
|
|
92
|
+
const configTypesReady = this.startConfigTypesLoading(flags, projectDir);
|
|
93
|
+
this.printHeader();
|
|
94
|
+
this.validateName(args.name);
|
|
95
|
+
const author = await this.resolveAuthorOrDefault(flags.author, projectDir);
|
|
96
|
+
const category = flags.category;
|
|
97
|
+
const domain = flags.domain ?? LOCAL_DEFAULTS.DOMAIN;
|
|
98
|
+
const skillsBasePath = await this.resolveSkillsBasePath(flags, projectDir);
|
|
99
|
+
const skillDir = path.join(skillsBasePath, args.name);
|
|
100
|
+
await this.checkExistingDir(skillDir, flags.force);
|
|
101
|
+
this.logSkillInfo(args.name, author, category, skillDir);
|
|
102
|
+
await this.createSkillFiles(
|
|
103
|
+
args.name,
|
|
104
|
+
author,
|
|
105
|
+
category,
|
|
106
|
+
domain,
|
|
107
|
+
skillDir,
|
|
108
|
+
flags,
|
|
109
|
+
projectDir,
|
|
110
|
+
configTypesReady
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
async ensureInstallation(projectDir, output) {
|
|
114
|
+
if (!output) {
|
|
82
115
|
const installation = await detectInstallation(projectDir);
|
|
83
116
|
if (!installation) {
|
|
84
117
|
this.error(`No installation found. Run '${CLI_BIN_NAME} init' first.`, {
|
|
@@ -86,35 +119,39 @@ var NewSkill = class _NewSkill extends BaseCommand {
|
|
|
86
119
|
});
|
|
87
120
|
}
|
|
88
121
|
}
|
|
89
|
-
|
|
122
|
+
}
|
|
123
|
+
startConfigTypesLoading(flags, projectDir) {
|
|
124
|
+
return flags.output ? null : loadConfigTypesDataInBackground(flags.source, projectDir);
|
|
125
|
+
}
|
|
126
|
+
printHeader() {
|
|
90
127
|
this.log("");
|
|
91
128
|
this.log("Create New Skill");
|
|
92
129
|
this.log("");
|
|
93
|
-
|
|
130
|
+
}
|
|
131
|
+
validateName(name) {
|
|
132
|
+
const validationError = validateSkillName(name);
|
|
94
133
|
if (validationError) {
|
|
95
134
|
this.error(validationError, { exit: EXIT_CODES.INVALID_ARGS });
|
|
96
135
|
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
let skillsBasePath;
|
|
136
|
+
}
|
|
137
|
+
async resolveAuthorOrDefault(authorFlag, projectDir) {
|
|
138
|
+
if (authorFlag) return authorFlag;
|
|
139
|
+
return await resolveAuthor(projectDir) || LOCAL_DEFAULTS.AUTHOR;
|
|
140
|
+
}
|
|
141
|
+
async resolveSkillsBasePath(flags, projectDir) {
|
|
104
142
|
if (flags.output) {
|
|
105
|
-
|
|
106
|
-
} else {
|
|
107
|
-
const marketplacePath = path.join(projectDir, PLUGIN_MANIFEST_DIR, "marketplace.json");
|
|
108
|
-
if (await fileExists(marketplacePath)) {
|
|
109
|
-
this.log(`Detected marketplace context, creating skill in ${SKILLS_DIR_PATH}/`);
|
|
110
|
-
skillsBasePath = path.join(projectDir, SKILLS_DIR_PATH);
|
|
111
|
-
} else {
|
|
112
|
-
skillsBasePath = path.join(projectDir, LOCAL_SKILLS_PATH);
|
|
113
|
-
}
|
|
143
|
+
return path.resolve(flags.output);
|
|
114
144
|
}
|
|
115
|
-
const
|
|
145
|
+
const marketplacePath = path.join(projectDir, PLUGIN_MANIFEST_DIR, "marketplace.json");
|
|
146
|
+
if (await fileExists(marketplacePath)) {
|
|
147
|
+
this.log(`Detected marketplace context, creating skill in ${SKILLS_DIR_PATH}/`);
|
|
148
|
+
return path.join(projectDir, SKILLS_DIR_PATH);
|
|
149
|
+
}
|
|
150
|
+
return path.join(projectDir, LOCAL_SKILLS_PATH);
|
|
151
|
+
}
|
|
152
|
+
async checkExistingDir(skillDir, force) {
|
|
116
153
|
if (await directoryExists(skillDir)) {
|
|
117
|
-
if (!
|
|
154
|
+
if (!force) {
|
|
118
155
|
this.error(`Skill directory already exists: ${skillDir}
|
|
119
156
|
Use --force to overwrite.`, {
|
|
120
157
|
exit: EXIT_CODES.ERROR
|
|
@@ -122,15 +159,19 @@ Use --force to overwrite.`, {
|
|
|
122
159
|
}
|
|
123
160
|
this.warn(`Overwriting existing skill at ${skillDir}`);
|
|
124
161
|
}
|
|
125
|
-
|
|
162
|
+
}
|
|
163
|
+
logSkillInfo(name, author, category, skillDir) {
|
|
164
|
+
this.log(`Skill name: ${name}`);
|
|
126
165
|
this.log(`Author: ${author}`);
|
|
127
166
|
this.log(`Category: ${category}`);
|
|
128
167
|
this.log(`Directory: ${skillDir}`);
|
|
129
168
|
this.log("");
|
|
169
|
+
}
|
|
170
|
+
async createSkillFiles(name, author, category, domain, skillDir, flags, projectDir, configTypesReady) {
|
|
130
171
|
this.log("Creating skill files...");
|
|
131
172
|
try {
|
|
132
173
|
const result = await scaffoldSkillFiles({
|
|
133
|
-
name
|
|
174
|
+
name,
|
|
134
175
|
author,
|
|
135
176
|
category,
|
|
136
177
|
domain,
|
|
@@ -152,7 +193,7 @@ Use --force to overwrite.`, {
|
|
|
152
193
|
if (configTypesReady) {
|
|
153
194
|
try {
|
|
154
195
|
await regenerateConfigTypes(projectDir, configTypesReady, {
|
|
155
|
-
extraSkillIds: [
|
|
196
|
+
extraSkillIds: [name],
|
|
156
197
|
extraDomains: [domain],
|
|
157
198
|
extraCategories: [category]
|
|
158
199
|
});
|
|
@@ -172,7 +213,130 @@ Use --force to overwrite.`, {
|
|
|
172
213
|
}
|
|
173
214
|
}
|
|
174
215
|
};
|
|
216
|
+
function validateSkillName(name) {
|
|
217
|
+
if (!name || name.trim() === "") {
|
|
218
|
+
return "Skill name is required";
|
|
219
|
+
}
|
|
220
|
+
if (!KEBAB_CASE_PATTERN.test(name)) {
|
|
221
|
+
return "Skill name must be kebab-case (lowercase letters, numbers, and hyphens, starting with a letter)";
|
|
222
|
+
}
|
|
223
|
+
return null;
|
|
224
|
+
}
|
|
225
|
+
function generateSkillMd(name) {
|
|
226
|
+
const titleName = toTitleCase(name);
|
|
227
|
+
return `---
|
|
228
|
+
name: ${name}
|
|
229
|
+
description: Brief description of this skill
|
|
230
|
+
---
|
|
231
|
+
|
|
232
|
+
# ${titleName}
|
|
233
|
+
|
|
234
|
+
> **Quick Guide:** Add a brief summary of what this skill teaches.
|
|
235
|
+
|
|
236
|
+
---
|
|
237
|
+
|
|
238
|
+
<critical_requirements>
|
|
239
|
+
|
|
240
|
+
## CRITICAL: Before Using This Skill
|
|
241
|
+
|
|
242
|
+
**(Add critical requirements here)**
|
|
243
|
+
|
|
244
|
+
</critical_requirements>
|
|
245
|
+
|
|
246
|
+
---
|
|
247
|
+
|
|
248
|
+
**When to use:**
|
|
249
|
+
|
|
250
|
+
- Add use cases here
|
|
251
|
+
|
|
252
|
+
**Key patterns covered:**
|
|
253
|
+
|
|
254
|
+
- Add patterns here
|
|
255
|
+
|
|
256
|
+
---
|
|
257
|
+
|
|
258
|
+
<patterns>
|
|
259
|
+
|
|
260
|
+
## Core Patterns
|
|
261
|
+
|
|
262
|
+
### Pattern 1: Example Pattern
|
|
263
|
+
|
|
264
|
+
Add your patterns here.
|
|
265
|
+
|
|
266
|
+
</patterns>
|
|
267
|
+
|
|
268
|
+
---
|
|
269
|
+
|
|
270
|
+
<critical_reminders>
|
|
271
|
+
|
|
272
|
+
## CRITICAL REMINDERS
|
|
273
|
+
|
|
274
|
+
**(Repeat critical requirements here)**
|
|
275
|
+
|
|
276
|
+
</critical_reminders>
|
|
277
|
+
`;
|
|
278
|
+
}
|
|
279
|
+
function generateMetadataYaml(name, author, category, contentHash, domain) {
|
|
280
|
+
const titleName = toTitleCase(name);
|
|
281
|
+
return `# yaml-language-server: $schema=https://raw.githubusercontent.com/agents-inc/cli/main/src/schemas/custom-metadata.schema.json
|
|
282
|
+
custom: true
|
|
283
|
+
domain: ${domain}
|
|
284
|
+
category: ${category}
|
|
285
|
+
author: "${author}"
|
|
286
|
+
displayName: ${titleName}
|
|
287
|
+
slug: ${name}
|
|
288
|
+
cliDescription: Brief description
|
|
289
|
+
usageGuidance: Use when <guidance>.
|
|
290
|
+
contentHash: ${contentHash}
|
|
291
|
+
`;
|
|
292
|
+
}
|
|
293
|
+
async function scaffoldSkillFiles(options) {
|
|
294
|
+
const { name, author, category, domain, skillDir } = options;
|
|
295
|
+
const skillMdContent = generateSkillMd(name);
|
|
296
|
+
const skillMdPath = path.join(skillDir, STANDARD_FILES.SKILL_MD);
|
|
297
|
+
const metadataPath = path.join(skillDir, STANDARD_FILES.METADATA_YAML);
|
|
298
|
+
await writeFile(skillMdPath, skillMdContent);
|
|
299
|
+
const contentHash = await computeSkillFolderHash(skillDir);
|
|
300
|
+
const metadataContent = generateMetadataYaml(name, author, category, contentHash, domain);
|
|
301
|
+
await writeFile(metadataPath, metadataContent);
|
|
302
|
+
return { skillMdPath, metadataPath, contentHash };
|
|
303
|
+
}
|
|
304
|
+
async function updateSkillRegistryConfig(options) {
|
|
305
|
+
const { projectRoot, category, domain } = options;
|
|
306
|
+
const categoriesPath = path.join(projectRoot, SKILL_CATEGORIES_PATH);
|
|
307
|
+
const rulesPath = path.join(projectRoot, SKILL_RULES_PATH);
|
|
308
|
+
let categoriesCreated = false;
|
|
309
|
+
let categoriesUpdated = false;
|
|
310
|
+
let rulesCreated = false;
|
|
311
|
+
if (await fileExists(categoriesPath)) {
|
|
312
|
+
const parsed = await loadConfig(categoriesPath) ?? {};
|
|
313
|
+
const categories = parsed.categories ?? {};
|
|
314
|
+
if (!categories[category]) {
|
|
315
|
+
categories[category] = buildCategoryEntry(category, domain);
|
|
316
|
+
parsed.categories = categories;
|
|
317
|
+
await writeFile(categoriesPath, formatTsExport(CATEGORIES_TS_COMMENT, parsed));
|
|
318
|
+
verbose(`Added category '${category}' to ${SKILL_CATEGORIES_PATH}`);
|
|
319
|
+
categoriesUpdated = true;
|
|
320
|
+
}
|
|
321
|
+
} else {
|
|
322
|
+
await ensureDir(path.dirname(categoriesPath));
|
|
323
|
+
await writeFile(categoriesPath, generateSkillCategoriesTs(category, domain));
|
|
324
|
+
verbose(`Created ${SKILL_CATEGORIES_PATH}`);
|
|
325
|
+
categoriesCreated = true;
|
|
326
|
+
}
|
|
327
|
+
if (!await fileExists(rulesPath)) {
|
|
328
|
+
await ensureDir(path.dirname(rulesPath));
|
|
329
|
+
await writeFile(rulesPath, generateSkillRulesTs());
|
|
330
|
+
verbose(`Created ${SKILL_RULES_PATH}`);
|
|
331
|
+
rulesCreated = true;
|
|
332
|
+
}
|
|
333
|
+
return { categoriesCreated, categoriesUpdated, rulesCreated };
|
|
334
|
+
}
|
|
335
|
+
var CATEGORIES_TS_COMMENT = "// Skill category definitions";
|
|
175
336
|
export {
|
|
176
|
-
NewSkill as default
|
|
337
|
+
NewSkill as default,
|
|
338
|
+
generateMetadataYaml,
|
|
339
|
+
generateSkillMd,
|
|
340
|
+
validateSkillName
|
|
177
341
|
};
|
|
178
342
|
//# sourceMappingURL=skill.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/cli/commands/new/skill.ts"],"sourcesContent":["import { Args, Flags } from \"@oclif/core\";\nimport path from \"path\";\nimport { BaseCommand } from \"../../base-command.js\";\nimport { resolveAuthor } from \"../../lib/configuration/index.js\";\nimport {\n loadConfigTypesDataInBackground,\n regenerateConfigTypes,\n} from \"../../lib/configuration/config-types-writer.js\";\nimport { directoryExists, fileExists } from \"../../utils/fs.js\";\nimport { getErrorMessage } from \"../../utils/errors.js\";\nimport {\n CLI_BIN_NAME,\n LOCAL_SKILLS_PATH,\n PLUGIN_MANIFEST_DIR,\n SKILLS_DIR_PATH,\n STANDARD_FILES,\n} from \"../../consts.js\";\nimport { EXIT_CODES } from \"../../lib/exit-codes.js\";\nimport { detectInstallation } from \"../../lib/installation/index.js\";\nimport { LOCAL_DEFAULTS } from \"../../lib/metadata-keys.js\";\nimport type { CategoryPath } from \"../../types/index.js\";\nimport {\n validateSkillName,\n scaffoldSkillFiles,\n updateSkillRegistryConfig,\n} from \"../../lib/operations/scaffold-skill.js\";\n\nexport default class NewSkill extends BaseCommand {\n static summary = \"Create a new local skill with proper structure\";\n static description = \"Create a new local skill scaffold with SKILL.md and metadata.yaml files\";\n\n static args = {\n name: Args.string({\n description: \"Name of the skill to create (kebab-case)\",\n required: true,\n }),\n };\n\n static flags = {\n ...BaseCommand.baseFlags,\n author: Flags.string({\n char: \"a\",\n description: \"Author identifier (e.g., @myhandle)\",\n required: false,\n }),\n category: Flags.string({\n char: \"c\",\n description: \"Skill category\",\n default: LOCAL_DEFAULTS.CATEGORY,\n }),\n domain: Flags.string({\n char: \"d\",\n description: \"Domain for the skill (e.g., web, api, cli)\",\n required: false,\n }),\n force: Flags.boolean({\n char: \"f\",\n description: \"Overwrite existing skill directory\",\n default: false,\n }),\n output: Flags.string({\n char: \"o\",\n description: \"Output directory for the skill (overrides marketplace detection)\",\n }),\n };\n\n async run(): Promise<void> {\n const { args, flags } = await this.parse(NewSkill);\n const projectDir = process.cwd();\n\n if (!flags.output) {\n const installation = await detectInstallation(projectDir);\n if (!installation) {\n this.error(`No installation found. Run '${CLI_BIN_NAME} init' first.`, {\n exit: EXIT_CODES.ERROR,\n });\n }\n }\n\n // Kick off background loading for config-types.ts regeneration (non-blocking)\n const configTypesReady = flags.output\n ? null\n : loadConfigTypesDataInBackground(flags.source, projectDir);\n\n this.log(\"\");\n this.log(\"Create New Skill\");\n this.log(\"\");\n\n const validationError = validateSkillName(args.name);\n if (validationError) {\n this.error(validationError, { exit: EXIT_CODES.INVALID_ARGS });\n }\n\n // Determine author: flag > project config > default\n let author = flags.author;\n if (!author) {\n author = (await resolveAuthor(projectDir)) || LOCAL_DEFAULTS.AUTHOR;\n }\n\n // Boundary cast: CLI flag accepts custom category values not in the generated union\n const category = flags.category as CategoryPath;\n\n const domain = flags.domain ?? LOCAL_DEFAULTS.DOMAIN;\n\n // Determine skill output path: --output flag > marketplace detection > local default\n let skillsBasePath: string;\n if (flags.output) {\n skillsBasePath = path.resolve(flags.output);\n } else {\n const marketplacePath = path.join(projectDir, PLUGIN_MANIFEST_DIR, \"marketplace.json\");\n if (await fileExists(marketplacePath)) {\n this.log(`Detected marketplace context, creating skill in ${SKILLS_DIR_PATH}/`);\n skillsBasePath = path.join(projectDir, SKILLS_DIR_PATH);\n } else {\n skillsBasePath = path.join(projectDir, LOCAL_SKILLS_PATH);\n }\n }\n\n const skillDir = path.join(skillsBasePath, args.name);\n\n if (await directoryExists(skillDir)) {\n if (!flags.force) {\n this.error(`Skill directory already exists: ${skillDir}\\nUse --force to overwrite.`, {\n exit: EXIT_CODES.ERROR,\n });\n }\n this.warn(`Overwriting existing skill at ${skillDir}`);\n }\n\n this.log(`Skill name: ${args.name}`);\n this.log(`Author: ${author}`);\n this.log(`Category: ${category}`);\n this.log(`Directory: ${skillDir}`);\n this.log(\"\");\n\n this.log(\"Creating skill files...\");\n\n try {\n const result = await scaffoldSkillFiles({\n name: args.name,\n author,\n category,\n domain,\n skillDir,\n });\n\n this.log(\"\");\n this.logSuccess(`Created ${STANDARD_FILES.SKILL_MD} at ${result.skillMdPath}`);\n this.logSuccess(`Created ${STANDARD_FILES.METADATA_YAML} at ${result.metadataPath}`);\n\n // Update config files when in marketplace context\n if (!flags.output) {\n const marketplacePath = path.join(projectDir, PLUGIN_MANIFEST_DIR, \"marketplace.json\");\n if (await fileExists(marketplacePath)) {\n try {\n await updateSkillRegistryConfig({ projectRoot: projectDir, category, domain });\n } catch (error) {\n this.warn(`Could not update config files: ${getErrorMessage(error)}`);\n }\n }\n }\n\n // Regenerate config-types.ts to include the new skill\n if (configTypesReady) {\n try {\n await regenerateConfigTypes(projectDir, configTypesReady, {\n extraSkillIds: [args.name],\n extraDomains: [domain],\n extraCategories: [category],\n });\n } catch (error) {\n this.warn(\n `Could not update ${STANDARD_FILES.CONFIG_TYPES_TS}: ${getErrorMessage(error)}`,\n );\n }\n }\n\n this.log(\"\");\n this.log(\n `Skill created successfully! Run '${CLI_BIN_NAME} compile' to include it in your agents.`,\n );\n this.log(\"\");\n } catch (error) {\n this.handleError(error);\n }\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/cli/commands/new/skill.ts"],"sourcesContent":["import { Args, Flags } from \"@oclif/core\";\nimport path from \"path\";\nimport { BaseCommand } from \"../../base-command.js\";\nimport { resolveAuthor } from \"../../lib/configuration/index.js\";\nimport { loadConfig } from \"../../lib/configuration/config-loader.js\";\nimport {\n loadConfigTypesDataInBackground,\n regenerateConfigTypes,\n} from \"../../lib/configuration/config-types-writer.js\";\nimport { directoryExists, fileExists, writeFile, ensureDir } from \"../../utils/fs.js\";\nimport { getErrorMessage } from \"../../utils/errors.js\";\nimport { verbose } from \"../../utils/logger.js\";\nimport { computeSkillFolderHash } from \"../../lib/versioning.js\";\nimport {\n CLI_BIN_NAME,\n KEBAB_CASE_PATTERN,\n LOCAL_SKILLS_PATH,\n PLUGIN_MANIFEST_DIR,\n SKILL_CATEGORIES_PATH,\n SKILL_RULES_PATH,\n SKILLS_DIR_PATH,\n STANDARD_FILES,\n} from \"../../consts.js\";\nimport { EXIT_CODES } from \"../../lib/exit-codes.js\";\nimport { detectInstallation } from \"../../lib/installation/index.js\";\nimport { LOCAL_DEFAULTS } from \"../../lib/metadata-keys.js\";\nimport type { CategoryPath } from \"../../types/index.js\";\nimport {\n toTitleCase,\n generateSkillCategoriesTs,\n generateSkillRulesTs,\n buildCategoryEntry,\n formatTsExport,\n} from \"../../lib/skills/generators.js\";\n\nexport default class NewSkill extends BaseCommand {\n static summary = \"Create a new local skill with proper structure\";\n static description = \"Create a new local skill scaffold with SKILL.md and metadata.yaml files\";\n\n static args = {\n name: Args.string({\n description: \"Name of the skill to create (kebab-case)\",\n required: true,\n }),\n };\n\n static flags = {\n ...BaseCommand.baseFlags,\n author: Flags.string({\n char: \"a\",\n description: \"Author identifier (e.g., @myhandle)\",\n required: false,\n }),\n category: Flags.string({\n char: \"c\",\n description: \"Skill category\",\n default: LOCAL_DEFAULTS.CATEGORY,\n }),\n domain: Flags.string({\n char: \"d\",\n description: \"Domain for the skill (e.g., web, api, cli)\",\n required: false,\n }),\n force: Flags.boolean({\n char: \"f\",\n description: \"Overwrite existing skill directory\",\n default: false,\n }),\n output: Flags.string({\n char: \"o\",\n description: \"Output directory for the skill (overrides marketplace detection)\",\n }),\n };\n\n async run(): Promise<void> {\n const { args, flags } = await this.parse(NewSkill);\n const projectDir = process.cwd();\n\n await this.ensureInstallation(projectDir, flags.output);\n const configTypesReady = this.startConfigTypesLoading(flags, projectDir);\n\n this.printHeader();\n this.validateName(args.name);\n\n const author = await this.resolveAuthorOrDefault(flags.author, projectDir);\n // Boundary cast: CLI flag accepts custom category values not in the generated union\n const category = flags.category as CategoryPath;\n const domain = flags.domain ?? LOCAL_DEFAULTS.DOMAIN;\n const skillsBasePath = await this.resolveSkillsBasePath(flags, projectDir);\n const skillDir = path.join(skillsBasePath, args.name);\n\n await this.checkExistingDir(skillDir, flags.force);\n this.logSkillInfo(args.name, author, category, skillDir);\n await this.createSkillFiles(\n args.name,\n author,\n category,\n domain,\n skillDir,\n flags,\n projectDir,\n configTypesReady,\n );\n }\n\n private async ensureInstallation(projectDir: string, output: string | undefined): Promise<void> {\n if (!output) {\n const installation = await detectInstallation(projectDir);\n if (!installation) {\n this.error(`No installation found. Run '${CLI_BIN_NAME} init' first.`, {\n exit: EXIT_CODES.ERROR,\n });\n }\n }\n }\n\n private startConfigTypesLoading(\n flags: { output?: string; source?: string },\n projectDir: string,\n ): ReturnType<typeof loadConfigTypesDataInBackground> | null {\n return flags.output ? null : loadConfigTypesDataInBackground(flags.source, projectDir);\n }\n\n private printHeader(): void {\n this.log(\"\");\n this.log(\"Create New Skill\");\n this.log(\"\");\n }\n\n private validateName(name: string): void {\n const validationError = validateSkillName(name);\n if (validationError) {\n this.error(validationError, { exit: EXIT_CODES.INVALID_ARGS });\n }\n }\n\n private async resolveAuthorOrDefault(\n authorFlag: string | undefined,\n projectDir: string,\n ): Promise<string> {\n if (authorFlag) return authorFlag;\n return (await resolveAuthor(projectDir)) || LOCAL_DEFAULTS.AUTHOR;\n }\n\n private async resolveSkillsBasePath(\n flags: { output?: string },\n projectDir: string,\n ): Promise<string> {\n if (flags.output) {\n return path.resolve(flags.output);\n }\n const marketplacePath = path.join(projectDir, PLUGIN_MANIFEST_DIR, \"marketplace.json\");\n if (await fileExists(marketplacePath)) {\n this.log(`Detected marketplace context, creating skill in ${SKILLS_DIR_PATH}/`);\n return path.join(projectDir, SKILLS_DIR_PATH);\n }\n return path.join(projectDir, LOCAL_SKILLS_PATH);\n }\n\n private async checkExistingDir(skillDir: string, force: boolean): Promise<void> {\n if (await directoryExists(skillDir)) {\n if (!force) {\n this.error(`Skill directory already exists: ${skillDir}\\nUse --force to overwrite.`, {\n exit: EXIT_CODES.ERROR,\n });\n }\n this.warn(`Overwriting existing skill at ${skillDir}`);\n }\n }\n\n private logSkillInfo(\n name: string,\n author: string,\n category: CategoryPath,\n skillDir: string,\n ): void {\n this.log(`Skill name: ${name}`);\n this.log(`Author: ${author}`);\n this.log(`Category: ${category}`);\n this.log(`Directory: ${skillDir}`);\n this.log(\"\");\n }\n\n private async createSkillFiles(\n name: string,\n author: string,\n category: CategoryPath,\n domain: string,\n skillDir: string,\n flags: { output?: string; source?: string; force?: boolean },\n projectDir: string,\n configTypesReady: ReturnType<typeof loadConfigTypesDataInBackground> | null,\n ): Promise<void> {\n this.log(\"Creating skill files...\");\n\n try {\n const result = await scaffoldSkillFiles({\n name,\n author,\n category,\n domain,\n skillDir,\n });\n\n this.log(\"\");\n this.logSuccess(`Created ${STANDARD_FILES.SKILL_MD} at ${result.skillMdPath}`);\n this.logSuccess(`Created ${STANDARD_FILES.METADATA_YAML} at ${result.metadataPath}`);\n\n if (!flags.output) {\n const marketplacePath = path.join(projectDir, PLUGIN_MANIFEST_DIR, \"marketplace.json\");\n if (await fileExists(marketplacePath)) {\n try {\n await updateSkillRegistryConfig({ projectRoot: projectDir, category, domain });\n } catch (error) {\n this.warn(`Could not update config files: ${getErrorMessage(error)}`);\n }\n }\n }\n\n if (configTypesReady) {\n try {\n await regenerateConfigTypes(projectDir, configTypesReady, {\n extraSkillIds: [name],\n extraDomains: [domain],\n extraCategories: [category],\n });\n } catch (error) {\n this.warn(\n `Could not update ${STANDARD_FILES.CONFIG_TYPES_TS}: ${getErrorMessage(error)}`,\n );\n }\n }\n\n this.log(\"\");\n this.log(\n `Skill created successfully! Run '${CLI_BIN_NAME} compile' to include it in your agents.`,\n );\n this.log(\"\");\n } catch (error) {\n this.handleError(error);\n }\n }\n}\n\ntype ScaffoldSkillOptions = {\n name: string;\n author: string;\n category: CategoryPath;\n domain: string;\n skillDir: string;\n};\n\ntype ScaffoldSkillResult = {\n skillMdPath: string;\n metadataPath: string;\n contentHash: string;\n};\n\ntype RegistryUpdateOptions = {\n projectRoot: string;\n category: CategoryPath;\n domain: string;\n};\n\ntype RegistryUpdateResult = {\n categoriesCreated: boolean;\n categoriesUpdated: boolean;\n rulesCreated: boolean;\n};\n\nexport function validateSkillName(name: string): string | null {\n if (!name || name.trim() === \"\") {\n return \"Skill name is required\";\n }\n\n if (!KEBAB_CASE_PATTERN.test(name)) {\n return \"Skill name must be kebab-case (lowercase letters, numbers, and hyphens, starting with a letter)\";\n }\n\n return null;\n}\n\nexport function generateSkillMd(name: string): string {\n const titleName = toTitleCase(name);\n\n return `---\nname: ${name}\ndescription: Brief description of this skill\n---\n\n# ${titleName}\n\n> **Quick Guide:** Add a brief summary of what this skill teaches.\n\n---\n\n<critical_requirements>\n\n## CRITICAL: Before Using This Skill\n\n**(Add critical requirements here)**\n\n</critical_requirements>\n\n---\n\n**When to use:**\n\n- Add use cases here\n\n**Key patterns covered:**\n\n- Add patterns here\n\n---\n\n<patterns>\n\n## Core Patterns\n\n### Pattern 1: Example Pattern\n\nAdd your patterns here.\n\n</patterns>\n\n---\n\n<critical_reminders>\n\n## CRITICAL REMINDERS\n\n**(Repeat critical requirements here)**\n\n</critical_reminders>\n`;\n}\n\nexport function generateMetadataYaml(\n name: string,\n author: string,\n category: CategoryPath,\n contentHash: string,\n domain: string,\n): string {\n const titleName = toTitleCase(name);\n\n return `# yaml-language-server: $schema=https://raw.githubusercontent.com/agents-inc/cli/main/src/schemas/custom-metadata.schema.json\ncustom: true\ndomain: ${domain}\ncategory: ${category}\nauthor: \"${author}\"\ndisplayName: ${titleName}\nslug: ${name}\ncliDescription: Brief description\nusageGuidance: Use when <guidance>.\ncontentHash: ${contentHash}\n`;\n}\n\nasync function scaffoldSkillFiles(options: ScaffoldSkillOptions): Promise<ScaffoldSkillResult> {\n const { name, author, category, domain, skillDir } = options;\n\n const skillMdContent = generateSkillMd(name);\n const skillMdPath = path.join(skillDir, STANDARD_FILES.SKILL_MD);\n const metadataPath = path.join(skillDir, STANDARD_FILES.METADATA_YAML);\n\n await writeFile(skillMdPath, skillMdContent);\n\n const contentHash = await computeSkillFolderHash(skillDir);\n const metadataContent = generateMetadataYaml(name, author, category, contentHash, domain);\n await writeFile(metadataPath, metadataContent);\n\n return { skillMdPath, metadataPath, contentHash };\n}\n\nasync function updateSkillRegistryConfig(\n options: RegistryUpdateOptions,\n): Promise<RegistryUpdateResult> {\n const { projectRoot, category, domain } = options;\n\n const categoriesPath = path.join(projectRoot, SKILL_CATEGORIES_PATH);\n const rulesPath = path.join(projectRoot, SKILL_RULES_PATH);\n\n let categoriesCreated = false;\n let categoriesUpdated = false;\n let rulesCreated = false;\n\n if (await fileExists(categoriesPath)) {\n // Boundary cast: loadConfig returns unknown structure from TS file\n const parsed = (await loadConfig<Record<string, unknown>>(categoriesPath)) ?? {};\n const categories = (parsed.categories ?? {}) as Record<string, unknown>;\n if (!categories[category]) {\n categories[category] = buildCategoryEntry(category, domain);\n parsed.categories = categories;\n await writeFile(categoriesPath, formatTsExport(CATEGORIES_TS_COMMENT, parsed));\n verbose(`Added category '${category}' to ${SKILL_CATEGORIES_PATH}`);\n categoriesUpdated = true;\n }\n } else {\n await ensureDir(path.dirname(categoriesPath));\n await writeFile(categoriesPath, generateSkillCategoriesTs(category, domain));\n verbose(`Created ${SKILL_CATEGORIES_PATH}`);\n categoriesCreated = true;\n }\n\n if (!(await fileExists(rulesPath))) {\n await ensureDir(path.dirname(rulesPath));\n await writeFile(rulesPath, generateSkillRulesTs());\n verbose(`Created ${SKILL_RULES_PATH}`);\n rulesCreated = true;\n }\n\n return { categoriesCreated, categoriesUpdated, rulesCreated };\n}\n\nconst CATEGORIES_TS_COMMENT = \"// Skill category definitions\";\n"],"mappings":"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","names":[]}
|
|
@@ -3,10 +3,8 @@ import {
|
|
|
3
3
|
compareSkillsWithSource,
|
|
4
4
|
detectProject,
|
|
5
5
|
loadSource
|
|
6
|
-
} from "../chunk-
|
|
6
|
+
} from "../chunk-5UJJQFET.js";
|
|
7
7
|
import "../chunk-N6A7A4RA.js";
|
|
8
|
-
import "../chunk-O5ZWS26C.js";
|
|
9
|
-
import "../chunk-XQK4S22C.js";
|
|
10
8
|
import "../chunk-FBZR46GC.js";
|
|
11
9
|
import "../chunk-TMTUTUEV.js";
|
|
12
10
|
import "../chunk-B6MYECV6.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/cli/commands/outdated.ts"],"sourcesContent":["import { Flags } from \"@oclif/core\";\nimport { printTable } from \"@oclif/table\";\nimport os from \"os\";\nimport path from \"path\";\nimport { countBy } from \"remeda\";\n\nimport { BaseCommand } from \"../base-command.js\";\nimport { getErrorMessage } from \"../utils/errors.js\";\nimport { EXIT_CODES } from \"../lib/exit-codes.js\";\nimport { loadSource, compareSkillsWithSource, detectProject } from \"../lib/operations/index.js\";\nimport { type SkillComparisonResult } from \"../lib/skills/index.js\";\nimport { fileExists } from \"../utils/fs.js\";\nimport { CLI_BIN_NAME, LOCAL_SKILLS_PATH } from \"../consts.js\";\n\ntype ComparisonSummary = {\n outdated: number;\n current: number;\n localOnly: number;\n};\n\nfunction calculateSummary(results: SkillComparisonResult[]): ComparisonSummary {\n const counts = countBy(results, (r) => r.status);\n return {\n outdated: counts[\"outdated\"] ?? 0,\n current: counts[\"current\"] ?? 0,\n localOnly: counts[\"local-only\"] ?? 0,\n };\n}\n\nfunction formatHash(hash: string | null, isLocal: boolean): string {\n if (hash === null) {\n return isLocal ? \"(local)\" : \"-\";\n }\n return hash;\n}\n\nexport default class Outdated extends BaseCommand {\n static summary = \"Check which local skills are out of date compared to source\";\n static description =\n \"Compare local skills against their source repository to identify outdated skills that need updating\";\n\n static examples = [\n {\n description: \"Check for outdated skills\",\n command: \"<%= config.bin %> <%= command.id %>\",\n },\n {\n description: \"Output results as JSON\",\n command: \"<%= config.bin %> <%= command.id %> --json\",\n },\n {\n description: \"Check against a custom source\",\n command: \"<%= config.bin %> <%= command.id %> --source github:org/marketplace\",\n },\n ];\n\n static flags = {\n ...BaseCommand.baseFlags,\n json: Flags.boolean({\n description: \"Output results as JSON\",\n default: false,\n }),\n };\n\n async run(): Promise<void> {\n const { flags } = await this.parse(Outdated);\n const detected = await detectProject();\n const projectDir = detected?.installation.projectDir ?? process.cwd();\n\n try {\n const projectLocalPath = path.join(projectDir, LOCAL_SKILLS_PATH);\n const homeDir = os.homedir();\n const globalLocalPath = path.join(homeDir, LOCAL_SKILLS_PATH);\n const hasProject = await fileExists(projectLocalPath);\n const hasGlobal = projectDir !== homeDir && (await fileExists(globalLocalPath));\n\n if (!hasProject && !hasGlobal) {\n if (flags.json) {\n this.log(\n JSON.stringify({\n skills: [],\n summary: { outdated: 0, current: 0, localOnly: 0 },\n }),\n );\n } else {\n this.warn(\n `No local skills found. Run \\`${CLI_BIN_NAME} init\\` or \\`${CLI_BIN_NAME} edit\\` first.`,\n );\n }\n return;\n }\n\n if (!flags.json) {\n this.log(\"Loading skills...\");\n }\n\n const { sourceResult } = await loadSource({\n sourceFlag: flags.source,\n projectDir,\n });\n const { matrix, sourcePath, isLocal } = sourceResult;\n\n if (!flags.json) {\n this.log(`Loaded from ${isLocal ? \"local\" : \"remote\"}: ${sourcePath}`);\n }\n\n const { merged: results } = await compareSkillsWithSource(projectDir, sourcePath, matrix);\n const summary = calculateSummary(results);\n\n if (flags.json) {\n this.log(\n JSON.stringify(\n {\n skills: results.map((r) => ({\n id: r.id,\n localHash: r.localHash,\n sourceHash: r.sourceHash,\n status: r.status,\n })),\n summary: {\n outdated: summary.outdated,\n current: summary.current,\n localOnly: summary.localOnly,\n },\n },\n null,\n 2,\n ),\n );\n } else {\n this.log(\"\");\n if (results.length === 0) {\n this.logInfo(\"No local skills found to compare.\");\n } else {\n printTable({\n data: results.map((result) => ({\n skill: result.id,\n localHash: formatHash(result.localHash, true),\n sourceHash: formatHash(result.sourceHash, false),\n status: result.status,\n })),\n columns: [\n { key: \"skill\", name: \"Skill\" },\n { key: \"localHash\", name: \"Local Hash\" },\n { key: \"sourceHash\", name: \"Source Hash\" },\n { key: \"status\", name: \"Status\" },\n ],\n headerOptions: { bold: true },\n });\n\n this.log(\"\");\n\n const parts: string[] = [];\n if (summary.outdated > 0) {\n parts.push(`${summary.outdated} outdated`);\n }\n if (summary.current > 0) {\n parts.push(`${summary.current} current`);\n }\n if (summary.localOnly > 0) {\n parts.push(`${summary.localOnly} local-only`);\n }\n this.log(`Summary: ${parts.join(\", \")}`);\n }\n this.log(\"\");\n }\n\n if (summary.outdated > 0) {\n this.error(\"Some skills are outdated\", { exit: EXIT_CODES.ERROR });\n }\n } catch (error) {\n const message = getErrorMessage(error);\n\n if (flags.json) {\n this.error(JSON.stringify({ error: message }), {\n exit: EXIT_CODES.ERROR,\n });\n } else {\n this.error(`Error: ${message}`, { exit: EXIT_CODES.ERROR });\n }\n }\n }\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../../src/cli/commands/outdated.ts"],"sourcesContent":["import { Flags } from \"@oclif/core\";\nimport { printTable } from \"@oclif/table\";\nimport os from \"os\";\nimport path from \"path\";\nimport { countBy } from \"remeda\";\n\nimport { BaseCommand } from \"../base-command.js\";\nimport { getErrorMessage } from \"../utils/errors.js\";\nimport { EXIT_CODES } from \"../lib/exit-codes.js\";\nimport { loadSource, compareSkillsWithSource, detectProject } from \"../lib/operations/index.js\";\nimport { type SkillComparisonResult } from \"../lib/skills/index.js\";\nimport { fileExists } from \"../utils/fs.js\";\nimport { CLI_BIN_NAME, LOCAL_SKILLS_PATH } from \"../consts.js\";\n\ntype ComparisonSummary = {\n outdated: number;\n current: number;\n localOnly: number;\n};\n\nfunction calculateSummary(results: SkillComparisonResult[]): ComparisonSummary {\n const counts = countBy(results, (r) => r.status);\n return {\n outdated: counts[\"outdated\"] ?? 0,\n current: counts[\"current\"] ?? 0,\n localOnly: counts[\"local-only\"] ?? 0,\n };\n}\n\nfunction formatHash(hash: string | null, isLocal: boolean): string {\n if (hash === null) {\n return isLocal ? \"(local)\" : \"-\";\n }\n return hash;\n}\n\nexport default class Outdated extends BaseCommand {\n static summary = \"Check which local skills are out of date compared to source\";\n static description =\n \"Compare local skills against their source repository to identify outdated skills that need updating\";\n\n static examples = [\n {\n description: \"Check for outdated skills\",\n command: \"<%= config.bin %> <%= command.id %>\",\n },\n {\n description: \"Output results as JSON\",\n command: \"<%= config.bin %> <%= command.id %> --json\",\n },\n {\n description: \"Check against a custom source\",\n command: \"<%= config.bin %> <%= command.id %> --source github:org/marketplace\",\n },\n ];\n\n static flags = {\n ...BaseCommand.baseFlags,\n json: Flags.boolean({\n description: \"Output results as JSON\",\n default: false,\n }),\n };\n\n async run(): Promise<void> {\n const { flags } = await this.parse(Outdated);\n const detected = await detectProject();\n const projectDir = detected?.installation.projectDir ?? process.cwd();\n\n try {\n const projectLocalPath = path.join(projectDir, LOCAL_SKILLS_PATH);\n const homeDir = os.homedir();\n const globalLocalPath = path.join(homeDir, LOCAL_SKILLS_PATH);\n const hasProject = await fileExists(projectLocalPath);\n const hasGlobal = projectDir !== homeDir && (await fileExists(globalLocalPath));\n\n if (!hasProject && !hasGlobal) {\n if (flags.json) {\n this.log(\n JSON.stringify({\n skills: [],\n summary: { outdated: 0, current: 0, localOnly: 0 },\n }),\n );\n } else {\n this.warn(\n `No local skills found. Run \\`${CLI_BIN_NAME} init\\` or \\`${CLI_BIN_NAME} edit\\` first.`,\n );\n }\n return;\n }\n\n if (!flags.json) {\n this.log(\"Loading skills...\");\n }\n\n const { sourceResult } = await loadSource({\n sourceFlag: flags.source,\n projectDir,\n });\n const { matrix, sourcePath, isLocal } = sourceResult;\n\n if (!flags.json) {\n this.log(`Loaded from ${isLocal ? \"local\" : \"remote\"}: ${sourcePath}`);\n }\n\n const { merged: results } = await compareSkillsWithSource(projectDir, sourcePath, matrix);\n const summary = calculateSummary(results);\n\n if (flags.json) {\n this.log(\n JSON.stringify(\n {\n skills: results.map((r) => ({\n id: r.id,\n localHash: r.localHash,\n sourceHash: r.sourceHash,\n status: r.status,\n })),\n summary: {\n outdated: summary.outdated,\n current: summary.current,\n localOnly: summary.localOnly,\n },\n },\n null,\n 2,\n ),\n );\n } else {\n this.log(\"\");\n if (results.length === 0) {\n this.logInfo(\"No local skills found to compare.\");\n } else {\n printTable({\n data: results.map((result) => ({\n skill: result.id,\n localHash: formatHash(result.localHash, true),\n sourceHash: formatHash(result.sourceHash, false),\n status: result.status,\n })),\n columns: [\n { key: \"skill\", name: \"Skill\" },\n { key: \"localHash\", name: \"Local Hash\" },\n { key: \"sourceHash\", name: \"Source Hash\" },\n { key: \"status\", name: \"Status\" },\n ],\n headerOptions: { bold: true },\n });\n\n this.log(\"\");\n\n const parts: string[] = [];\n if (summary.outdated > 0) {\n parts.push(`${summary.outdated} outdated`);\n }\n if (summary.current > 0) {\n parts.push(`${summary.current} current`);\n }\n if (summary.localOnly > 0) {\n parts.push(`${summary.localOnly} local-only`);\n }\n this.log(`Summary: ${parts.join(\", \")}`);\n }\n this.log(\"\");\n }\n\n if (summary.outdated > 0) {\n this.error(\"Some skills are outdated\", { exit: EXIT_CODES.ERROR });\n }\n } catch (error) {\n const message = getErrorMessage(error);\n\n if (flags.json) {\n this.error(JSON.stringify({ error: message }), {\n exit: EXIT_CODES.ERROR,\n });\n } else {\n this.error(`Error: ${message}`, { exit: EXIT_CODES.ERROR });\n }\n }\n }\n}\n"],"mappings":"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","names":[]}
|