@tacuchi/agent-workflow-cli 16.2.0 → 17.0.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/README.md +13 -0
- package/dist/adapters/node-file-system.d.ts +3 -1
- package/dist/adapters/node-file-system.d.ts.map +1 -1
- package/dist/adapters/node-file-system.js +18 -1
- package/dist/adapters/node-file-system.js.map +1 -1
- package/dist/application/mcp-doctor-service.d.ts.map +1 -1
- package/dist/application/mcp-doctor-service.js +3 -2
- package/dist/application/mcp-doctor-service.js.map +1 -1
- package/dist/application/mcp-host-writer.d.ts +1 -1
- package/dist/application/mcp-host-writer.d.ts.map +1 -1
- package/dist/application/mcp-host-writer.js +40 -10
- package/dist/application/mcp-host-writer.js.map +1 -1
- package/dist/application/mcp-remove-service.d.ts.map +1 -1
- package/dist/application/mcp-remove-service.js +3 -2
- package/dist/application/mcp-remove-service.js.map +1 -1
- package/dist/application/mcp-setup-service.d.ts.map +1 -1
- package/dist/application/mcp-setup-service.js +3 -2
- package/dist/application/mcp-setup-service.js.map +1 -1
- package/dist/application/self/install-plugin-skills-git.d.ts +1 -0
- package/dist/application/self/install-plugin-skills-git.d.ts.map +1 -1
- package/dist/application/self/install-plugin-skills-git.js +11 -2
- package/dist/application/self/install-plugin-skills-git.js.map +1 -1
- package/dist/application/self/install-plugin-skills.d.ts +6 -0
- package/dist/application/self/install-plugin-skills.d.ts.map +1 -1
- package/dist/application/self/install-plugin-skills.js +12 -3
- package/dist/application/self/install-plugin-skills.js.map +1 -1
- package/dist/application/self/mcp-config.d.ts +2 -0
- package/dist/application/self/mcp-config.d.ts.map +1 -1
- package/dist/application/self/mcp-config.js +29 -12
- package/dist/application/self/mcp-config.js.map +1 -1
- package/dist/application/self/skills-manager.d.ts +101 -0
- package/dist/application/self/skills-manager.d.ts.map +1 -0
- package/dist/application/self/skills-manager.js +543 -0
- package/dist/application/self/skills-manager.js.map +1 -0
- package/dist/application/self/skills-registry.d.ts +31 -0
- package/dist/application/self/skills-registry.d.ts.map +1 -0
- package/dist/application/self/skills-registry.js +64 -0
- package/dist/application/self/skills-registry.js.map +1 -0
- package/dist/cli/tui/app.js +5 -2
- package/dist/cli/tui/app.js.map +1 -1
- package/dist/cli/tui/components/focus-row.d.ts +1 -1
- package/dist/cli/tui/components/focus-row.js +1 -1
- package/dist/cli/tui/components/host-admin-section.d.ts +22 -0
- package/dist/cli/tui/components/host-admin-section.d.ts.map +1 -0
- package/dist/cli/tui/components/host-admin-section.js +321 -0
- package/dist/cli/tui/components/host-admin-section.js.map +1 -0
- package/dist/cli/tui/components/tabs-config.js +1 -1
- package/dist/cli/tui/components/tabs-config.js.map +1 -1
- package/dist/cli/tui/data/recommended-skills.d.ts +3 -0
- package/dist/cli/tui/data/recommended-skills.d.ts.map +1 -0
- package/dist/cli/tui/data/recommended-skills.js +52 -0
- package/dist/cli/tui/data/recommended-skills.js.map +1 -0
- package/dist/cli/tui/data/workflow-content.d.ts +5 -4
- package/dist/cli/tui/data/workflow-content.d.ts.map +1 -1
- package/dist/cli/tui/data/workflow-content.js +14 -134
- package/dist/cli/tui/data/workflow-content.js.map +1 -1
- package/dist/cli/tui/tabs/mcp-tab-helpers.d.ts +14 -7
- package/dist/cli/tui/tabs/mcp-tab-helpers.d.ts.map +1 -1
- package/dist/cli/tui/tabs/mcp-tab-helpers.js +16 -5
- package/dist/cli/tui/tabs/mcp-tab-helpers.js.map +1 -1
- package/dist/cli/tui/tabs/mcp-tab.d.ts.map +1 -1
- package/dist/cli/tui/tabs/mcp-tab.js +15 -13
- package/dist/cli/tui/tabs/mcp-tab.js.map +1 -1
- package/dist/cli/tui/tabs/skills-tab.d.ts +0 -1
- package/dist/cli/tui/tabs/skills-tab.d.ts.map +1 -1
- package/dist/cli/tui/tabs/skills-tab.js +272 -229
- package/dist/cli/tui/tabs/skills-tab.js.map +1 -1
- package/dist/cli/tui/tabs/status-tab.d.ts +1 -1
- package/dist/cli/tui/tabs/status-tab.d.ts.map +1 -1
- package/dist/cli/tui/tabs/status-tab.js +3 -2
- package/dist/cli/tui/tabs/status-tab.js.map +1 -1
- package/dist/cli/tui/tabs/workflow-tab.d.ts +6 -1
- package/dist/cli/tui/tabs/workflow-tab.d.ts.map +1 -1
- package/dist/cli/tui/tabs/workflow-tab.js +15 -28
- package/dist/cli/tui/tabs/workflow-tab.js.map +1 -1
- package/dist/domain/mcp-entry.d.ts +11 -0
- package/dist/domain/mcp-entry.d.ts.map +1 -1
- package/dist/domain/mcp-entry.js +13 -0
- package/dist/domain/mcp-entry.js.map +1 -1
- package/dist/ports/file-system.d.ts +13 -0
- package/dist/ports/file-system.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,543 @@
|
|
|
1
|
+
// Motor de skills sueltas (modelo skills.sh): canónica en ~/.agents/skills/<n>
|
|
2
|
+
// (el ancla del estándar abierto que escanean los hosts no-Claude) + réplica en
|
|
3
|
+
// ~/.claude/skills/<n> vía symlink, con fallback a copia (Windows sin links).
|
|
4
|
+
//
|
|
5
|
+
// El registro user-level (skills-registry.ts) es la fuente de verdad de QUÉ
|
|
6
|
+
// administra este motor. Guards de ownership (el motor escribe bajo el HOME
|
|
7
|
+
// real del usuario, donde también viven el bundle `w`, skills de plugins y
|
|
8
|
+
// skills manuales):
|
|
9
|
+
// - toda operación exige nombre registrado (SKILL_NOT_REGISTERED);
|
|
10
|
+
// - la canónica solo se crea/borra si este motor la materializó — señal:
|
|
11
|
+
// `installedAt` en el registro (SKILL_NAME_COLLISION al chocar con un dir
|
|
12
|
+
// ajeno; en uninstall/remove el dir ajeno se conserva con warning);
|
|
13
|
+
// - la réplica de Claude es nuestra solo si es un symlink QUE APUNTA a la
|
|
14
|
+
// canónica o un dir con mode:"copy" registrado (FOREIGN_REPLICA si no), y
|
|
15
|
+
// se verifica ANTES de mutar nada;
|
|
16
|
+
// - un registro ilegible (warning del read) aborta toda mutación: jamás se
|
|
17
|
+
// reescribe por encima de entradas que no se pudieron leer.
|
|
18
|
+
import { readFile, readdir, readlink, rename } from "node:fs/promises";
|
|
19
|
+
import { mkdtemp, rm } from "node:fs/promises";
|
|
20
|
+
import { tmpdir } from "node:os";
|
|
21
|
+
import { basename, isAbsolute, join, resolve } from "node:path";
|
|
22
|
+
import { gitClone } from "./install-plugin-skills-git.js";
|
|
23
|
+
import { copyDir, hasValidFrontmatter } from "./install-plugin-skills.js";
|
|
24
|
+
import { isValidSkillName, readSkillsRegistry, writeSkillsRegistry, } from "./skills-registry.js";
|
|
25
|
+
// skills/<categoría>/<skill> (mattpocock/skills) cabe en 3 niveles bajo la raíz.
|
|
26
|
+
const MAX_SCAN_DEPTH = 3;
|
|
27
|
+
export function canonicalSkillsRoot(home) {
|
|
28
|
+
return join(home, ".agents", "skills");
|
|
29
|
+
}
|
|
30
|
+
export function claudeReplicaRoot(home) {
|
|
31
|
+
return join(home, ".claude", "skills");
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Normaliza la fuente del usuario: URL git (con `#ref`), atajo `owner/repo`
|
|
35
|
+
* (→ GitHub) o path local absoluto. Paths relativos se rechazan a propósito:
|
|
36
|
+
* el registro debe poder resolverse desde cualquier cwd futuro.
|
|
37
|
+
*/
|
|
38
|
+
export function resolveSkillSource(raw, ref) {
|
|
39
|
+
const trimmed = raw.trim();
|
|
40
|
+
if (trimmed.length === 0)
|
|
41
|
+
return { error: "la fuente no puede estar vacía" };
|
|
42
|
+
// file:// cuenta como git (clone por transporte local) — permite registrar
|
|
43
|
+
// repos locales CON historial, a diferencia del path plano.
|
|
44
|
+
if (/^(https?:\/\/|git@|ssh:\/\/|file:\/\/)/.test(trimmed)) {
|
|
45
|
+
const hashIdx = trimmed.indexOf("#");
|
|
46
|
+
const url = hashIdx >= 0 ? trimmed.slice(0, hashIdx) : trimmed;
|
|
47
|
+
const parsedRef = ref ?? (hashIdx >= 0 ? trimmed.slice(hashIdx + 1) : undefined);
|
|
48
|
+
return { kind: "git", url, ...(parsedRef ? { ref: parsedRef } : {}) };
|
|
49
|
+
}
|
|
50
|
+
if (isAbsolute(trimmed))
|
|
51
|
+
return { kind: "local", path: trimmed };
|
|
52
|
+
// El atajo GitHub exige segmentos que arranquen alfanuméricos: "./x" o "../x"
|
|
53
|
+
// son paths relativos (rechazados), no owner/repo.
|
|
54
|
+
if (/^[A-Za-z0-9][\w.-]*\/[A-Za-z0-9][\w.-]*$/.test(trimmed)) {
|
|
55
|
+
return { kind: "git", url: `https://github.com/${trimmed}.git`, ...(ref ? { ref } : {}) };
|
|
56
|
+
}
|
|
57
|
+
return {
|
|
58
|
+
error: `fuente inválida: '${raw}'. Usá owner/repo, una URL git o un path local absoluto.`,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
async function isSkillDir(dir) {
|
|
62
|
+
try {
|
|
63
|
+
return hasValidFrontmatter(await readFile(join(dir, "SKILL.md"), "utf8"));
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
/** `name:` del frontmatter — el nombre real de la skill cuando la fuente ES un
|
|
70
|
+
* skill-dir (el basename de un clone temporal es aleatorio, jamás sirve). */
|
|
71
|
+
function frontmatterName(content) {
|
|
72
|
+
const block = content.match(/^---[ \t]*\r?\n([\s\S]*?)\r?\n---/)?.[1] ?? "";
|
|
73
|
+
return block.match(/^name:\s*(\S[^\r\n]*)/m)?.[1]?.trim() ?? null;
|
|
74
|
+
}
|
|
75
|
+
/** Walk acotado: skills anidadas hasta skills/<categoría>/<skill>; salta
|
|
76
|
+
* dot-dirs, node_modules y symlinks (Dirent de link no es isDirectory). */
|
|
77
|
+
async function walkSkillDirs(dir, depth) {
|
|
78
|
+
if (depth >= MAX_SCAN_DEPTH)
|
|
79
|
+
return [];
|
|
80
|
+
let entries;
|
|
81
|
+
try {
|
|
82
|
+
entries = await readdir(dir, { withFileTypes: true });
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
return [];
|
|
86
|
+
}
|
|
87
|
+
const out = [];
|
|
88
|
+
for (const entry of entries) {
|
|
89
|
+
if (!entry.isDirectory())
|
|
90
|
+
continue;
|
|
91
|
+
if (entry.name.startsWith(".") || entry.name === "node_modules")
|
|
92
|
+
continue;
|
|
93
|
+
const full = join(dir, entry.name);
|
|
94
|
+
if (await isSkillDir(full)) {
|
|
95
|
+
out.push({ name: entry.name, path: full });
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
out.push(...(await walkSkillDirs(full, depth + 1)));
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return out;
|
|
102
|
+
}
|
|
103
|
+
/** Skill dirs de una fuente: el dir mismo (si ES una skill, nombrado por su
|
|
104
|
+
* frontmatter) o el árbol; nombres duplicados o inválidos se descartan. */
|
|
105
|
+
async function collectCandidates(dir) {
|
|
106
|
+
if (await isSkillDir(dir)) {
|
|
107
|
+
const content = await readFile(join(dir, "SKILL.md"), "utf8");
|
|
108
|
+
const name = frontmatterName(content) ?? basename(dir);
|
|
109
|
+
return isValidSkillName(name) ? [{ name, path: dir }] : [];
|
|
110
|
+
}
|
|
111
|
+
const found = await walkSkillDirs(dir, 0);
|
|
112
|
+
const byName = new Map();
|
|
113
|
+
for (const c of found) {
|
|
114
|
+
if (!isValidSkillName(c.name) || byName.has(c.name))
|
|
115
|
+
continue;
|
|
116
|
+
byName.set(c.name, c);
|
|
117
|
+
}
|
|
118
|
+
return [...byName.values()];
|
|
119
|
+
}
|
|
120
|
+
/** Trae la fuente a un dir legible y lista sus skills (clone temp si es git). */
|
|
121
|
+
async function fetchSourceCandidates(resolved, ctx) {
|
|
122
|
+
if (resolved.kind === "local") {
|
|
123
|
+
if (!(await ctx.fs.exists(resolved.path))) {
|
|
124
|
+
return { code: "SOURCE_NOT_FOUND", error: `el path local '${resolved.path}' no existe` };
|
|
125
|
+
}
|
|
126
|
+
return { candidates: await collectCandidates(resolved.path), cleanup: async () => { } };
|
|
127
|
+
}
|
|
128
|
+
const temp = await mkdtemp(join(tmpdir(), "aw-skill-fetch-"));
|
|
129
|
+
const cleanup = async () => {
|
|
130
|
+
await rm(temp, { recursive: true, force: true }).catch(() => { });
|
|
131
|
+
};
|
|
132
|
+
try {
|
|
133
|
+
await gitClone(resolved.url, temp, resolved.ref);
|
|
134
|
+
}
|
|
135
|
+
catch (err) {
|
|
136
|
+
await cleanup();
|
|
137
|
+
return { code: "GIT_CLONE_FAILED", error: `git clone falló: ${err.message}` };
|
|
138
|
+
}
|
|
139
|
+
return { candidates: await collectCandidates(temp), cleanup };
|
|
140
|
+
}
|
|
141
|
+
/** Lectura previa a una mutación: un registro ilegible ABORTA — la primera
|
|
142
|
+
* escritura tras un read fallido pisaría todas las entradas previas. */
|
|
143
|
+
async function readRegistryForWrite(ctx) {
|
|
144
|
+
const read = await readSkillsRegistry(ctx);
|
|
145
|
+
if (read.warning) {
|
|
146
|
+
return {
|
|
147
|
+
code: "REGISTRY_UNREADABLE",
|
|
148
|
+
error: `${read.warning} Corregí (o borrá) el archivo antes de operar.`,
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
return { registry: read.registry };
|
|
152
|
+
}
|
|
153
|
+
/** Inspección sin efectos: lista las skills de una fuente para que el wizard
|
|
154
|
+
* muestre picker + warning de terceros ANTES de registrar nada. */
|
|
155
|
+
export async function probeSkillSource(ctx, input) {
|
|
156
|
+
const resolved = resolveSkillSource(input.source, input.ref);
|
|
157
|
+
if ("error" in resolved)
|
|
158
|
+
return fail("INVALID_SOURCE", resolved.error);
|
|
159
|
+
const fetched = await fetchSourceCandidates(resolved, ctx);
|
|
160
|
+
if ("error" in fetched)
|
|
161
|
+
return fail(fetched.code, fetched.error);
|
|
162
|
+
try {
|
|
163
|
+
if (fetched.candidates.length === 0) {
|
|
164
|
+
return fail("SOURCE_NOT_FOUND", `no se encontró ninguna skill válida (SKILL.md con name+description) en '${input.source}'`);
|
|
165
|
+
}
|
|
166
|
+
return {
|
|
167
|
+
ok: true,
|
|
168
|
+
data: { candidates: fetched.candidates.map((c) => c.name).sort() },
|
|
169
|
+
exitCode: 0,
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
finally {
|
|
173
|
+
await fetched.cleanup();
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
export async function registerSkill(ctx, input) {
|
|
177
|
+
const resolved = resolveSkillSource(input.source, input.ref);
|
|
178
|
+
if ("error" in resolved)
|
|
179
|
+
return fail("INVALID_SOURCE", resolved.error);
|
|
180
|
+
const fetched = await fetchSourceCandidates(resolved, ctx);
|
|
181
|
+
if ("error" in fetched)
|
|
182
|
+
return fail(fetched.code, fetched.error);
|
|
183
|
+
try {
|
|
184
|
+
const picked = pickCandidate(fetched.candidates, input);
|
|
185
|
+
if ("error" in picked)
|
|
186
|
+
return fail(picked.code, picked.error);
|
|
187
|
+
if ("candidates" in picked) {
|
|
188
|
+
return {
|
|
189
|
+
ok: true,
|
|
190
|
+
data: {
|
|
191
|
+
status: "needs-pick",
|
|
192
|
+
candidates: picked.candidates,
|
|
193
|
+
summary: `La fuente contiene ${picked.candidates.length} skills; elegí una para registrar.`,
|
|
194
|
+
},
|
|
195
|
+
exitCode: 0,
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
const read = await readRegistryForWrite(ctx);
|
|
199
|
+
if ("error" in read)
|
|
200
|
+
return fail(read.code, read.error);
|
|
201
|
+
const { registry } = read;
|
|
202
|
+
if (registry.skills[picked.name]) {
|
|
203
|
+
return fail("SKILL_ALREADY_REGISTERED", `'${picked.name}' ya está registrada (fuente: ${registry.skills[picked.name]?.source})`);
|
|
204
|
+
}
|
|
205
|
+
// Guard de ownership: un dir canónico existente NO registrado es de otro
|
|
206
|
+
// (bundle `w`, skill de plugin, instalación manual) — nunca lo adoptamos.
|
|
207
|
+
const canonical = join(canonicalSkillsRoot(ctx.env.homeDir()), picked.name);
|
|
208
|
+
if (await ctx.fs.exists(canonical)) {
|
|
209
|
+
return fail("SKILL_NAME_COLLISION", `ya existe ${canonical} y no está en el registro de sueltas — elegí otro nombre o resolvé la colisión a mano`);
|
|
210
|
+
}
|
|
211
|
+
const entry = {
|
|
212
|
+
source: resolved.kind === "git" ? (input.source.split("#")[0] ?? input.source) : resolved.path,
|
|
213
|
+
...(resolved.kind === "git" && resolved.ref ? { ref: resolved.ref } : {}),
|
|
214
|
+
};
|
|
215
|
+
registry.skills[picked.name] = entry;
|
|
216
|
+
await writeSkillsRegistry(ctx, registry);
|
|
217
|
+
return {
|
|
218
|
+
ok: true,
|
|
219
|
+
data: {
|
|
220
|
+
status: "registered",
|
|
221
|
+
name: picked.name,
|
|
222
|
+
entry,
|
|
223
|
+
summary: `Skill '${picked.name}' registrada desde ${entry.source}.`,
|
|
224
|
+
},
|
|
225
|
+
exitCode: 0,
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
finally {
|
|
229
|
+
await fetched.cleanup();
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
function pickCandidate(candidates, input) {
|
|
233
|
+
if (candidates.length === 0) {
|
|
234
|
+
return {
|
|
235
|
+
code: "SOURCE_NOT_FOUND",
|
|
236
|
+
error: `no se encontró ninguna skill válida (SKILL.md con name+description) en '${input.source}'`,
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
if (input.pick !== undefined) {
|
|
240
|
+
const found = candidates.find((c) => c.name === input.pick);
|
|
241
|
+
return (found ?? {
|
|
242
|
+
code: "INVALID_PICK",
|
|
243
|
+
error: `la fuente no contiene la skill '${input.pick}' (disponibles: ${candidates
|
|
244
|
+
.map((c) => c.name)
|
|
245
|
+
.sort()
|
|
246
|
+
.join(", ")})`,
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
if (candidates.length === 1 && candidates[0])
|
|
250
|
+
return candidates[0];
|
|
251
|
+
return { candidates: candidates.map((c) => c.name).sort() };
|
|
252
|
+
}
|
|
253
|
+
export async function installSkill(ctx, name, opts = { refetch: true }) {
|
|
254
|
+
const read = await readRegistryForWrite(ctx);
|
|
255
|
+
if ("error" in read)
|
|
256
|
+
return fail(read.code, read.error);
|
|
257
|
+
const entry = read.registry.skills[name];
|
|
258
|
+
if (!entry)
|
|
259
|
+
return notRegistered(name);
|
|
260
|
+
const home = ctx.env.homeDir();
|
|
261
|
+
const canonical = join(canonicalSkillsRoot(home), name);
|
|
262
|
+
// Pre-flight ANTES de mutar nada: réplica ajena o colisión de canónica
|
|
263
|
+
// abortan sin tocar la instalación previa ni el dir ajeno.
|
|
264
|
+
const replicaState = await inspectReplica(ctx, name, entry.mode);
|
|
265
|
+
if (replicaState === "foreign") {
|
|
266
|
+
return fail("FOREIGN_REPLICA", `ya existe ${join(claudeReplicaRoot(home), name)} y no lo creó este manager — resolvé la colisión a mano`);
|
|
267
|
+
}
|
|
268
|
+
if (opts.refetch && !entry.installedAt && (await ctx.fs.exists(canonical))) {
|
|
269
|
+
return fail("SKILL_NAME_COLLISION", `ya existe ${canonical} y este manager no lo materializó — resolvé la colisión a mano`);
|
|
270
|
+
}
|
|
271
|
+
if (opts.refetch) {
|
|
272
|
+
const resolved = resolveSkillSource(entry.source, entry.ref);
|
|
273
|
+
if ("error" in resolved)
|
|
274
|
+
return fail("INVALID_SOURCE", resolved.error);
|
|
275
|
+
const fetched = await fetchSourceCandidates(resolved, ctx);
|
|
276
|
+
if ("error" in fetched)
|
|
277
|
+
return fail("FETCH_FAILED", fetched.error);
|
|
278
|
+
try {
|
|
279
|
+
const skillDir = fetched.candidates.find((c) => c.name === name);
|
|
280
|
+
if (!skillDir) {
|
|
281
|
+
return fail("FETCH_FAILED", `la fuente '${entry.source}' ya no contiene la skill '${name}'`);
|
|
282
|
+
}
|
|
283
|
+
await materializeCanonical(ctx, skillDir.path, canonical, name);
|
|
284
|
+
}
|
|
285
|
+
catch (err) {
|
|
286
|
+
return fail("MATERIALIZE_FAILED", err.message);
|
|
287
|
+
}
|
|
288
|
+
finally {
|
|
289
|
+
await fetched.cleanup();
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
else if (!entry.installedAt || !(await ctx.fs.exists(canonical))) {
|
|
293
|
+
// Reinstall exige que ESTE manager haya materializado la canónica: sin
|
|
294
|
+
// installedAt, un dir homónimo existente es ajeno y no se replica.
|
|
295
|
+
return fail("SKILL_NOT_INSTALLED", `'${name}' no está instalada (no existe ${canonical} materializada por este manager); usá Install/Update`);
|
|
296
|
+
}
|
|
297
|
+
const replica = await replicateToClaude(ctx, name, replicaState);
|
|
298
|
+
// Re-leer antes de escribir: el clone puede tardar y otra invocación pudo
|
|
299
|
+
// tocar el registro en el medio — nunca escribir un snapshot viejo.
|
|
300
|
+
const fresh = await readRegistryForWrite(ctx);
|
|
301
|
+
if ("error" in fresh)
|
|
302
|
+
return fail(fresh.code, fresh.error);
|
|
303
|
+
const current = fresh.registry.skills[name] ?? entry;
|
|
304
|
+
fresh.registry.skills[name] = {
|
|
305
|
+
...current,
|
|
306
|
+
mode: replica.mode,
|
|
307
|
+
...(opts.refetch ? { installedAt: new Date().toISOString() } : {}),
|
|
308
|
+
};
|
|
309
|
+
await writeSkillsRegistry(ctx, fresh.registry);
|
|
310
|
+
return {
|
|
311
|
+
ok: true,
|
|
312
|
+
data: {
|
|
313
|
+
status: opts.refetch ? "installed" : "reinstalled",
|
|
314
|
+
name,
|
|
315
|
+
canonical,
|
|
316
|
+
replica: replica.path,
|
|
317
|
+
mode: replica.mode,
|
|
318
|
+
summary: `Skill '${name}' materializada en ${canonical} (réplica Claude: ${replica.mode}).`,
|
|
319
|
+
},
|
|
320
|
+
exitCode: 0,
|
|
321
|
+
};
|
|
322
|
+
}
|
|
323
|
+
/** Reinstall: repara canónica→réplica sin tocar la fuente (offline-safe). */
|
|
324
|
+
export async function reinstallSkill(ctx, name) {
|
|
325
|
+
return installSkill(ctx, name, { refetch: false });
|
|
326
|
+
}
|
|
327
|
+
/** Update: re-fetch del ref registrado; solo fuentes git. Staging+swap: un fallo
|
|
328
|
+
* de fetch deja la instalación previa intacta. */
|
|
329
|
+
export async function updateSkill(ctx, name) {
|
|
330
|
+
const read = await readRegistryForWrite(ctx);
|
|
331
|
+
if ("error" in read)
|
|
332
|
+
return fail(read.code, read.error);
|
|
333
|
+
const entry = read.registry.skills[name];
|
|
334
|
+
if (!entry)
|
|
335
|
+
return notRegistered(name);
|
|
336
|
+
const resolved = resolveSkillSource(entry.source, entry.ref);
|
|
337
|
+
if ("error" in resolved || resolved.kind !== "git") {
|
|
338
|
+
return fail("UPDATE_REQUIRES_GIT", `Update re-fetchea git; '${name}' viene de un path local — usá Reinstall (o re-registrá la fuente).`);
|
|
339
|
+
}
|
|
340
|
+
if (!(await ctx.fs.exists(join(canonicalSkillsRoot(ctx.env.homeDir()), name)))) {
|
|
341
|
+
return fail("SKILL_NOT_INSTALLED", `'${name}' no está instalada; usá Install`);
|
|
342
|
+
}
|
|
343
|
+
const result = await installSkill(ctx, name, { refetch: true });
|
|
344
|
+
if (!result.ok || !result.data)
|
|
345
|
+
return result;
|
|
346
|
+
return {
|
|
347
|
+
...result,
|
|
348
|
+
data: {
|
|
349
|
+
...result.data,
|
|
350
|
+
status: "updated",
|
|
351
|
+
summary: `Skill '${name}' actualizada (ref registrado re-fetcheado).`,
|
|
352
|
+
},
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
export async function uninstallSkill(ctx, name) {
|
|
356
|
+
const read = await readRegistryForWrite(ctx);
|
|
357
|
+
if ("error" in read)
|
|
358
|
+
return fail(read.code, read.error);
|
|
359
|
+
const entry = read.registry.skills[name];
|
|
360
|
+
if (!entry)
|
|
361
|
+
return notRegistered(name);
|
|
362
|
+
const warning = await teardownSkill(ctx, name, entry);
|
|
363
|
+
read.registry.skills[name] = {
|
|
364
|
+
source: entry.source,
|
|
365
|
+
...(entry.ref ? { ref: entry.ref } : {}),
|
|
366
|
+
};
|
|
367
|
+
await writeSkillsRegistry(ctx, read.registry);
|
|
368
|
+
return {
|
|
369
|
+
ok: true,
|
|
370
|
+
data: {
|
|
371
|
+
status: "uninstalled",
|
|
372
|
+
name,
|
|
373
|
+
...(warning ? { warning } : {}),
|
|
374
|
+
summary: `Skill '${name}' desinstalada; sigue registrada (fuente: ${entry.source}).`,
|
|
375
|
+
},
|
|
376
|
+
exitCode: 0,
|
|
377
|
+
};
|
|
378
|
+
}
|
|
379
|
+
export async function removeSkill(ctx, name) {
|
|
380
|
+
const read = await readRegistryForWrite(ctx);
|
|
381
|
+
if ("error" in read)
|
|
382
|
+
return fail(read.code, read.error);
|
|
383
|
+
const entry = read.registry.skills[name];
|
|
384
|
+
if (!entry)
|
|
385
|
+
return notRegistered(name);
|
|
386
|
+
const warning = await teardownSkill(ctx, name, entry);
|
|
387
|
+
delete read.registry.skills[name];
|
|
388
|
+
await writeSkillsRegistry(ctx, read.registry);
|
|
389
|
+
return {
|
|
390
|
+
ok: true,
|
|
391
|
+
data: {
|
|
392
|
+
status: "removed",
|
|
393
|
+
name,
|
|
394
|
+
...(warning ? { warning } : {}),
|
|
395
|
+
summary: `Skill '${name}' desinstalada y quitada del registro.`,
|
|
396
|
+
},
|
|
397
|
+
exitCode: 0,
|
|
398
|
+
};
|
|
399
|
+
}
|
|
400
|
+
/** Lista única para la TUI: registradas (instaladas o no) + semilla no registrada.
|
|
401
|
+
* Orden: installed → registered → recommended; alfabético dentro de cada grupo. */
|
|
402
|
+
export async function listSkills(ctx, seed) {
|
|
403
|
+
const { registry } = await readSkillsRegistry(ctx);
|
|
404
|
+
const home = ctx.env.homeDir();
|
|
405
|
+
const seedByName = new Map(seed.map((s) => [s.name, s]));
|
|
406
|
+
const items = [];
|
|
407
|
+
for (const [name, entry] of Object.entries(registry.skills)) {
|
|
408
|
+
const canonical = await ctx.fs.exists(join(canonicalSkillsRoot(home), name));
|
|
409
|
+
const replica = (await ctx.fs.lstat(join(claudeReplicaRoot(home), name))) !== null;
|
|
410
|
+
const description = seedByName.get(name)?.description;
|
|
411
|
+
items.push({
|
|
412
|
+
name,
|
|
413
|
+
source: entry.source,
|
|
414
|
+
...(entry.ref ? { ref: entry.ref } : {}),
|
|
415
|
+
...(entry.mode ? { mode: entry.mode } : {}),
|
|
416
|
+
...(entry.installedAt ? { installedAt: entry.installedAt } : {}),
|
|
417
|
+
...(description ? { description } : {}),
|
|
418
|
+
status: canonical ? "installed" : "registered",
|
|
419
|
+
replicas: { agents: canonical, claude: replica },
|
|
420
|
+
});
|
|
421
|
+
}
|
|
422
|
+
for (const s of seed) {
|
|
423
|
+
if (registry.skills[s.name])
|
|
424
|
+
continue;
|
|
425
|
+
items.push({
|
|
426
|
+
name: s.name,
|
|
427
|
+
source: s.source,
|
|
428
|
+
description: s.description,
|
|
429
|
+
status: "recommended",
|
|
430
|
+
replicas: { agents: false, claude: false },
|
|
431
|
+
});
|
|
432
|
+
}
|
|
433
|
+
const rank = { installed: 0, registered: 1, recommended: 2 };
|
|
434
|
+
return items.sort((a, b) => rank[a.status] - rank[b.status] || a.name.localeCompare(b.name));
|
|
435
|
+
}
|
|
436
|
+
// --- internos ---
|
|
437
|
+
/**
|
|
438
|
+
* Copia src a un staging oculto y lo intercambia con la canónica; el .bak solo
|
|
439
|
+
* se descarta cuando el swap completó — un fallo restaura el estado previo.
|
|
440
|
+
* `renameFn` es inyectable para poder testear la rama de restore.
|
|
441
|
+
*/
|
|
442
|
+
export async function materializeCanonical(ctx, srcDir, canonical, name, renameFn = rename) {
|
|
443
|
+
const root = canonicalSkillsRoot(ctx.env.homeDir());
|
|
444
|
+
await ctx.fs.mkdirp(root);
|
|
445
|
+
const staging = join(root, `.staging-${name}-${process.pid}`);
|
|
446
|
+
const bak = join(root, `.bak-${name}-${process.pid}`);
|
|
447
|
+
await ctx.fs.remove(staging);
|
|
448
|
+
try {
|
|
449
|
+
await copyDir(srcDir, staging);
|
|
450
|
+
const hadPrevious = await ctx.fs.exists(canonical);
|
|
451
|
+
if (hadPrevious)
|
|
452
|
+
await renameFn(canonical, bak);
|
|
453
|
+
try {
|
|
454
|
+
await renameFn(staging, canonical);
|
|
455
|
+
}
|
|
456
|
+
catch (err) {
|
|
457
|
+
if (hadPrevious)
|
|
458
|
+
await renameFn(bak, canonical).catch(() => { });
|
|
459
|
+
throw err;
|
|
460
|
+
}
|
|
461
|
+
if (hadPrevious)
|
|
462
|
+
await ctx.fs.remove(bak);
|
|
463
|
+
}
|
|
464
|
+
finally {
|
|
465
|
+
await ctx.fs.remove(staging);
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
/** Ownership de la réplica: nuestra solo si es un symlink que apunta a NUESTRA
|
|
469
|
+
* canónica, o un dir real con mode:"copy" registrado. Un symlink del usuario
|
|
470
|
+
* hacia otro lado es ajeno — jamás se re-apunta. */
|
|
471
|
+
async function inspectReplica(ctx, name, registeredMode) {
|
|
472
|
+
const home = ctx.env.homeDir();
|
|
473
|
+
const replica = join(claudeReplicaRoot(home), name);
|
|
474
|
+
const existing = await ctx.fs.lstat(replica);
|
|
475
|
+
if (!existing)
|
|
476
|
+
return "absent";
|
|
477
|
+
if (existing.isSymlink) {
|
|
478
|
+
try {
|
|
479
|
+
const target = await readlink(replica);
|
|
480
|
+
const canonical = join(canonicalSkillsRoot(home), name);
|
|
481
|
+
return resolve(join(claudeReplicaRoot(home)), target) === resolve(canonical)
|
|
482
|
+
? "ours"
|
|
483
|
+
: "foreign";
|
|
484
|
+
}
|
|
485
|
+
catch {
|
|
486
|
+
return "foreign";
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
return registeredMode === "copy" ? "ours" : "foreign";
|
|
490
|
+
}
|
|
491
|
+
/** Materializa la réplica (el pre-flight ya garantizó que no es ajena). */
|
|
492
|
+
async function replicateToClaude(ctx, name, state) {
|
|
493
|
+
const home = ctx.env.homeDir();
|
|
494
|
+
const canonical = join(canonicalSkillsRoot(home), name);
|
|
495
|
+
const replica = join(claudeReplicaRoot(home), name);
|
|
496
|
+
if (state === "ours")
|
|
497
|
+
await ctx.fs.remove(replica);
|
|
498
|
+
await ctx.fs.mkdirp(claudeReplicaRoot(home));
|
|
499
|
+
try {
|
|
500
|
+
await ctx.fs.symlink(canonical, replica);
|
|
501
|
+
return { path: replica, mode: "symlink" };
|
|
502
|
+
}
|
|
503
|
+
catch {
|
|
504
|
+
// Sin symlinks (Windows sin Developer Mode / EPERM) → copia real.
|
|
505
|
+
await copyDir(canonical, replica);
|
|
506
|
+
return { path: replica, mode: "copy" };
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
/** Desmonta réplica y canónica respetando ownership; devuelve warning si algo
|
|
510
|
+
* ajeno homónimo se conservó. */
|
|
511
|
+
async function teardownSkill(ctx, name, entry) {
|
|
512
|
+
const home = ctx.env.homeDir();
|
|
513
|
+
const warnings = [];
|
|
514
|
+
const replica = join(claudeReplicaRoot(home), name);
|
|
515
|
+
const replicaState = await inspectReplica(ctx, name, entry.mode);
|
|
516
|
+
if (replicaState === "ours")
|
|
517
|
+
await ctx.fs.remove(replica);
|
|
518
|
+
else if (replicaState === "foreign") {
|
|
519
|
+
warnings.push(`se conservó ${replica}: existe pero no lo creó este manager`);
|
|
520
|
+
}
|
|
521
|
+
const canonical = join(canonicalSkillsRoot(home), name);
|
|
522
|
+
if (entry.installedAt) {
|
|
523
|
+
await ctx.fs.remove(canonical);
|
|
524
|
+
}
|
|
525
|
+
else if (await ctx.fs.exists(canonical)) {
|
|
526
|
+
warnings.push(`se conservó ${canonical}: este manager no lo materializó`);
|
|
527
|
+
}
|
|
528
|
+
return warnings.length > 0 ? warnings.join(" · ") : undefined;
|
|
529
|
+
}
|
|
530
|
+
function notRegistered(name) {
|
|
531
|
+
return {
|
|
532
|
+
ok: false,
|
|
533
|
+
error: {
|
|
534
|
+
code: "SKILL_NOT_REGISTERED",
|
|
535
|
+
message: `'${name}' no está en el registro de sueltas — este manager no toca dirs que no registró (bundle w, skills de plugins o manuales).`,
|
|
536
|
+
},
|
|
537
|
+
exitCode: 1,
|
|
538
|
+
};
|
|
539
|
+
}
|
|
540
|
+
function fail(code, message) {
|
|
541
|
+
return { ok: false, error: { code, message }, exitCode: 1 };
|
|
542
|
+
}
|
|
543
|
+
//# sourceMappingURL=skills-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skills-manager.js","sourceRoot":"","sources":["../../../src/application/self/skills-manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { CliContext } from "../../cli/types.js";
|
|
2
|
+
export declare const SKILLS_REGISTRY_REL: readonly [".agents", ".skills-registry.json"];
|
|
3
|
+
export type SkillReplicaMode = "symlink" | "copy";
|
|
4
|
+
export interface SkillRegistryEntry {
|
|
5
|
+
/** Git URL, atajo `owner/repo` o path local absoluto. */
|
|
6
|
+
source: string;
|
|
7
|
+
/** Ref git registrado (branch/tag); update siempre re-fetchea ESTE ref. */
|
|
8
|
+
ref?: string;
|
|
9
|
+
/** Modo con que se materializó la réplica de Claude (fallback Windows = copy). */
|
|
10
|
+
mode?: SkillReplicaMode;
|
|
11
|
+
/** ISO timestamp del último install/update; ausente = registrada sin instalar. */
|
|
12
|
+
installedAt?: string;
|
|
13
|
+
}
|
|
14
|
+
export interface SkillsRegistry {
|
|
15
|
+
skills: Record<string, SkillRegistryEntry>;
|
|
16
|
+
}
|
|
17
|
+
export interface SkillsRegistryRead {
|
|
18
|
+
registry: SkillsRegistry;
|
|
19
|
+
path: string;
|
|
20
|
+
/** Presente si el archivo existía pero no parseó — se deja intacto (patrón lock). */
|
|
21
|
+
warning?: string;
|
|
22
|
+
}
|
|
23
|
+
export declare function skillsRegistryPath(home: string): string;
|
|
24
|
+
/**
|
|
25
|
+
* Un nombre de skill es un segmento de path seguro: el registro se joinea a
|
|
26
|
+
* rutas que luego se borran recursivamente — "..", separadores o vacíos jamás.
|
|
27
|
+
*/
|
|
28
|
+
export declare function isValidSkillName(name: string): boolean;
|
|
29
|
+
export declare function readSkillsRegistry(ctx: CliContext): Promise<SkillsRegistryRead>;
|
|
30
|
+
export declare function writeSkillsRegistry(ctx: CliContext, registry: SkillsRegistry): Promise<string>;
|
|
31
|
+
//# sourceMappingURL=skills-registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skills-registry.d.ts","sourceRoot":"","sources":["../../../src/application/self/skills-registry.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAErD,eAAO,MAAM,mBAAmB,+CAAgD,CAAC;AAEjF,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,MAAM,CAAC;AAElD,MAAM,WAAW,kBAAkB;IACjC,yDAAyD;IACzD,MAAM,EAAE,MAAM,CAAC;IACf,2EAA2E;IAC3E,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,kFAAkF;IAClF,IAAI,CAAC,EAAE,gBAAgB,CAAC;IACxB,kFAAkF;IAClF,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;CAC5C;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,cAAc,CAAC;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,qFAAqF;IACrF,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEvD;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEtD;AAED,wBAAsB,kBAAkB,CAAC,GAAG,EAAE,UAAU,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAmCrF;AAED,wBAAsB,mBAAmB,CACvC,GAAG,EAAE,UAAU,EACf,QAAQ,EAAE,cAAc,GACvB,OAAO,CAAC,MAAM,CAAC,CAKjB"}
|