@agents-inc/cli 0.86.0 → 0.88.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 +20 -0
- package/dist/{chunk-GED2F75H.js → chunk-23M3SPXX.js} +180 -124
- package/dist/chunk-23M3SPXX.js.map +1 -0
- package/dist/{chunk-ZOWRO7UQ.js → chunk-2DRPZXXK.js} +3 -3
- package/dist/{chunk-5M6Q5UQO.js → chunk-57KI55GJ.js} +2 -2
- package/dist/{chunk-HH3AWXF4.js → chunk-5IYZGJDW.js} +3 -3
- package/dist/{chunk-Q4DMIPZB.js → chunk-6YR2NEW3.js} +2 -2
- package/dist/{chunk-HU6XQVZL.js → chunk-AP4DLJDP.js} +1 -1
- package/dist/{chunk-HU6XQVZL.js.map → chunk-AP4DLJDP.js.map} +1 -1
- package/dist/{chunk-SGZOFIFF.js → chunk-ATPHV3MD.js} +2 -2
- package/dist/{chunk-HSLVCKVQ.js → chunk-DDCW4SKN.js} +3 -3
- package/dist/{chunk-TMTUTUEV.js → chunk-EADZIYQW.js} +12 -7
- package/dist/chunk-EADZIYQW.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-HZ2IBXVQ.js → chunk-ITBSJNIC.js} +3 -3
- package/dist/chunk-J6PI73YV.js +68 -0
- package/dist/chunk-J6PI73YV.js.map +1 -0
- package/dist/{chunk-BEFYAFGV.js → chunk-JNUFQBXX.js} +2 -2
- package/dist/chunk-LHUK5L6P.js +564 -0
- package/dist/chunk-LHUK5L6P.js.map +1 -0
- package/dist/{chunk-LZ7XQ3IU.js → chunk-MY4TVLRB.js} +2 -2
- package/dist/{chunk-I44YG6VI.js → chunk-PZBLGD7O.js} +5 -19
- package/dist/chunk-PZBLGD7O.js.map +1 -0
- package/dist/{chunk-HZQOFFKA.js → chunk-REZZSDXG.js} +10 -10
- package/dist/{chunk-O27WJ5KS.js → chunk-RWVF6DQE.js} +3 -3
- package/dist/{chunk-B6MYECV6.js → chunk-STMRDPGZ.js} +2 -2
- package/dist/{chunk-MMTMXLI4.js → chunk-TAPEVEET.js} +2 -2
- package/dist/{chunk-CXWBVBDM.js → chunk-VWTZOBBQ.js} +2 -2
- package/dist/{chunk-UNEJKTLP.js → chunk-WTPPVXJP.js} +3 -3
- package/dist/{chunk-FBZR46GC.js → chunk-YM3V4Q3W.js} +4 -4
- package/dist/{chunk-C5IYJ42F.js → chunk-ZFQTKY2S.js} +2 -2
- package/dist/{chunk-NUU3U43A.js → chunk-ZTRQO5CX.js} +2 -2
- package/dist/chunk-ZTRQO5CX.js.map +1 -0
- package/dist/commands/build/marketplace.js +3 -3
- package/dist/commands/build/plugins.js +5 -5
- package/dist/commands/build/stack.js +5 -5
- package/dist/commands/compile.js +31 -25
- package/dist/commands/compile.js.map +1 -1
- package/dist/commands/config/index.js +5 -5
- package/dist/commands/config/path.js +4 -4
- package/dist/commands/config/show.js +5 -5
- package/dist/commands/diff.js +685 -86
- package/dist/commands/diff.js.map +1 -1
- package/dist/commands/doctor.js +35 -63
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/edit.js +180 -48
- package/dist/commands/edit.js.map +1 -1
- package/dist/commands/eject.js +182 -32
- package/dist/commands/eject.js.map +1 -1
- package/dist/commands/import/skill.js +200 -36
- package/dist/commands/import/skill.js.map +1 -1
- package/dist/commands/info.js +46 -39
- package/dist/commands/info.js.map +1 -1
- package/dist/commands/init.js +19 -22
- package/dist/commands/list.js +4 -4
- package/dist/commands/new/agent.js +144 -48
- package/dist/commands/new/agent.js.map +1 -1
- package/dist/commands/new/marketplace.js +9 -9
- package/dist/commands/new/marketplace.js.map +1 -1
- package/dist/commands/new/skill.js +198 -34
- package/dist/commands/new/skill.js.map +1 -1
- package/dist/commands/outdated.js +6 -8
- package/dist/commands/outdated.js.map +1 -1
- package/dist/commands/search.js +165 -68
- package/dist/commands/search.js.map +1 -1
- package/dist/commands/uninstall.js +263 -65
- package/dist/commands/uninstall.js.map +1 -1
- package/dist/commands/update.js +236 -167
- package/dist/commands/update.js.map +1 -1
- package/dist/commands/validate.js +4 -4
- package/dist/components/skill-search/skill-search.js +1 -1
- package/dist/components/wizard/category-grid.test.js +7 -7
- package/dist/components/wizard/domain-selection.js +5 -5
- package/dist/components/wizard/help-modal.js +5 -5
- package/dist/components/wizard/source-grid.test.js +7 -7
- package/dist/components/wizard/stack-selection.js +5 -5
- package/dist/components/wizard/step-agents.js +5 -5
- package/dist/components/wizard/step-agents.test.js +8 -8
- package/dist/components/wizard/step-build.js +5 -5
- package/dist/components/wizard/step-build.test.js +7 -7
- package/dist/components/wizard/step-confirm.test.js +5 -5
- package/dist/components/wizard/step-settings.js +4 -4
- package/dist/components/wizard/step-settings.test.js +7 -7
- package/dist/components/wizard/step-sources.js +5 -5
- package/dist/components/wizard/step-sources.test.js +8 -8
- package/dist/components/wizard/step-stack.js +6 -6
- package/dist/components/wizard/step-stack.test.js +7 -7
- package/dist/components/wizard/wizard-layout.js +6 -6
- package/dist/components/wizard/wizard.js +14 -14
- package/dist/hooks/init.js +18 -20
- package/dist/hooks/init.js.map +1 -1
- package/dist/{loader-GSEGPK64.js → loader-SQOK2BF7.js} +3 -3
- package/dist/{source-loader-OGFTIRIX.js → source-loader-CCECAU5L.js} +4 -4
- package/dist/{source-manager-FMMDDVZA.js → source-manager-4P7MTZRR.js} +4 -4
- package/dist/stores/wizard-store.js +4 -4
- package/dist/stores/wizard-store.test.js +7 -7
- 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-I44YG6VI.js.map +0 -1
- package/dist/chunk-NUU3U43A.js.map +0 -1
- package/dist/chunk-O5ZWS26C.js +0 -166
- package/dist/chunk-O5ZWS26C.js.map +0 -1
- package/dist/chunk-TMTUTUEV.js.map +0 -1
- package/dist/chunk-XQK4S22C.js +0 -202
- package/dist/chunk-XQK4S22C.js.map +0 -1
- /package/dist/{chunk-ZOWRO7UQ.js.map → chunk-2DRPZXXK.js.map} +0 -0
- /package/dist/{chunk-5M6Q5UQO.js.map → chunk-57KI55GJ.js.map} +0 -0
- /package/dist/{chunk-HH3AWXF4.js.map → chunk-5IYZGJDW.js.map} +0 -0
- /package/dist/{chunk-Q4DMIPZB.js.map → chunk-6YR2NEW3.js.map} +0 -0
- /package/dist/{chunk-SGZOFIFF.js.map → chunk-ATPHV3MD.js.map} +0 -0
- /package/dist/{chunk-HSLVCKVQ.js.map → chunk-DDCW4SKN.js.map} +0 -0
- /package/dist/{chunk-HZ2IBXVQ.js.map → chunk-ITBSJNIC.js.map} +0 -0
- /package/dist/{chunk-BEFYAFGV.js.map → chunk-JNUFQBXX.js.map} +0 -0
- /package/dist/{chunk-LZ7XQ3IU.js.map → chunk-MY4TVLRB.js.map} +0 -0
- /package/dist/{chunk-HZQOFFKA.js.map → chunk-REZZSDXG.js.map} +0 -0
- /package/dist/{chunk-O27WJ5KS.js.map → chunk-RWVF6DQE.js.map} +0 -0
- /package/dist/{chunk-B6MYECV6.js.map → chunk-STMRDPGZ.js.map} +0 -0
- /package/dist/{chunk-MMTMXLI4.js.map → chunk-TAPEVEET.js.map} +0 -0
- /package/dist/{chunk-CXWBVBDM.js.map → chunk-VWTZOBBQ.js.map} +0 -0
- /package/dist/{chunk-UNEJKTLP.js.map → chunk-WTPPVXJP.js.map} +0 -0
- /package/dist/{chunk-FBZR46GC.js.map → chunk-YM3V4Q3W.js.map} +0 -0
- /package/dist/{chunk-C5IYJ42F.js.map → chunk-ZFQTKY2S.js.map} +0 -0
- /package/dist/{loader-GSEGPK64.js.map → loader-SQOK2BF7.js.map} +0 -0
- /package/dist/{source-loader-OGFTIRIX.js.map → source-loader-CCECAU5L.js.map} +0 -0
- /package/dist/{source-manager-FMMDDVZA.js.map → source-manager-4P7MTZRR.js.map} +0 -0
package/dist/chunk-O5ZWS26C.js
DELETED
|
@@ -1,166 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
IMPORT_DEFAULTS,
|
|
4
|
-
computeFileHash,
|
|
5
|
-
fetchFromSource,
|
|
6
|
-
getCurrentDate
|
|
7
|
-
} from "./chunk-TMTUTUEV.js";
|
|
8
|
-
import {
|
|
9
|
-
copy,
|
|
10
|
-
ensureDir,
|
|
11
|
-
fileExists,
|
|
12
|
-
importedSkillMetadataSchema,
|
|
13
|
-
listDirectories,
|
|
14
|
-
readFile,
|
|
15
|
-
warn,
|
|
16
|
-
writeFile
|
|
17
|
-
} from "./chunk-NUU3U43A.js";
|
|
18
|
-
import {
|
|
19
|
-
GITHUB_SOURCE,
|
|
20
|
-
STANDARD_FILES,
|
|
21
|
-
YAML_FORMATTING
|
|
22
|
-
} from "./chunk-6PGL2XMY.js";
|
|
23
|
-
import {
|
|
24
|
-
init_esm_shims
|
|
25
|
-
} from "./chunk-DHET7RCE.js";
|
|
26
|
-
|
|
27
|
-
// src/cli/lib/operations/import-skill.ts
|
|
28
|
-
init_esm_shims();
|
|
29
|
-
import path from "path";
|
|
30
|
-
import { parse as parseYaml, stringify as stringifyYaml } from "yaml";
|
|
31
|
-
function parseGitHubSource(source) {
|
|
32
|
-
if (source.startsWith(GITHUB_SOURCE.HTTPS_PREFIX)) {
|
|
33
|
-
const path2 = source.replace(GITHUB_SOURCE.HTTPS_PREFIX, "");
|
|
34
|
-
return {
|
|
35
|
-
gigetSource: `${GITHUB_SOURCE.GITHUB_PREFIX}${path2}`,
|
|
36
|
-
displaySource: source
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
|
-
if (source.startsWith(GITHUB_SOURCE.GITHUB_PREFIX) || source.startsWith(GITHUB_SOURCE.GH_PREFIX)) {
|
|
40
|
-
const normalized = source.startsWith(GITHUB_SOURCE.GH_PREFIX) ? GITHUB_SOURCE.GITHUB_PREFIX + source.slice(GITHUB_SOURCE.GH_PREFIX.length) : source;
|
|
41
|
-
return {
|
|
42
|
-
gigetSource: normalized,
|
|
43
|
-
displaySource: `${GITHUB_SOURCE.HTTPS_PREFIX}${normalized.replace(GITHUB_SOURCE.GITHUB_PREFIX, "")}`
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
if (source.includes("/") && !source.includes(":")) {
|
|
47
|
-
return {
|
|
48
|
-
gigetSource: `${GITHUB_SOURCE.GITHUB_PREFIX}${source}`,
|
|
49
|
-
displaySource: `${GITHUB_SOURCE.HTTPS_PREFIX}${source}`
|
|
50
|
-
};
|
|
51
|
-
}
|
|
52
|
-
return {
|
|
53
|
-
gigetSource: source,
|
|
54
|
-
displaySource: source
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
async function fetchSkillSource(options) {
|
|
58
|
-
const result = await fetchFromSource(options.gigetSource, {
|
|
59
|
-
forceRefresh: options.forceRefresh
|
|
60
|
-
});
|
|
61
|
-
return { path: result.path, fromCache: result.fromCache };
|
|
62
|
-
}
|
|
63
|
-
async function discoverValidSkills(skillsDir) {
|
|
64
|
-
const skillDirs = await listDirectories(skillsDir);
|
|
65
|
-
const validSkills = [];
|
|
66
|
-
for (const skillDir of skillDirs) {
|
|
67
|
-
const skillMdPath = path.join(skillsDir, skillDir, STANDARD_FILES.SKILL_MD);
|
|
68
|
-
if (await fileExists(skillMdPath)) {
|
|
69
|
-
validSkills.push(skillDir);
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
return validSkills.sort();
|
|
73
|
-
}
|
|
74
|
-
async function importSkillFromSource(options) {
|
|
75
|
-
const { sourcePath, destPath, skillName, displaySource } = options;
|
|
76
|
-
const skillMdPath = path.join(sourcePath, STANDARD_FILES.SKILL_MD);
|
|
77
|
-
if (!await fileExists(skillMdPath)) {
|
|
78
|
-
throw new Error(
|
|
79
|
-
`Missing required SKILL.md file at ${skillMdPath}
|
|
80
|
-
Every skill must have a SKILL.md file containing the skill's prompt content.
|
|
81
|
-
Create one with:
|
|
82
|
-
echo "# ${skillName}" > ${path.join(sourcePath, STANDARD_FILES.SKILL_MD)}`
|
|
83
|
-
);
|
|
84
|
-
}
|
|
85
|
-
const contentHash = await computeFileHash(skillMdPath);
|
|
86
|
-
await ensureDir(path.dirname(destPath));
|
|
87
|
-
await copy(sourcePath, destPath);
|
|
88
|
-
await injectImportedForkedFromMetadata(destPath, skillName, displaySource, contentHash);
|
|
89
|
-
}
|
|
90
|
-
async function injectImportedForkedFromMetadata(destPath, skillName, source, contentHash) {
|
|
91
|
-
const metadataYamlPath = path.join(destPath, STANDARD_FILES.METADATA_YAML);
|
|
92
|
-
const metadataJsonPath = path.join(destPath, STANDARD_FILES.METADATA_JSON);
|
|
93
|
-
const forkedFrom = {
|
|
94
|
-
source,
|
|
95
|
-
skillName,
|
|
96
|
-
contentHash,
|
|
97
|
-
date: getCurrentDate()
|
|
98
|
-
};
|
|
99
|
-
if (await fileExists(metadataYamlPath)) {
|
|
100
|
-
const rawContent = await readFile(metadataYamlPath);
|
|
101
|
-
const lines = rawContent.split("\n");
|
|
102
|
-
let yamlContent2 = rawContent;
|
|
103
|
-
let schemaComment = "";
|
|
104
|
-
if (lines[0]?.startsWith("# yaml-language-server:")) {
|
|
105
|
-
schemaComment = `${lines[0]}
|
|
106
|
-
`;
|
|
107
|
-
yamlContent2 = lines.slice(1).join("\n");
|
|
108
|
-
}
|
|
109
|
-
const raw = parseYaml(yamlContent2);
|
|
110
|
-
const parseResult = importedSkillMetadataSchema.safeParse(raw);
|
|
111
|
-
if (!parseResult.success) {
|
|
112
|
-
warn(
|
|
113
|
-
`Malformed metadata.yaml at ${metadataYamlPath} \u2014 existing fields may be lost
|
|
114
|
-
Validation errors: ${parseResult.error.issues.map((i) => i.message).join(", ")}
|
|
115
|
-
Expected fields: displayName (string), cliDescription (string), category (string)
|
|
116
|
-
Validate your YAML syntax at https://yamllint.com`
|
|
117
|
-
);
|
|
118
|
-
}
|
|
119
|
-
const metadata = parseResult.success ? parseResult.data : { forkedFrom: void 0 };
|
|
120
|
-
metadata.forkedFrom = forkedFrom;
|
|
121
|
-
const newYamlContent = stringifyYaml(metadata, {
|
|
122
|
-
lineWidth: YAML_FORMATTING.LINE_WIDTH_NONE
|
|
123
|
-
});
|
|
124
|
-
await writeFile(metadataYamlPath, schemaComment + newYamlContent);
|
|
125
|
-
return;
|
|
126
|
-
}
|
|
127
|
-
if (await fileExists(metadataJsonPath)) {
|
|
128
|
-
const rawContent = await readFile(metadataJsonPath);
|
|
129
|
-
let jsonParsed;
|
|
130
|
-
try {
|
|
131
|
-
jsonParsed = JSON.parse(rawContent);
|
|
132
|
-
} catch {
|
|
133
|
-
warn(
|
|
134
|
-
`Malformed JSON in ${metadataJsonPath} \u2014 skipping metadata injection
|
|
135
|
-
Common issues: trailing commas, unquoted keys, single quotes instead of double quotes
|
|
136
|
-
Validate your JSON at https://jsonlint.com`
|
|
137
|
-
);
|
|
138
|
-
return;
|
|
139
|
-
}
|
|
140
|
-
const jsonResult = importedSkillMetadataSchema.safeParse(jsonParsed);
|
|
141
|
-
const metadata = jsonResult.success ? jsonResult.data : { forkedFrom: void 0 };
|
|
142
|
-
metadata.forkedFrom = forkedFrom;
|
|
143
|
-
const yamlContent2 = stringifyYaml(metadata, { lineWidth: YAML_FORMATTING.LINE_WIDTH_NONE });
|
|
144
|
-
await writeFile(metadataYamlPath, yamlContent2);
|
|
145
|
-
return;
|
|
146
|
-
}
|
|
147
|
-
const minimalMetadata = {
|
|
148
|
-
displayName: skillName.split("-").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" "),
|
|
149
|
-
cliDescription: "Imported from third-party repository",
|
|
150
|
-
category: IMPORT_DEFAULTS.CATEGORY,
|
|
151
|
-
author: IMPORT_DEFAULTS.AUTHOR,
|
|
152
|
-
forkedFrom
|
|
153
|
-
};
|
|
154
|
-
const yamlContent = stringifyYaml(minimalMetadata, {
|
|
155
|
-
lineWidth: YAML_FORMATTING.LINE_WIDTH_NONE
|
|
156
|
-
});
|
|
157
|
-
await writeFile(metadataYamlPath, yamlContent);
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
export {
|
|
161
|
-
parseGitHubSource,
|
|
162
|
-
fetchSkillSource,
|
|
163
|
-
discoverValidSkills,
|
|
164
|
-
importSkillFromSource
|
|
165
|
-
};
|
|
166
|
-
//# sourceMappingURL=chunk-O5ZWS26C.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli/lib/operations/import-skill.ts"],"sourcesContent":["import path from \"path\";\nimport { parse as parseYaml, stringify as stringifyYaml } from \"yaml\";\nimport { fetchFromSource } from \"../loading/index.js\";\nimport { importedSkillMetadataSchema } from \"../schemas.js\";\nimport { getCurrentDate, computeFileHash } from \"../versioning.js\";\nimport {\n copy,\n fileExists,\n listDirectories,\n readFile,\n writeFile,\n ensureDir,\n} from \"../../utils/fs.js\";\nimport { warn } from \"../../utils/logger.js\";\nimport { GITHUB_SOURCE, STANDARD_FILES, YAML_FORMATTING } from \"../../consts.js\";\nimport { IMPORT_DEFAULTS } from \"../metadata-keys.js\";\n\n/**\n * Metadata for tracking third-party imports. Different from ForkedFromMetadata\n * in skill-metadata.ts which tracks internal fork lineage (uses skillId\n * instead of source/skillName).\n */\nexport type ImportedForkedFromMetadata = {\n source: string;\n skillName: string;\n contentHash: string;\n date: string;\n};\n\ntype SkillMetadata = {\n forkedFrom?: ImportedForkedFromMetadata;\n [key: string]: unknown;\n};\n\nexport type ParsedGitHubSource = {\n gigetSource: string;\n displaySource: string;\n};\n\nexport type FetchSourceOptions = {\n gigetSource: string;\n forceRefresh?: boolean;\n};\n\nexport type FetchedSource = {\n path: string;\n fromCache: boolean;\n};\n\nexport type ImportSkillOptions = {\n sourcePath: string;\n destPath: string;\n skillName: string;\n displaySource: string;\n};\n\nexport type ImportSkillResult = {\n imported: string[];\n skipped: string[];\n errors: Array<{ skillName: string; error: string }>;\n};\n\n/**\n * Parses various GitHub URL formats into a normalized giget source string\n * and a human-readable display URL.\n *\n * Supports: `https://github.com/owner/repo`, `github:owner/repo`,\n * `gh:owner/repo`, and bare `owner/repo` formats.\n */\nexport function parseGitHubSource(source: string): ParsedGitHubSource {\n if (source.startsWith(GITHUB_SOURCE.HTTPS_PREFIX)) {\n const path = source.replace(GITHUB_SOURCE.HTTPS_PREFIX, \"\");\n return {\n gigetSource: `${GITHUB_SOURCE.GITHUB_PREFIX}${path}`,\n displaySource: source,\n };\n }\n\n if (\n source.startsWith(GITHUB_SOURCE.GITHUB_PREFIX) ||\n source.startsWith(GITHUB_SOURCE.GH_PREFIX)\n ) {\n const normalized = source.startsWith(GITHUB_SOURCE.GH_PREFIX)\n ? GITHUB_SOURCE.GITHUB_PREFIX + source.slice(GITHUB_SOURCE.GH_PREFIX.length)\n : source;\n return {\n gigetSource: normalized,\n displaySource: `${GITHUB_SOURCE.HTTPS_PREFIX}${normalized.replace(GITHUB_SOURCE.GITHUB_PREFIX, \"\")}`,\n };\n }\n\n if (source.includes(\"/\") && !source.includes(\":\")) {\n return {\n gigetSource: `${GITHUB_SOURCE.GITHUB_PREFIX}${source}`,\n displaySource: `${GITHUB_SOURCE.HTTPS_PREFIX}${source}`,\n };\n }\n\n return {\n gigetSource: source,\n displaySource: source,\n };\n}\n\n/**\n * Fetches a source repository using giget. Wraps `fetchFromSource` from the\n * loading layer.\n */\nexport async function fetchSkillSource(options: FetchSourceOptions): Promise<FetchedSource> {\n const result = await fetchFromSource(options.gigetSource, {\n forceRefresh: options.forceRefresh,\n });\n return { path: result.path, fromCache: result.fromCache };\n}\n\n/**\n * Discovers valid skill directories within a source path by checking\n * for the presence of SKILL.md files.\n *\n * @returns Sorted list of directory names that contain a SKILL.md file.\n */\nexport async function discoverValidSkills(skillsDir: string): Promise<string[]> {\n const skillDirs = await listDirectories(skillsDir);\n const validSkills: string[] = [];\n\n for (const skillDir of skillDirs) {\n const skillMdPath = path.join(skillsDir, skillDir, STANDARD_FILES.SKILL_MD);\n if (await fileExists(skillMdPath)) {\n validSkills.push(skillDir);\n }\n }\n\n return validSkills.sort();\n}\n\n/**\n * Imports a single skill from a source directory into the destination.\n *\n * Validates that the source skill has a SKILL.md file, copies the directory,\n * and injects `forkedFrom` metadata into the destination's metadata.yaml.\n *\n * @throws {Error} If the source skill is missing a SKILL.md file.\n */\nexport async function importSkillFromSource(options: ImportSkillOptions): Promise<void> {\n const { sourcePath, destPath, skillName, displaySource } = options;\n const skillMdPath = path.join(sourcePath, STANDARD_FILES.SKILL_MD);\n\n if (!(await fileExists(skillMdPath))) {\n throw new Error(\n `Missing required SKILL.md file at ${skillMdPath}\\n` +\n `Every skill must have a SKILL.md file containing the skill's prompt content.\\n` +\n `Create one with:\\n` +\n ` echo \"# ${skillName}\" > ${path.join(sourcePath, STANDARD_FILES.SKILL_MD)}`,\n );\n }\n\n const contentHash = await computeFileHash(skillMdPath);\n\n await ensureDir(path.dirname(destPath));\n await copy(sourcePath, destPath);\n\n await injectImportedForkedFromMetadata(destPath, skillName, displaySource, contentHash);\n}\n\n/**\n * Injects `forkedFrom` metadata into a third-party imported skill's metadata.yaml.\n *\n * Handles three cases:\n * 1. Existing metadata.yaml — preserves fields, adds/overwrites forkedFrom\n * 2. Existing metadata.json — converts to YAML, adds forkedFrom\n * 3. No metadata file — creates minimal metadata.yaml with forkedFrom\n *\n * @remarks\n * Different from `injectForkedFromMetadata` in `skill-metadata.ts` which tracks\n * internal marketplace fork lineage using `skillId`. This function tracks\n * third-party imports using `source` + `skillName`.\n */\nasync function injectImportedForkedFromMetadata(\n destPath: string,\n skillName: string,\n source: string,\n contentHash: string,\n): Promise<void> {\n const metadataYamlPath = path.join(destPath, STANDARD_FILES.METADATA_YAML);\n const metadataJsonPath = path.join(destPath, STANDARD_FILES.METADATA_JSON);\n\n const forkedFrom: ImportedForkedFromMetadata = {\n source,\n skillName,\n contentHash,\n date: getCurrentDate(),\n };\n\n if (await fileExists(metadataYamlPath)) {\n const rawContent = await readFile(metadataYamlPath);\n const lines = rawContent.split(\"\\n\");\n let yamlContent = rawContent;\n let schemaComment = \"\";\n\n if (lines[0]?.startsWith(\"# yaml-language-server:\")) {\n schemaComment = `${lines[0]}\\n`;\n yamlContent = lines.slice(1).join(\"\\n\");\n }\n\n const raw = parseYaml(yamlContent);\n const parseResult = importedSkillMetadataSchema.safeParse(raw);\n if (!parseResult.success) {\n warn(\n `Malformed metadata.yaml at ${metadataYamlPath} — existing fields may be lost\\n` +\n ` Validation errors: ${parseResult.error.issues.map((i) => i.message).join(\", \")}\\n` +\n ` Expected fields: displayName (string), cliDescription (string), category (string)\\n` +\n ` Validate your YAML syntax at https://yamllint.com`,\n );\n }\n const metadata = parseResult.success\n ? (parseResult.data as SkillMetadata)\n : { forkedFrom: undefined };\n metadata.forkedFrom = forkedFrom;\n\n const newYamlContent = stringifyYaml(metadata, {\n lineWidth: YAML_FORMATTING.LINE_WIDTH_NONE,\n });\n await writeFile(metadataYamlPath, schemaComment + newYamlContent);\n return;\n }\n\n if (await fileExists(metadataJsonPath)) {\n const rawContent = await readFile(metadataJsonPath);\n let jsonParsed: unknown;\n try {\n jsonParsed = JSON.parse(rawContent);\n } catch {\n warn(\n `Malformed JSON in ${metadataJsonPath} — skipping metadata injection\\n` +\n ` Common issues: trailing commas, unquoted keys, single quotes instead of double quotes\\n` +\n ` Validate your JSON at https://jsonlint.com`,\n );\n return;\n }\n const jsonResult = importedSkillMetadataSchema.safeParse(jsonParsed);\n const metadata = jsonResult.success\n ? (jsonResult.data as SkillMetadata)\n : { forkedFrom: undefined };\n metadata.forkedFrom = forkedFrom;\n\n const yamlContent = stringifyYaml(metadata, { lineWidth: YAML_FORMATTING.LINE_WIDTH_NONE });\n await writeFile(metadataYamlPath, yamlContent);\n return;\n }\n\n const minimalMetadata: SkillMetadata = {\n displayName: skillName\n .split(\"-\")\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1))\n .join(\" \"),\n cliDescription: \"Imported from third-party repository\",\n category: IMPORT_DEFAULTS.CATEGORY,\n author: IMPORT_DEFAULTS.AUTHOR,\n forkedFrom,\n };\n\n const yamlContent = stringifyYaml(minimalMetadata, {\n lineWidth: YAML_FORMATTING.LINE_WIDTH_NONE,\n });\n await writeFile(metadataYamlPath, yamlContent);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA,OAAO,UAAU;AACjB,SAAS,SAAS,WAAW,aAAa,qBAAqB;AAoExD,SAAS,kBAAkB,QAAoC;AACpE,MAAI,OAAO,WAAW,cAAc,YAAY,GAAG;AACjD,UAAMA,QAAO,OAAO,QAAQ,cAAc,cAAc,EAAE;AAC1D,WAAO;AAAA,MACL,aAAa,GAAG,cAAc,aAAa,GAAGA,KAAI;AAAA,MAClD,eAAe;AAAA,IACjB;AAAA,EACF;AAEA,MACE,OAAO,WAAW,cAAc,aAAa,KAC7C,OAAO,WAAW,cAAc,SAAS,GACzC;AACA,UAAM,aAAa,OAAO,WAAW,cAAc,SAAS,IACxD,cAAc,gBAAgB,OAAO,MAAM,cAAc,UAAU,MAAM,IACzE;AACJ,WAAO;AAAA,MACL,aAAa;AAAA,MACb,eAAe,GAAG,cAAc,YAAY,GAAG,WAAW,QAAQ,cAAc,eAAe,EAAE,CAAC;AAAA,IACpG;AAAA,EACF;AAEA,MAAI,OAAO,SAAS,GAAG,KAAK,CAAC,OAAO,SAAS,GAAG,GAAG;AACjD,WAAO;AAAA,MACL,aAAa,GAAG,cAAc,aAAa,GAAG,MAAM;AAAA,MACpD,eAAe,GAAG,cAAc,YAAY,GAAG,MAAM;AAAA,IACvD;AAAA,EACF;AAEA,SAAO;AAAA,IACL,aAAa;AAAA,IACb,eAAe;AAAA,EACjB;AACF;AAMA,eAAsB,iBAAiB,SAAqD;AAC1F,QAAM,SAAS,MAAM,gBAAgB,QAAQ,aAAa;AAAA,IACxD,cAAc,QAAQ;AAAA,EACxB,CAAC;AACD,SAAO,EAAE,MAAM,OAAO,MAAM,WAAW,OAAO,UAAU;AAC1D;AAQA,eAAsB,oBAAoB,WAAsC;AAC9E,QAAM,YAAY,MAAM,gBAAgB,SAAS;AACjD,QAAM,cAAwB,CAAC;AAE/B,aAAW,YAAY,WAAW;AAChC,UAAM,cAAc,KAAK,KAAK,WAAW,UAAU,eAAe,QAAQ;AAC1E,QAAI,MAAM,WAAW,WAAW,GAAG;AACjC,kBAAY,KAAK,QAAQ;AAAA,IAC3B;AAAA,EACF;AAEA,SAAO,YAAY,KAAK;AAC1B;AAUA,eAAsB,sBAAsB,SAA4C;AACtF,QAAM,EAAE,YAAY,UAAU,WAAW,cAAc,IAAI;AAC3D,QAAM,cAAc,KAAK,KAAK,YAAY,eAAe,QAAQ;AAEjE,MAAI,CAAE,MAAM,WAAW,WAAW,GAAI;AACpC,UAAM,IAAI;AAAA,MACR,qCAAqC,WAAW;AAAA;AAAA;AAAA,YAGjC,SAAS,OAAO,KAAK,KAAK,YAAY,eAAe,QAAQ,CAAC;AAAA,IAC/E;AAAA,EACF;AAEA,QAAM,cAAc,MAAM,gBAAgB,WAAW;AAErD,QAAM,UAAU,KAAK,QAAQ,QAAQ,CAAC;AACtC,QAAM,KAAK,YAAY,QAAQ;AAE/B,QAAM,iCAAiC,UAAU,WAAW,eAAe,WAAW;AACxF;AAeA,eAAe,iCACb,UACA,WACA,QACA,aACe;AACf,QAAM,mBAAmB,KAAK,KAAK,UAAU,eAAe,aAAa;AACzE,QAAM,mBAAmB,KAAK,KAAK,UAAU,eAAe,aAAa;AAEzE,QAAM,aAAyC;AAAA,IAC7C;AAAA,IACA;AAAA,IACA;AAAA,IACA,MAAM,eAAe;AAAA,EACvB;AAEA,MAAI,MAAM,WAAW,gBAAgB,GAAG;AACtC,UAAM,aAAa,MAAM,SAAS,gBAAgB;AAClD,UAAM,QAAQ,WAAW,MAAM,IAAI;AACnC,QAAIC,eAAc;AAClB,QAAI,gBAAgB;AAEpB,QAAI,MAAM,CAAC,GAAG,WAAW,yBAAyB,GAAG;AACnD,sBAAgB,GAAG,MAAM,CAAC,CAAC;AAAA;AAC3B,MAAAA,eAAc,MAAM,MAAM,CAAC,EAAE,KAAK,IAAI;AAAA,IACxC;AAEA,UAAM,MAAM,UAAUA,YAAW;AACjC,UAAM,cAAc,4BAA4B,UAAU,GAAG;AAC7D,QAAI,CAAC,YAAY,SAAS;AACxB;AAAA,QACE,8BAA8B,gBAAgB;AAAA,uBACpB,YAAY,MAAM,OAAO,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;AAAA;AAAA;AAAA,MAGrF;AAAA,IACF;AACA,UAAM,WAAW,YAAY,UACxB,YAAY,OACb,EAAE,YAAY,OAAU;AAC5B,aAAS,aAAa;AAEtB,UAAM,iBAAiB,cAAc,UAAU;AAAA,MAC7C,WAAW,gBAAgB;AAAA,IAC7B,CAAC;AACD,UAAM,UAAU,kBAAkB,gBAAgB,cAAc;AAChE;AAAA,EACF;AAEA,MAAI,MAAM,WAAW,gBAAgB,GAAG;AACtC,UAAM,aAAa,MAAM,SAAS,gBAAgB;AAClD,QAAI;AACJ,QAAI;AACF,mBAAa,KAAK,MAAM,UAAU;AAAA,IACpC,QAAQ;AACN;AAAA,QACE,qBAAqB,gBAAgB;AAAA;AAAA;AAAA,MAGvC;AACA;AAAA,IACF;AACA,UAAM,aAAa,4BAA4B,UAAU,UAAU;AACnE,UAAM,WAAW,WAAW,UACvB,WAAW,OACZ,EAAE,YAAY,OAAU;AAC5B,aAAS,aAAa;AAEtB,UAAMA,eAAc,cAAc,UAAU,EAAE,WAAW,gBAAgB,gBAAgB,CAAC;AAC1F,UAAM,UAAU,kBAAkBA,YAAW;AAC7C;AAAA,EACF;AAEA,QAAM,kBAAiC;AAAA,IACrC,aAAa,UACV,MAAM,GAAG,EACT,IAAI,CAAC,SAAS,KAAK,OAAO,CAAC,EAAE,YAAY,IAAI,KAAK,MAAM,CAAC,CAAC,EAC1D,KAAK,GAAG;AAAA,IACX,gBAAgB;AAAA,IAChB,UAAU,gBAAgB;AAAA,IAC1B,QAAQ,gBAAgB;AAAA,IACxB;AAAA,EACF;AAEA,QAAM,cAAc,cAAc,iBAAiB;AAAA,IACjD,WAAW,gBAAgB;AAAA,EAC7B,CAAC;AACD,QAAM,UAAU,kBAAkB,WAAW;AAC/C;","names":["path","yamlContent"]}
|