ostacky 0.6.1 → 0.6.2

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/dist/cli.js CHANGED
@@ -173,2159 +173,2267 @@ var require_picocolors = __commonJS((exports, module) => {
173
173
  module.exports.createColors = createColors;
174
174
  });
175
175
 
176
- // node_modules/@clack/core/dist/index.mjs
177
- import { stdin as $, stdout as j } from "node:process";
178
- import * as f from "node:readline";
179
- import M from "node:readline";
180
- import { WriteStream as U } from "node:tty";
181
- function J({ onlyFirst: t = false } = {}) {
182
- const F = ["[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]+)*|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?(?:\\u0007|\\u001B\\u005C|\\u009C))", "(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-nq-uy=><~]))"].join("|");
183
- return new RegExp(F, t ? undefined : "g");
176
+ // src/security.ts
177
+ var exports_security = {};
178
+ __export(exports_security, {
179
+ verifyChecksum: () => verifyChecksum,
180
+ validateFilePath: () => validateFilePath,
181
+ sha256: () => sha256
182
+ });
183
+ import { createHash } from "crypto";
184
+ function validateFilePath(filePath) {
185
+ if (filePath.includes("..") || filePath.startsWith("/") || filePath.startsWith("\\") || /^[a-zA-Z]:/.test(filePath)) {
186
+ throw new Error(`Ruta de archivo inválida: "${filePath}"`);
187
+ }
184
188
  }
185
- function T(t) {
186
- if (typeof t != "string")
187
- throw new TypeError(`Expected a \`string\`, got \`${typeof t}\``);
188
- return t.replace(Q, "");
189
+ function sha256(content) {
190
+ return createHash("sha256").update(content, "utf-8").digest("hex");
189
191
  }
190
- function O(t) {
191
- return t && t.__esModule && Object.prototype.hasOwnProperty.call(t, "default") ? t.default : t;
192
+ function verifyChecksum(content, expectedHash, label) {
193
+ if (!expectedHash)
194
+ return;
195
+ const actual = sha256(content);
196
+ if (actual !== expectedHash) {
197
+ throw new Error(`Checksum inválido para "${label}"
198
+ esperado: ${expectedHash}
199
+ recibido: ${actual}`);
200
+ }
192
201
  }
193
- function A(t, u = {}) {
194
- if (typeof t != "string" || t.length === 0 || (u = { ambiguousIsNarrow: true, ...u }, t = T(t), t.length === 0))
195
- return 0;
196
- t = t.replace(FD(), " ");
197
- const F = u.ambiguousIsNarrow ? 1 : 2;
198
- let e = 0;
199
- for (const s of t) {
200
- const i = s.codePointAt(0);
201
- if (i <= 31 || i >= 127 && i <= 159 || i >= 768 && i <= 879)
202
- continue;
203
- switch (DD.eastAsianWidth(s)) {
204
- case "F":
205
- case "W":
206
- e += 2;
207
- break;
208
- case "A":
209
- e += F;
210
- break;
211
- default:
212
- e += 1;
202
+ var init_security = () => {};
203
+
204
+ // src/fs.ts
205
+ import {
206
+ existsSync,
207
+ mkdirSync,
208
+ unlinkSync,
209
+ readdirSync,
210
+ statSync,
211
+ copyFileSync,
212
+ readFileSync,
213
+ rmSync,
214
+ createWriteStream,
215
+ renameSync
216
+ } from "fs";
217
+ import { createHash as createHash2 } from "crypto";
218
+ import { join, resolve, dirname, relative, basename } from "path";
219
+ import { execFileSync } from "child_process";
220
+ function findOpenCodeDir(startDir = process.cwd()) {
221
+ let current = resolve(startDir);
222
+ while (true) {
223
+ const opencodeDir = join(current, ".opencode");
224
+ if (existsSync(opencodeDir))
225
+ return opencodeDir;
226
+ if (existsSync(join(current, ".git")))
227
+ return null;
228
+ const parent = dirname(current);
229
+ if (parent === current)
230
+ return null;
231
+ current = parent;
232
+ }
233
+ }
234
+ function findProjectRoot(startDir = process.cwd()) {
235
+ let current = resolve(startDir);
236
+ while (true) {
237
+ if (existsSync(join(current, ".opencode")) || existsSync(join(current, ".git"))) {
238
+ return current;
213
239
  }
240
+ const parent = dirname(current);
241
+ if (parent === current)
242
+ return resolve(startDir);
243
+ current = parent;
214
244
  }
215
- return e;
216
245
  }
217
- function sD() {
218
- const t = new Map;
219
- for (const [u, F] of Object.entries(r)) {
220
- for (const [e, s] of Object.entries(F))
221
- r[e] = { open: `\x1B[${s[0]}m`, close: `\x1B[${s[1]}m` }, F[e] = r[e], t.set(s[0], s[1]);
222
- Object.defineProperty(r, u, { value: F, enumerable: false });
246
+ function ensureOpenCodePaths(opencodeDir) {
247
+ const paths = {
248
+ root: opencodeDir,
249
+ agents: join(opencodeDir, "agents"),
250
+ commands: join(opencodeDir, "commands"),
251
+ plugins: join(opencodeDir, "plugins"),
252
+ skills: join(opencodeDir, "skills"),
253
+ mcp: join(opencodeDir, "mcp"),
254
+ tools: join(opencodeDir, "tools")
255
+ };
256
+ for (const dir of [paths.root, paths.agents, paths.commands, paths.plugins, paths.skills, paths.mcp, paths.tools]) {
257
+ if (!existsSync(dir))
258
+ mkdirSync(dir, { recursive: true });
223
259
  }
224
- return Object.defineProperty(r, "codes", { value: t, enumerable: false }), r.color.close = "\x1B[39m", r.bgColor.close = "\x1B[49m", r.color.ansi = L(), r.color.ansi256 = N(), r.color.ansi16m = I(), r.bgColor.ansi = L(m), r.bgColor.ansi256 = N(m), r.bgColor.ansi16m = I(m), Object.defineProperties(r, { rgbToAnsi256: { value: (u, F, e) => u === F && F === e ? u < 8 ? 16 : u > 248 ? 231 : Math.round((u - 8) / 247 * 24) + 232 : 16 + 36 * Math.round(u / 255 * 5) + 6 * Math.round(F / 255 * 5) + Math.round(e / 255 * 5), enumerable: false }, hexToRgb: { value: (u) => {
225
- const F = /[a-f\d]{6}|[a-f\d]{3}/i.exec(u.toString(16));
226
- if (!F)
227
- return [0, 0, 0];
228
- let [e] = F;
229
- e.length === 3 && (e = [...e].map((i) => i + i).join(""));
230
- const s = Number.parseInt(e, 16);
231
- return [s >> 16 & 255, s >> 8 & 255, s & 255];
232
- }, enumerable: false }, hexToAnsi256: { value: (u) => r.rgbToAnsi256(...r.hexToRgb(u)), enumerable: false }, ansi256ToAnsi: { value: (u) => {
233
- if (u < 8)
234
- return 30 + u;
235
- if (u < 16)
236
- return 90 + (u - 8);
237
- let F, e, s;
238
- if (u >= 232)
239
- F = ((u - 232) * 10 + 8) / 255, e = F, s = F;
240
- else {
241
- u -= 16;
242
- const C = u % 36;
243
- F = Math.floor(u / 36) / 5, e = Math.floor(C / 6) / 5, s = C % 6 / 5;
260
+ return paths;
261
+ }
262
+ function ensureToolDirs(toolsDir, toolNames) {
263
+ for (const name of toolNames) {
264
+ const dir = join(toolsDir, name);
265
+ if (!existsSync(dir))
266
+ mkdirSync(dir, { recursive: true });
267
+ }
268
+ }
269
+ function createOpenCodeDir(baseDir) {
270
+ return ensureOpenCodePaths(join(baseDir, ".opencode"));
271
+ }
272
+ function copyDirRecursive(src, dest, skipGenerated = false) {
273
+ if (!existsSync(dest))
274
+ mkdirSync(dest, { recursive: true });
275
+ for (const entry of readdirSync(src)) {
276
+ if (skipGenerated && (entry === "node_modules" || entry === "package-lock.json"))
277
+ continue;
278
+ const srcPath = join(src, entry);
279
+ const destPath = join(dest, entry);
280
+ const stat = statSync(srcPath);
281
+ if (stat.isDirectory()) {
282
+ copyDirRecursive(srcPath, destPath, skipGenerated);
283
+ } else {
284
+ copyFileSync(srcPath, destPath);
244
285
  }
245
- const i = Math.max(F, e, s) * 2;
246
- if (i === 0)
247
- return 30;
248
- let D = 30 + (Math.round(s) << 2 | Math.round(e) << 1 | Math.round(F));
249
- return i === 2 && (D += 60), D;
250
- }, enumerable: false }, rgbToAnsi: { value: (u, F, e) => r.ansi256ToAnsi(r.rgbToAnsi256(u, F, e)), enumerable: false }, hexToAnsi: { value: (u) => r.ansi256ToAnsi(r.hexToAnsi256(u)), enumerable: false } }), r;
286
+ }
251
287
  }
252
- function G(t, u, F) {
253
- return String(t).normalize().replace(/\r\n/g, `
254
- `).split(`
255
- `).map((e) => oD(e, u, F)).join(`
288
+ function computeTreeHash(dir) {
289
+ const lines = [];
290
+ walkForHash(dir, dir, lines);
291
+ const combined = lines.sort().join(`
256
292
  `);
293
+ return createHash2("sha256").update(combined, "utf-8").digest("hex");
257
294
  }
258
- function hD(t) {
259
- for (const u in t) {
260
- const F = u;
261
- if (!Object.hasOwn(t, F))
295
+ function walkForHash(root, current, lines) {
296
+ for (const entry of readdirSync(current)) {
297
+ if (entry === "node_modules" || entry === "package-lock.json")
262
298
  continue;
263
- const e = t[F];
264
- switch (F) {
265
- case "aliases": {
266
- for (const s in e)
267
- Object.hasOwn(e, s) && (c.aliases.has(s) || c.aliases.set(s, e[s]));
268
- break;
269
- }
299
+ const full = join(current, entry);
300
+ const stat = statSync(full);
301
+ if (stat.isDirectory()) {
302
+ walkForHash(root, full, lines);
303
+ } else {
304
+ const rel = relative(root, full);
305
+ const content = readFileSync(full, "utf-8");
306
+ lines.push(`${rel}:${sha256(content)}`);
270
307
  }
271
308
  }
272
309
  }
273
- function k(t, u) {
274
- if (typeof t == "string")
275
- return c.aliases.get(t) === u;
276
- for (const F of t)
277
- if (F !== undefined && k(F, u))
278
- return true;
279
- return false;
310
+ function isCommandAvailable(cmd) {
311
+ try {
312
+ execFileSync(process.platform === "win32" ? "where" : "which", [cmd], {
313
+ stdio: "ignore"
314
+ });
315
+ return true;
316
+ } catch {
317
+ return false;
318
+ }
280
319
  }
281
- function lD(t, u) {
282
- if (t === u)
283
- return;
284
- const F = t.split(`
285
- `), e = u.split(`
286
- `), s = [];
287
- for (let i = 0;i < Math.max(F.length, e.length); i++)
288
- F[i] !== e[i] && s.push(i);
289
- return s;
320
+ function findExecutablePath(cmd) {
321
+ try {
322
+ const command = process.platform === "win32" ? "where" : "which";
323
+ const result = execFileSync(command, [cmd], {
324
+ encoding: "utf-8",
325
+ stdio: ["pipe", "pipe", "pipe"]
326
+ });
327
+ return result.split(/\r?\n/).map((entry) => entry.trim()).find(Boolean) ?? null;
328
+ } catch {
329
+ return null;
330
+ }
290
331
  }
291
- function BD(t) {
292
- return t === S;
332
+ function detectPlatformTarget(platform = process.platform, arch = process.arch) {
333
+ let os;
334
+ let cpu;
335
+ if (platform === "darwin")
336
+ os = "darwin";
337
+ else if (platform === "linux")
338
+ os = "linux";
339
+ else if (platform === "win32")
340
+ os = "win32";
341
+ else
342
+ return null;
343
+ if (arch === "arm64")
344
+ cpu = "arm64";
345
+ else if (arch === "x64")
346
+ cpu = "x64";
347
+ else
348
+ return null;
349
+ return `${os}-${cpu}`;
293
350
  }
294
- function d(t, u) {
295
- const F = t;
296
- F.isTTY && F.setRawMode(u);
351
+ function getExecutableName(name, platform = process.platform) {
352
+ return platform === "win32" ? `${name}.exe` : name;
297
353
  }
298
- function cD({ input: t = $, output: u = j, overwrite: F = true, hideCursor: e = true } = {}) {
299
- const s = f.createInterface({ input: t, output: u, prompt: "", tabSize: 1 });
300
- f.emitKeypressEvents(t, s), t.isTTY && t.setRawMode(true);
301
- const i = (D, { name: C, sequence: o }) => {
302
- const E = String(D);
303
- if (k([E, C, o], "cancel")) {
304
- e && u.write(import_sisteransi.cursor.show), process.exit(0);
305
- return;
306
- }
307
- if (!F)
308
- return;
309
- const a = C === "return" ? 0 : -1, n = C === "return" ? -1 : 0;
310
- f.moveCursor(u, a, n, () => {
311
- f.clearLine(u, 1, () => {
312
- t.once("keypress", i);
313
- });
314
- });
354
+ function getExecutableNames(name, platform = process.platform) {
355
+ if (platform !== "win32")
356
+ return [name];
357
+ return name === "codegraph" ? [`${name}.exe`, `${name}.cmd`] : [`${name}.exe`];
358
+ }
359
+ function getCommandInvocation(command, args, platform = process.platform) {
360
+ const requiresCmd = platform === "win32" && (command.toLowerCase().endsWith(".cmd") || command === "npm" || command === "npx");
361
+ if (!requiresCmd)
362
+ return { command, args };
363
+ return {
364
+ command: "cmd.exe",
365
+ args: ["/d", "/c", "call", command, ...args]
315
366
  };
316
- return e && u.write(import_sisteransi.cursor.hide), t.once("keypress", i), () => {
317
- t.off("keypress", i), e && u.write(import_sisteransi.cursor.show), t.isTTY && !xD && t.setRawMode(false), s.terminal = false, s.close();
367
+ }
368
+ function getEngramReleaseTarget(platform = process.platform, arch = process.arch) {
369
+ const os = platform === "win32" ? "windows" : platform === "darwin" || platform === "linux" ? platform : null;
370
+ const cpu = arch === "x64" ? "amd64" : arch === "arm64" ? "arm64" : null;
371
+ return os && cpu ? `${os}-${cpu}` : null;
372
+ }
373
+ function shouldRetryDownload(error) {
374
+ const message = error instanceof Error ? error.message : String(error);
375
+ const status = message.match(/\bHTTP\s+(\d{3})\b/i)?.[1];
376
+ if (status) {
377
+ const code = Number(status);
378
+ return code === 408 || code === 425 || code === 429 || code >= 500;
379
+ }
380
+ return /abort|timeout|timed out|econnreset|econnrefused|eai_again|enotfound|fetch failed|network/i.test(message);
381
+ }
382
+ function promoteStagedDirectory(stagedDir, destinationDir) {
383
+ const backupDir = `${destinationDir}.backup-${process.pid}-${Date.now()}`;
384
+ const hadDestination = existsSync(destinationDir);
385
+ if (hadDestination)
386
+ renameSync(destinationDir, backupDir);
387
+ try {
388
+ mkdirSync(dirname(destinationDir), { recursive: true });
389
+ renameSync(stagedDir, destinationDir);
390
+ } catch (error) {
391
+ if (hadDestination && existsSync(backupDir))
392
+ renameSync(backupDir, destinationDir);
393
+ throw error;
394
+ }
395
+ let settled = false;
396
+ return {
397
+ commit() {
398
+ if (settled)
399
+ return;
400
+ if (hadDestination && existsSync(backupDir))
401
+ rmSync(backupDir, { recursive: true, force: true });
402
+ settled = true;
403
+ },
404
+ rollback() {
405
+ if (settled)
406
+ return;
407
+ if (existsSync(destinationDir))
408
+ rmSync(destinationDir, { recursive: true, force: true });
409
+ if (hadDestination && existsSync(backupDir))
410
+ renameSync(backupDir, destinationDir);
411
+ settled = true;
412
+ }
318
413
  };
319
414
  }
320
-
321
- class x {
322
- constructor(u, F = true) {
323
- h(this, "input"), h(this, "output"), h(this, "_abortSignal"), h(this, "rl"), h(this, "opts"), h(this, "_render"), h(this, "_track", false), h(this, "_prevFrame", ""), h(this, "_subscribers", new Map), h(this, "_cursor", 0), h(this, "state", "initial"), h(this, "error", ""), h(this, "value");
324
- const { input: e = $, output: s = j, render: i, signal: D, ...C } = u;
325
- this.opts = C, this.onKeypress = this.onKeypress.bind(this), this.close = this.close.bind(this), this.render = this.render.bind(this), this._render = i.bind(this), this._track = F, this._abortSignal = D, this.input = e, this.output = s;
326
- }
327
- unsubscribe() {
328
- this._subscribers.clear();
329
- }
330
- setSubscriber(u, F) {
331
- const e = this._subscribers.get(u) ?? [];
332
- e.push(F), this._subscribers.set(u, e);
333
- }
334
- on(u, F) {
335
- this.setSubscriber(u, { cb: F });
336
- }
337
- once(u, F) {
338
- this.setSubscriber(u, { cb: F, once: true });
339
- }
340
- emit(u, ...F) {
341
- const e = this._subscribers.get(u) ?? [], s = [];
342
- for (const i of e)
343
- i.cb(...F), i.once && s.push(() => e.splice(e.indexOf(i), 1));
344
- for (const i of s)
345
- i();
346
- }
347
- prompt() {
348
- return new Promise((u, F) => {
349
- if (this._abortSignal) {
350
- if (this._abortSignal.aborted)
351
- return this.state = "cancel", this.close(), u(S);
352
- this._abortSignal.addEventListener("abort", () => {
353
- this.state = "cancel", this.close();
354
- }, { once: true });
415
+ function downloadToFile(url, dest, timeoutMs = 180000) {
416
+ return new Promise((resolve2, reject) => {
417
+ const controller = new AbortController;
418
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
419
+ fetch(url, { signal: controller.signal, headers: { "User-Agent": USER_AGENT } }).then((res) => {
420
+ if (!res.ok || !res.body) {
421
+ throw new Error(`HTTP ${res.status} ${res.statusText} descargando ${url}`);
355
422
  }
356
- const e = new U(0);
357
- e._write = (s, i, D) => {
358
- this._track && (this.value = this.rl?.line.replace(/\t/g, ""), this._cursor = this.rl?.cursor ?? 0, this.emit("value", this.value)), D();
359
- }, this.input.pipe(e), this.rl = M.createInterface({ input: this.input, output: e, tabSize: 2, prompt: "", escapeCodeTimeout: 50 }), M.emitKeypressEvents(this.input, this.rl), this.rl.prompt(), this.opts.initialValue !== undefined && this._track && this.rl.write(this.opts.initialValue), this.input.on("keypress", this.onKeypress), d(this.input, true), this.output.on("resize", this.render), this.render(), this.once("submit", () => {
360
- this.output.write(import_sisteransi.cursor.show), this.output.off("resize", this.render), d(this.input, false), u(this.value);
361
- }), this.once("cancel", () => {
362
- this.output.write(import_sisteransi.cursor.show), this.output.off("resize", this.render), d(this.input, false), u(S);
423
+ const file = createWriteStream(dest);
424
+ const fail = (error) => {
425
+ file.destroy();
426
+ try {
427
+ unlinkSync(dest);
428
+ } catch {}
429
+ reject(error);
430
+ };
431
+ file.once("error", fail);
432
+ file.once("finish", resolve2);
433
+ const writable = new WritableStream({
434
+ write(chunk) {
435
+ return new Promise((ok, failWrite) => file.write(Buffer.from(chunk), (err) => err ? failWrite(err) : ok()));
436
+ },
437
+ close() {
438
+ file.end();
439
+ }
363
440
  });
441
+ return res.body.pipeTo(writable).catch(fail);
442
+ }).then(() => {
443
+ clearTimeout(timer);
444
+ }).catch((err) => {
445
+ clearTimeout(timer);
446
+ try {
447
+ unlinkSync(dest);
448
+ } catch {}
449
+ reject(err);
364
450
  });
365
- }
366
- onKeypress(u, F) {
367
- if (this.state === "error" && (this.state = "active"), F?.name && (!this._track && c.aliases.has(F.name) && this.emit("cursor", c.aliases.get(F.name)), c.actions.has(F.name) && this.emit("cursor", F.name)), u && (u.toLowerCase() === "y" || u.toLowerCase() === "n") && this.emit("confirm", u.toLowerCase() === "y"), u === "\t" && this.opts.placeholder && (this.value || (this.rl?.write(this.opts.placeholder), this.emit("value", this.opts.placeholder))), u && this.emit("key", u.toLowerCase()), F?.name === "return") {
368
- if (this.opts.validate) {
369
- const e = this.opts.validate(this.value);
370
- e && (this.error = e instanceof Error ? e.message : e, this.state = "error", this.rl?.write(this.value));
451
+ });
452
+ }
453
+ async function downloadAndExtract(url, destDir, stripComponents = 1, timeoutMs = 180000) {
454
+ const tmp = join(dirname(destDir), `.${basename(destDir)}.download-${Date.now()}`);
455
+ if (!existsSync(tmp))
456
+ mkdirSync(tmp, { recursive: true });
457
+ const archivePath = join(tmp, url.endsWith(".zip") ? "archive.zip" : "archive.tar.gz");
458
+ const extractedDir = join(tmp, "extracted");
459
+ try {
460
+ await downloadToFile(url, archivePath, timeoutMs);
461
+ mkdirSync(extractedDir, { recursive: true });
462
+ const args = url.endsWith(".zip") ? ["-xf", archivePath, "-C", extractedDir] : ["-xzf", archivePath, "-C", extractedDir];
463
+ execFileSync("tar", args, { stdio: "pipe", timeout: 60000 });
464
+ let stagedDir = extractedDir;
465
+ for (let component = 0;component < stripComponents; component++) {
466
+ const entries = readdirSync(stagedDir);
467
+ if (entries.length !== 1) {
468
+ throw new Error(`No se puede remover ${stripComponents} componente(s) del archive: estructura inesperada.`);
371
469
  }
372
- this.state !== "error" && (this.state = "submit");
373
- }
374
- k([u, F?.name, F?.sequence], "cancel") && (this.state = "cancel"), (this.state === "submit" || this.state === "cancel") && this.emit("finalize"), this.render(), (this.state === "submit" || this.state === "cancel") && this.close();
375
- }
376
- close() {
377
- this.input.unpipe(), this.input.removeListener("keypress", this.onKeypress), this.output.write(`
378
- `), d(this.input, false), this.rl?.close(), this.rl = undefined, this.emit(`${this.state}`, this.value), this.unsubscribe();
379
- }
380
- restoreCursor() {
381
- const u = G(this._prevFrame, process.stdout.columns, { hard: true }).split(`
382
- `).length - 1;
383
- this.output.write(import_sisteransi.cursor.move(-999, u * -1));
384
- }
385
- render() {
386
- const u = G(this._render(this) ?? "", process.stdout.columns, { hard: true });
387
- if (u !== this._prevFrame) {
388
- if (this.state === "initial")
389
- this.output.write(import_sisteransi.cursor.hide);
390
- else {
391
- const F = lD(this._prevFrame, u);
392
- if (this.restoreCursor(), F && F?.length === 1) {
393
- const e = F[0];
394
- this.output.write(import_sisteransi.cursor.move(0, e)), this.output.write(import_sisteransi.erase.lines(1));
395
- const s = u.split(`
396
- `);
397
- this.output.write(s[e]), this._prevFrame = u, this.output.write(import_sisteransi.cursor.move(0, s.length - e - 1));
398
- return;
399
- }
400
- if (F && F?.length > 1) {
401
- const e = F[0];
402
- this.output.write(import_sisteransi.cursor.move(0, e)), this.output.write(import_sisteransi.erase.down());
403
- const s = u.split(`
404
- `).slice(e);
405
- this.output.write(s.join(`
406
- `)), this._prevFrame = u;
407
- return;
408
- }
409
- this.output.write(import_sisteransi.erase.down());
470
+ const next = join(stagedDir, entries[0]);
471
+ if (!statSync(next).isDirectory()) {
472
+ throw new Error(`No se puede remover ${stripComponents} componente(s) del archive: falta directorio raíz.`);
410
473
  }
411
- this.output.write(u), this.state === "initial" && (this.state = "active"), this._prevFrame = u;
474
+ stagedDir = next;
412
475
  }
476
+ return promoteStagedDirectory(stagedDir, destDir);
477
+ } finally {
478
+ try {
479
+ rmSync(tmp, { recursive: true, force: true });
480
+ } catch {}
413
481
  }
414
482
  }
415
- var import_sisteransi, import_picocolors, Q, P, X, DD, uD = function() {
416
- return /\uD83C\uDFF4\uDB40\uDC67\uDB40\uDC62(?:\uDB40\uDC77\uDB40\uDC6C\uDB40\uDC73|\uDB40\uDC73\uDB40\uDC63\uDB40\uDC74|\uDB40\uDC65\uDB40\uDC6E\uDB40\uDC67)\uDB40\uDC7F|(?:\uD83E\uDDD1\uD83C\uDFFF\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFF\u200D\uD83E\uDD1D\u200D(?:\uD83D[\uDC68\uDC69]))(?:\uD83C[\uDFFB-\uDFFE])|(?:\uD83E\uDDD1\uD83C\uDFFE\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFE\u200D\uD83E\uDD1D\u200D(?:\uD83D[\uDC68\uDC69]))(?:\uD83C[\uDFFB-\uDFFD\uDFFF])|(?:\uD83E\uDDD1\uD83C\uDFFD\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFD\u200D\uD83E\uDD1D\u200D(?:\uD83D[\uDC68\uDC69]))(?:\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF])|(?:\uD83E\uDDD1\uD83C\uDFFC\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFC\u200D\uD83E\uDD1D\u200D(?:\uD83D[\uDC68\uDC69]))(?:\uD83C[\uDFFB\uDFFD-\uDFFF])|(?:\uD83E\uDDD1\uD83C\uDFFB\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFB\u200D\uD83E\uDD1D\u200D(?:\uD83D[\uDC68\uDC69]))(?:\uD83C[\uDFFC-\uDFFF])|\uD83D\uDC68(?:\uD83C\uDFFB(?:\u200D(?:\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFF])|\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFF]))|\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFC-\uDFFF])|[\u2695\u2696\u2708]\uFE0F|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD]))?|(?:\uD83C[\uDFFC-\uDFFF])\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFF])|\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFF]))|\u200D(?:\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83D\uDC68|(?:\uD83D[\uDC68\uDC69])\u200D(?:\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67]))|\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67])|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFF\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFE])|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFE\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFD\uDFFF])|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFD\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF])|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFC\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB\uDFFD-\uDFFF])|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|(?:\uD83C\uDFFF\u200D[\u2695\u2696\u2708]|\uD83C\uDFFE\u200D[\u2695\u2696\u2708]|\uD83C\uDFFD\u200D[\u2695\u2696\u2708]|\uD83C\uDFFC\u200D[\u2695\u2696\u2708]|\u200D[\u2695\u2696\u2708])\uFE0F|\u200D(?:(?:\uD83D[\uDC68\uDC69])\u200D(?:\uD83D[\uDC66\uDC67])|\uD83D[\uDC66\uDC67])|\uD83C\uDFFF|\uD83C\uDFFE|\uD83C\uDFFD|\uD83C\uDFFC)?|(?:\uD83D\uDC69(?:\uD83C\uDFFB\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D(?:\uD83D[\uDC68\uDC69])|\uD83D[\uDC68\uDC69])|(?:\uD83C[\uDFFC-\uDFFF])\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D(?:\uD83D[\uDC68\uDC69])|\uD83D[\uDC68\uDC69]))|\uD83E\uDDD1(?:\uD83C[\uDFFB-\uDFFF])\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1)(?:\uD83C[\uDFFB-\uDFFF])|\uD83D\uDC69\u200D\uD83D\uDC69\u200D(?:\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67]))|\uD83D\uDC69(?:\u200D(?:\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D(?:\uD83D[\uDC68\uDC69])|\uD83D[\uDC68\uDC69])|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFF\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFE\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFD\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFC\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFB\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD]))|\uD83E\uDDD1(?:\u200D(?:\uD83E\uDD1D\u200D\uD83E\uDDD1|\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFF\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFE\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFD\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFC\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFB\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD]))|\uD83D\uDC69\u200D\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC69\u200D\uD83D\uDC69\u200D(?:\uD83D[\uDC66\uDC67])|\uD83D\uDC69\u200D\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67])|(?:\uD83D\uDC41\uFE0F\u200D\uD83D\uDDE8|\uD83E\uDDD1(?:\uD83C\uDFFF\u200D[\u2695\u2696\u2708]|\uD83C\uDFFE\u200D[\u2695\u2696\u2708]|\uD83C\uDFFD\u200D[\u2695\u2696\u2708]|\uD83C\uDFFC\u200D[\u2695\u2696\u2708]|\uD83C\uDFFB\u200D[\u2695\u2696\u2708]|\u200D[\u2695\u2696\u2708])|\uD83D\uDC69(?:\uD83C\uDFFF\u200D[\u2695\u2696\u2708]|\uD83C\uDFFE\u200D[\u2695\u2696\u2708]|\uD83C\uDFFD\u200D[\u2695\u2696\u2708]|\uD83C\uDFFC\u200D[\u2695\u2696\u2708]|\uD83C\uDFFB\u200D[\u2695\u2696\u2708]|\u200D[\u2695\u2696\u2708])|\uD83D\uDE36\u200D\uD83C\uDF2B|\uD83C\uDFF3\uFE0F\u200D\u26A7|\uD83D\uDC3B\u200D\u2744|(?:(?:\uD83C[\uDFC3\uDFC4\uDFCA]|\uD83D[\uDC6E\uDC70\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6]|\uD83E[\uDD26\uDD35\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD-\uDDCF\uDDD4\uDDD6-\uDDDD])(?:\uD83C[\uDFFB-\uDFFF])|\uD83D\uDC6F|\uD83E[\uDD3C\uDDDE\uDDDF])\u200D[\u2640\u2642]|(?:\u26F9|\uD83C[\uDFCB\uDFCC]|\uD83D\uDD75)(?:\uFE0F|\uD83C[\uDFFB-\uDFFF])\u200D[\u2640\u2642]|\uD83C\uDFF4\u200D\u2620|(?:\uD83C[\uDFC3\uDFC4\uDFCA]|\uD83D[\uDC6E\uDC70\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6]|\uD83E[\uDD26\uDD35\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD-\uDDCF\uDDD4\uDDD6-\uDDDD])\u200D[\u2640\u2642]|[\xA9\xAE\u203C\u2049\u2122\u2139\u2194-\u2199\u21A9\u21AA\u2328\u23CF\u23ED-\u23EF\u23F1\u23F2\u23F8-\u23FA\u24C2\u25AA\u25AB\u25B6\u25C0\u25FB\u25FC\u2600-\u2604\u260E\u2611\u2618\u2620\u2622\u2623\u2626\u262A\u262E\u262F\u2638-\u263A\u2640\u2642\u265F\u2660\u2663\u2665\u2666\u2668\u267B\u267E\u2692\u2694-\u2697\u2699\u269B\u269C\u26A0\u26A7\u26B0\u26B1\u26C8\u26CF\u26D1\u26D3\u26E9\u26F0\u26F1\u26F4\u26F7\u26F8\u2702\u2708\u2709\u270F\u2712\u2714\u2716\u271D\u2721\u2733\u2734\u2744\u2747\u2763\u27A1\u2934\u2935\u2B05-\u2B07\u3030\u303D\u3297\u3299]|\uD83C[\uDD70\uDD71\uDD7E\uDD7F\uDE02\uDE37\uDF21\uDF24-\uDF2C\uDF36\uDF7D\uDF96\uDF97\uDF99-\uDF9B\uDF9E\uDF9F\uDFCD\uDFCE\uDFD4-\uDFDF\uDFF5\uDFF7]|\uD83D[\uDC3F\uDCFD\uDD49\uDD4A\uDD6F\uDD70\uDD73\uDD76-\uDD79\uDD87\uDD8A-\uDD8D\uDDA5\uDDA8\uDDB1\uDDB2\uDDBC\uDDC2-\uDDC4\uDDD1-\uDDD3\uDDDC-\uDDDE\uDDE1\uDDE3\uDDE8\uDDEF\uDDF3\uDDFA\uDECB\uDECD-\uDECF\uDEE0-\uDEE5\uDEE9\uDEF0\uDEF3])\uFE0F|\uD83C\uDFF3\uFE0F\u200D\uD83C\uDF08|\uD83D\uDC69\u200D\uD83D\uDC67|\uD83D\uDC69\u200D\uD83D\uDC66|\uD83D\uDE35\u200D\uD83D\uDCAB|\uD83D\uDE2E\u200D\uD83D\uDCA8|\uD83D\uDC15\u200D\uD83E\uDDBA|\uD83E\uDDD1(?:\uD83C\uDFFF|\uD83C\uDFFE|\uD83C\uDFFD|\uD83C\uDFFC|\uD83C\uDFFB)?|\uD83D\uDC69(?:\uD83C\uDFFF|\uD83C\uDFFE|\uD83C\uDFFD|\uD83C\uDFFC|\uD83C\uDFFB)?|\uD83C\uDDFD\uD83C\uDDF0|\uD83C\uDDF6\uD83C\uDDE6|\uD83C\uDDF4\uD83C\uDDF2|\uD83D\uDC08\u200D\u2B1B|\u2764\uFE0F\u200D(?:\uD83D\uDD25|\uD83E\uDE79)|\uD83D\uDC41\uFE0F|\uD83C\uDFF3\uFE0F|\uD83C\uDDFF(?:\uD83C[\uDDE6\uDDF2\uDDFC])|\uD83C\uDDFE(?:\uD83C[\uDDEA\uDDF9])|\uD83C\uDDFC(?:\uD83C[\uDDEB\uDDF8])|\uD83C\uDDFB(?:\uD83C[\uDDE6\uDDE8\uDDEA\uDDEC\uDDEE\uDDF3\uDDFA])|\uD83C\uDDFA(?:\uD83C[\uDDE6\uDDEC\uDDF2\uDDF3\uDDF8\uDDFE\uDDFF])|\uD83C\uDDF9(?:\uD83C[\uDDE6\uDDE8\uDDE9\uDDEB-\uDDED\uDDEF-\uDDF4\uDDF7\uDDF9\uDDFB\uDDFC\uDDFF])|\uD83C\uDDF8(?:\uD83C[\uDDE6-\uDDEA\uDDEC-\uDDF4\uDDF7-\uDDF9\uDDFB\uDDFD-\uDDFF])|\uD83C\uDDF7(?:\uD83C[\uDDEA\uDDF4\uDDF8\uDDFA\uDDFC])|\uD83C\uDDF5(?:\uD83C[\uDDE6\uDDEA-\uDDED\uDDF0-\uDDF3\uDDF7-\uDDF9\uDDFC\uDDFE])|\uD83C\uDDF3(?:\uD83C[\uDDE6\uDDE8\uDDEA-\uDDEC\uDDEE\uDDF1\uDDF4\uDDF5\uDDF7\uDDFA\uDDFF])|\uD83C\uDDF2(?:\uD83C[\uDDE6\uDDE8-\uDDED\uDDF0-\uDDFF])|\uD83C\uDDF1(?:\uD83C[\uDDE6-\uDDE8\uDDEE\uDDF0\uDDF7-\uDDFB\uDDFE])|\uD83C\uDDF0(?:\uD83C[\uDDEA\uDDEC-\uDDEE\uDDF2\uDDF3\uDDF5\uDDF7\uDDFC\uDDFE\uDDFF])|\uD83C\uDDEF(?:\uD83C[\uDDEA\uDDF2\uDDF4\uDDF5])|\uD83C\uDDEE(?:\uD83C[\uDDE8-\uDDEA\uDDF1-\uDDF4\uDDF6-\uDDF9])|\uD83C\uDDED(?:\uD83C[\uDDF0\uDDF2\uDDF3\uDDF7\uDDF9\uDDFA])|\uD83C\uDDEC(?:\uD83C[\uDDE6\uDDE7\uDDE9-\uDDEE\uDDF1-\uDDF3\uDDF5-\uDDFA\uDDFC\uDDFE])|\uD83C\uDDEB(?:\uD83C[\uDDEE-\uDDF0\uDDF2\uDDF4\uDDF7])|\uD83C\uDDEA(?:\uD83C[\uDDE6\uDDE8\uDDEA\uDDEC\uDDED\uDDF7-\uDDFA])|\uD83C\uDDE9(?:\uD83C[\uDDEA\uDDEC\uDDEF\uDDF0\uDDF2\uDDF4\uDDFF])|\uD83C\uDDE8(?:\uD83C[\uDDE6\uDDE8\uDDE9\uDDEB-\uDDEE\uDDF0-\uDDF5\uDDF7\uDDFA-\uDDFF])|\uD83C\uDDE7(?:\uD83C[\uDDE6\uDDE7\uDDE9-\uDDEF\uDDF1-\uDDF4\uDDF6-\uDDF9\uDDFB\uDDFC\uDDFE\uDDFF])|\uD83C\uDDE6(?:\uD83C[\uDDE8-\uDDEC\uDDEE\uDDF1\uDDF2\uDDF4\uDDF6-\uDDFA\uDDFC\uDDFD\uDDFF])|[#\*0-9]\uFE0F\u20E3|\u2764\uFE0F|(?:\uD83C[\uDFC3\uDFC4\uDFCA]|\uD83D[\uDC6E\uDC70\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6]|\uD83E[\uDD26\uDD35\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD-\uDDCF\uDDD4\uDDD6-\uDDDD])(?:\uD83C[\uDFFB-\uDFFF])|(?:\u26F9|\uD83C[\uDFCB\uDFCC]|\uD83D\uDD75)(?:\uFE0F|\uD83C[\uDFFB-\uDFFF])|\uD83C\uDFF4|(?:[\u270A\u270B]|\uD83C[\uDF85\uDFC2\uDFC7]|\uD83D[\uDC42\uDC43\uDC46-\uDC50\uDC66\uDC67\uDC6B-\uDC6D\uDC72\uDC74-\uDC76\uDC78\uDC7C\uDC83\uDC85\uDC8F\uDC91\uDCAA\uDD7A\uDD95\uDD96\uDE4C\uDE4F\uDEC0\uDECC]|\uD83E[\uDD0C\uDD0F\uDD18-\uDD1C\uDD1E\uDD1F\uDD30-\uDD34\uDD36\uDD77\uDDB5\uDDB6\uDDBB\uDDD2\uDDD3\uDDD5])(?:\uD83C[\uDFFB-\uDFFF])|(?:[\u261D\u270C\u270D]|\uD83D[\uDD74\uDD90])(?:\uFE0F|\uD83C[\uDFFB-\uDFFF])|[\u270A\u270B]|\uD83C[\uDF85\uDFC2\uDFC7]|\uD83D[\uDC08\uDC15\uDC3B\uDC42\uDC43\uDC46-\uDC50\uDC66\uDC67\uDC6B-\uDC6D\uDC72\uDC74-\uDC76\uDC78\uDC7C\uDC83\uDC85\uDC8F\uDC91\uDCAA\uDD7A\uDD95\uDD96\uDE2E\uDE35\uDE36\uDE4C\uDE4F\uDEC0\uDECC]|\uD83E[\uDD0C\uDD0F\uDD18-\uDD1C\uDD1E\uDD1F\uDD30-\uDD34\uDD36\uDD77\uDDB5\uDDB6\uDDBB\uDDD2\uDDD3\uDDD5]|\uD83C[\uDFC3\uDFC4\uDFCA]|\uD83D[\uDC6E\uDC70\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6]|\uD83E[\uDD26\uDD35\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD-\uDDCF\uDDD4\uDDD6-\uDDDD]|\uD83D\uDC6F|\uD83E[\uDD3C\uDDDE\uDDDF]|[\u231A\u231B\u23E9-\u23EC\u23F0\u23F3\u25FD\u25FE\u2614\u2615\u2648-\u2653\u267F\u2693\u26A1\u26AA\u26AB\u26BD\u26BE\u26C4\u26C5\u26CE\u26D4\u26EA\u26F2\u26F3\u26F5\u26FA\u26FD\u2705\u2728\u274C\u274E\u2753-\u2755\u2757\u2795-\u2797\u27B0\u27BF\u2B1B\u2B1C\u2B50\u2B55]|\uD83C[\uDC04\uDCCF\uDD8E\uDD91-\uDD9A\uDE01\uDE1A\uDE2F\uDE32-\uDE36\uDE38-\uDE3A\uDE50\uDE51\uDF00-\uDF20\uDF2D-\uDF35\uDF37-\uDF7C\uDF7E-\uDF84\uDF86-\uDF93\uDFA0-\uDFC1\uDFC5\uDFC6\uDFC8\uDFC9\uDFCF-\uDFD3\uDFE0-\uDFF0\uDFF8-\uDFFF]|\uD83D[\uDC00-\uDC07\uDC09-\uDC14\uDC16-\uDC3A\uDC3C-\uDC3E\uDC40\uDC44\uDC45\uDC51-\uDC65\uDC6A\uDC79-\uDC7B\uDC7D-\uDC80\uDC84\uDC88-\uDC8E\uDC90\uDC92-\uDCA9\uDCAB-\uDCFC\uDCFF-\uDD3D\uDD4B-\uDD4E\uDD50-\uDD67\uDDA4\uDDFB-\uDE2D\uDE2F-\uDE34\uDE37-\uDE44\uDE48-\uDE4A\uDE80-\uDEA2\uDEA4-\uDEB3\uDEB7-\uDEBF\uDEC1-\uDEC5\uDED0-\uDED2\uDED5-\uDED7\uDEEB\uDEEC\uDEF4-\uDEFC\uDFE0-\uDFEB]|\uD83E[\uDD0D\uDD0E\uDD10-\uDD17\uDD1D\uDD20-\uDD25\uDD27-\uDD2F\uDD3A\uDD3F-\uDD45\uDD47-\uDD76\uDD78\uDD7A-\uDDB4\uDDB7\uDDBA\uDDBC-\uDDCB\uDDD0\uDDE0-\uDDFF\uDE70-\uDE74\uDE78-\uDE7A\uDE80-\uDE86\uDE90-\uDEA8\uDEB0-\uDEB6\uDEC0-\uDEC2\uDED0-\uDED6]|(?:[\u231A\u231B\u23E9-\u23EC\u23F0\u23F3\u25FD\u25FE\u2614\u2615\u2648-\u2653\u267F\u2693\u26A1\u26AA\u26AB\u26BD\u26BE\u26C4\u26C5\u26CE\u26D4\u26EA\u26F2\u26F3\u26F5\u26FA\u26FD\u2705\u270A\u270B\u2728\u274C\u274E\u2753-\u2755\u2757\u2795-\u2797\u27B0\u27BF\u2B1B\u2B1C\u2B50\u2B55]|\uD83C[\uDC04\uDCCF\uDD8E\uDD91-\uDD9A\uDDE6-\uDDFF\uDE01\uDE1A\uDE2F\uDE32-\uDE36\uDE38-\uDE3A\uDE50\uDE51\uDF00-\uDF20\uDF2D-\uDF35\uDF37-\uDF7C\uDF7E-\uDF93\uDFA0-\uDFCA\uDFCF-\uDFD3\uDFE0-\uDFF0\uDFF4\uDFF8-\uDFFF]|\uD83D[\uDC00-\uDC3E\uDC40\uDC42-\uDCFC\uDCFF-\uDD3D\uDD4B-\uDD4E\uDD50-\uDD67\uDD7A\uDD95\uDD96\uDDA4\uDDFB-\uDE4F\uDE80-\uDEC5\uDECC\uDED0-\uDED2\uDED5-\uDED7\uDEEB\uDEEC\uDEF4-\uDEFC\uDFE0-\uDFEB]|\uD83E[\uDD0C-\uDD3A\uDD3C-\uDD45\uDD47-\uDD78\uDD7A-\uDDCB\uDDCD-\uDDFF\uDE70-\uDE74\uDE78-\uDE7A\uDE80-\uDE86\uDE90-\uDEA8\uDEB0-\uDEB6\uDEC0-\uDEC2\uDED0-\uDED6])|(?:[#\*0-9\xA9\xAE\u203C\u2049\u2122\u2139\u2194-\u2199\u21A9\u21AA\u231A\u231B\u2328\u23CF\u23E9-\u23F3\u23F8-\u23FA\u24C2\u25AA\u25AB\u25B6\u25C0\u25FB-\u25FE\u2600-\u2604\u260E\u2611\u2614\u2615\u2618\u261D\u2620\u2622\u2623\u2626\u262A\u262E\u262F\u2638-\u263A\u2640\u2642\u2648-\u2653\u265F\u2660\u2663\u2665\u2666\u2668\u267B\u267E\u267F\u2692-\u2697\u2699\u269B\u269C\u26A0\u26A1\u26A7\u26AA\u26AB\u26B0\u26B1\u26BD\u26BE\u26C4\u26C5\u26C8\u26CE\u26CF\u26D1\u26D3\u26D4\u26E9\u26EA\u26F0-\u26F5\u26F7-\u26FA\u26FD\u2702\u2705\u2708-\u270D\u270F\u2712\u2714\u2716\u271D\u2721\u2728\u2733\u2734\u2744\u2747\u274C\u274E\u2753-\u2755\u2757\u2763\u2764\u2795-\u2797\u27A1\u27B0\u27BF\u2934\u2935\u2B05-\u2B07\u2B1B\u2B1C\u2B50\u2B55\u3030\u303D\u3297\u3299]|\uD83C[\uDC04\uDCCF\uDD70\uDD71\uDD7E\uDD7F\uDD8E\uDD91-\uDD9A\uDDE6-\uDDFF\uDE01\uDE02\uDE1A\uDE2F\uDE32-\uDE3A\uDE50\uDE51\uDF00-\uDF21\uDF24-\uDF93\uDF96\uDF97\uDF99-\uDF9B\uDF9E-\uDFF0\uDFF3-\uDFF5\uDFF7-\uDFFF]|\uD83D[\uDC00-\uDCFD\uDCFF-\uDD3D\uDD49-\uDD4E\uDD50-\uDD67\uDD6F\uDD70\uDD73-\uDD7A\uDD87\uDD8A-\uDD8D\uDD90\uDD95\uDD96\uDDA4\uDDA5\uDDA8\uDDB1\uDDB2\uDDBC\uDDC2-\uDDC4\uDDD1-\uDDD3\uDDDC-\uDDDE\uDDE1\uDDE3\uDDE8\uDDEF\uDDF3\uDDFA-\uDE4F\uDE80-\uDEC5\uDECB-\uDED2\uDED5-\uDED7\uDEE0-\uDEE5\uDEE9\uDEEB\uDEEC\uDEF0\uDEF3-\uDEFC\uDFE0-\uDFEB]|\uD83E[\uDD0C-\uDD3A\uDD3C-\uDD45\uDD47-\uDD78\uDD7A-\uDDCB\uDDCD-\uDDFF\uDE70-\uDE74\uDE78-\uDE7A\uDE80-\uDE86\uDE90-\uDEA8\uDEB0-\uDEB6\uDEC0-\uDEC2\uDED0-\uDED6])\uFE0F|(?:[\u261D\u26F9\u270A-\u270D]|\uD83C[\uDF85\uDFC2-\uDFC4\uDFC7\uDFCA-\uDFCC]|\uD83D[\uDC42\uDC43\uDC46-\uDC50\uDC66-\uDC78\uDC7C\uDC81-\uDC83\uDC85-\uDC87\uDC8F\uDC91\uDCAA\uDD74\uDD75\uDD7A\uDD90\uDD95\uDD96\uDE45-\uDE47\uDE4B-\uDE4F\uDEA3\uDEB4-\uDEB6\uDEC0\uDECC]|\uD83E[\uDD0C\uDD0F\uDD18-\uDD1F\uDD26\uDD30-\uDD39\uDD3C-\uDD3E\uDD77\uDDB5\uDDB6\uDDB8\uDDB9\uDDBB\uDDCD-\uDDCF\uDDD1-\uDDDD])/g;
417
- }, FD, m = 10, L = (t = 0) => (u) => `\x1B[${u + t}m`, N = (t = 0) => (u) => `\x1B[${38 + t};5;${u}m`, I = (t = 0) => (u, F, e) => `\x1B[${38 + t};2;${u};${F};${e}m`, r, tD, eD, iD, v, CD = 39, w = "\x07", W = "[", rD = "]", R = "m", y, V = (t) => `${v.values().next().value}${W}${t}${R}`, z = (t) => `${v.values().next().value}${y}${t}${w}`, ED = (t) => t.split(" ").map((u) => A(u)), _ = (t, u, F) => {
418
- const e = [...u];
419
- let s = false, i = false, D = A(T(t[t.length - 1]));
420
- for (const [C, o] of e.entries()) {
421
- const E = A(o);
422
- if (D + E <= F ? t[t.length - 1] += o : (t.push(o), D = 0), v.has(o) && (s = true, i = e.slice(C + 1).join("").startsWith(y)), s) {
423
- i ? o === w && (s = false, i = false) : o === R && (s = false);
424
- continue;
425
- }
426
- D += E, D === F && C < e.length - 1 && (t.push(""), D = 0);
427
- }
428
- !D && t[t.length - 1].length > 0 && t.length > 1 && (t[t.length - 2] += t.pop());
429
- }, nD = (t) => {
430
- const u = t.split(" ");
431
- let F = u.length;
432
- for (;F > 0 && !(A(u[F - 1]) > 0); )
433
- F--;
434
- return F === u.length ? t : u.slice(0, F).join(" ") + u.slice(F).join("");
435
- }, oD = (t, u, F = {}) => {
436
- if (F.trim !== false && t.trim() === "")
437
- return "";
438
- let e = "", s, i;
439
- const D = ED(t);
440
- let C = [""];
441
- for (const [E, a] of t.split(" ").entries()) {
442
- F.trim !== false && (C[C.length - 1] = C[C.length - 1].trimStart());
443
- let n = A(C[C.length - 1]);
444
- if (E !== 0 && (n >= u && (F.wordWrap === false || F.trim === false) && (C.push(""), n = 0), (n > 0 || F.trim === false) && (C[C.length - 1] += " ", n++)), F.hard && D[E] > u) {
445
- const B = u - n, p = 1 + Math.floor((D[E] - B - 1) / u);
446
- Math.floor((D[E] - 1) / u) < p && C.push(""), _(C, a, u);
447
- continue;
448
- }
449
- if (n + D[E] > u && n > 0 && D[E] > 0) {
450
- if (F.wordWrap === false && n < u) {
451
- _(C, a, u);
452
- continue;
483
+ async function downloadAndExtractWithRetry(url, destDir, stripComponents = 1, timeoutMs = 180000, maxRetries = 2) {
484
+ let lastError = null;
485
+ for (let attempt = 0;attempt <= maxRetries; attempt++) {
486
+ try {
487
+ return await downloadAndExtract(url, destDir, stripComponents, timeoutMs);
488
+ } catch (err) {
489
+ lastError = err;
490
+ if (attempt < maxRetries && shouldRetryDownload(lastError)) {
491
+ const delay = 1000 * Math.pow(2, attempt);
492
+ console.error(`[download] Intento ${attempt + 1} falló: ${lastError.message}. Reintentando en ${delay}ms...`);
493
+ await new Promise((r2) => setTimeout(r2, delay));
453
494
  }
454
- C.push("");
455
- }
456
- if (n + D[E] > u && F.wordWrap === false) {
457
- _(C, a, u);
458
- continue;
459
495
  }
460
- C[C.length - 1] += a;
461
496
  }
462
- F.trim !== false && (C = C.map((E) => nD(E)));
463
- const o = [...C.join(`
464
- `)];
465
- for (const [E, a] of o.entries()) {
466
- if (e += a, v.has(a)) {
467
- const { groups: B } = new RegExp(`(?:\\${W}(?<code>\\d+)m|\\${y}(?<uri>.*)${w})`).exec(o.slice(E).join("")) || { groups: {} };
468
- if (B.code !== undefined) {
469
- const p = Number.parseFloat(B.code);
470
- s = p === CD ? undefined : p;
471
- } else
472
- B.uri !== undefined && (i = B.uri.length === 0 ? undefined : B.uri);
497
+ throw lastError;
498
+ }
499
+ function findBinaryInDir(dir, name) {
500
+ const entries = readdirSync(dir);
501
+ for (const entry of entries) {
502
+ const full = join(dir, entry);
503
+ const stat = statSync(full);
504
+ if (stat.isDirectory()) {
505
+ const found = findBinaryInDir(full, name);
506
+ if (found)
507
+ return found;
508
+ } else if (getExecutableNames(name).includes(entry)) {
509
+ return full;
473
510
  }
474
- const n = iD.codes.get(Number(s));
475
- o[E + 1] === `
476
- ` ? (i && (e += z("")), s && n && (e += V(n))) : a === `
477
- ` && (s && n && (e += V(s)), i && (e += z(i)));
478
511
  }
479
- return e;
480
- }, aD, c, xD, S, AD, pD = (t, u, F) => (u in t) ? AD(t, u, { enumerable: true, configurable: true, writable: true, value: F }) : t[u] = F, h = (t, u, F) => (pD(t, typeof u != "symbol" ? u + "" : u, F), F), fD, gD, vD = (t, u, F) => (u in t) ? gD(t, u, { enumerable: true, configurable: true, writable: true, value: F }) : t[u] = F, K = (t, u, F) => (vD(t, typeof u != "symbol" ? u + "" : u, F), F), dD, bD, mD = (t, u, F) => (u in t) ? bD(t, u, { enumerable: true, configurable: true, writable: true, value: F }) : t[u] = F, Y = (t, u, F) => (mD(t, typeof u != "symbol" ? u + "" : u, F), F), wD, yD, _D = (t, u, F) => (u in t) ? yD(t, u, { enumerable: true, configurable: true, writable: true, value: F }) : t[u] = F, Z = (t, u, F) => (_D(t, typeof u != "symbol" ? u + "" : u, F), F), kD, SD, $D = (t, u, F) => (u in t) ? SD(t, u, { enumerable: true, configurable: true, writable: true, value: F }) : t[u] = F, q = (t, u, F) => ($D(t, typeof u != "symbol" ? u + "" : u, F), F), jD, MD, TD = (t, u, F) => (u in t) ? MD(t, u, { enumerable: true, configurable: true, writable: true, value: F }) : t[u] = F, H = (t, u, F) => (TD(t, typeof u != "symbol" ? u + "" : u, F), F), OD, PD;
481
- var init_dist = __esm(() => {
482
- import_sisteransi = __toESM(require_src(), 1);
483
- import_picocolors = __toESM(require_picocolors(), 1);
484
- Q = J();
485
- P = { exports: {} };
486
- (function(t) {
487
- var u = {};
488
- t.exports = u, u.eastAsianWidth = function(e) {
489
- var s = e.charCodeAt(0), i = e.length == 2 ? e.charCodeAt(1) : 0, D = s;
490
- return 55296 <= s && s <= 56319 && 56320 <= i && i <= 57343 && (s &= 1023, i &= 1023, D = s << 10 | i, D += 65536), D == 12288 || 65281 <= D && D <= 65376 || 65504 <= D && D <= 65510 ? "F" : D == 8361 || 65377 <= D && D <= 65470 || 65474 <= D && D <= 65479 || 65482 <= D && D <= 65487 || 65490 <= D && D <= 65495 || 65498 <= D && D <= 65500 || 65512 <= D && D <= 65518 ? "H" : 4352 <= D && D <= 4447 || 4515 <= D && D <= 4519 || 4602 <= D && D <= 4607 || 9001 <= D && D <= 9002 || 11904 <= D && D <= 11929 || 11931 <= D && D <= 12019 || 12032 <= D && D <= 12245 || 12272 <= D && D <= 12283 || 12289 <= D && D <= 12350 || 12353 <= D && D <= 12438 || 12441 <= D && D <= 12543 || 12549 <= D && D <= 12589 || 12593 <= D && D <= 12686 || 12688 <= D && D <= 12730 || 12736 <= D && D <= 12771 || 12784 <= D && D <= 12830 || 12832 <= D && D <= 12871 || 12880 <= D && D <= 13054 || 13056 <= D && D <= 19903 || 19968 <= D && D <= 42124 || 42128 <= D && D <= 42182 || 43360 <= D && D <= 43388 || 44032 <= D && D <= 55203 || 55216 <= D && D <= 55238 || 55243 <= D && D <= 55291 || 63744 <= D && D <= 64255 || 65040 <= D && D <= 65049 || 65072 <= D && D <= 65106 || 65108 <= D && D <= 65126 || 65128 <= D && D <= 65131 || 110592 <= D && D <= 110593 || 127488 <= D && D <= 127490 || 127504 <= D && D <= 127546 || 127552 <= D && D <= 127560 || 127568 <= D && D <= 127569 || 131072 <= D && D <= 194367 || 177984 <= D && D <= 196605 || 196608 <= D && D <= 262141 ? "W" : 32 <= D && D <= 126 || 162 <= D && D <= 163 || 165 <= D && D <= 166 || D == 172 || D == 175 || 10214 <= D && D <= 10221 || 10629 <= D && D <= 10630 ? "Na" : D == 161 || D == 164 || 167 <= D && D <= 168 || D == 170 || 173 <= D && D <= 174 || 176 <= D && D <= 180 || 182 <= D && D <= 186 || 188 <= D && D <= 191 || D == 198 || D == 208 || 215 <= D && D <= 216 || 222 <= D && D <= 225 || D == 230 || 232 <= D && D <= 234 || 236 <= D && D <= 237 || D == 240 || 242 <= D && D <= 243 || 247 <= D && D <= 250 || D == 252 || D == 254 || D == 257 || D == 273 || D == 275 || D == 283 || 294 <= D && D <= 295 || D == 299 || 305 <= D && D <= 307 || D == 312 || 319 <= D && D <= 322 || D == 324 || 328 <= D && D <= 331 || D == 333 || 338 <= D && D <= 339 || 358 <= D && D <= 359 || D == 363 || D == 462 || D == 464 || D == 466 || D == 468 || D == 470 || D == 472 || D == 474 || D == 476 || D == 593 || D == 609 || D == 708 || D == 711 || 713 <= D && D <= 715 || D == 717 || D == 720 || 728 <= D && D <= 731 || D == 733 || D == 735 || 768 <= D && D <= 879 || 913 <= D && D <= 929 || 931 <= D && D <= 937 || 945 <= D && D <= 961 || 963 <= D && D <= 969 || D == 1025 || 1040 <= D && D <= 1103 || D == 1105 || D == 8208 || 8211 <= D && D <= 8214 || 8216 <= D && D <= 8217 || 8220 <= D && D <= 8221 || 8224 <= D && D <= 8226 || 8228 <= D && D <= 8231 || D == 8240 || 8242 <= D && D <= 8243 || D == 8245 || D == 8251 || D == 8254 || D == 8308 || D == 8319 || 8321 <= D && D <= 8324 || D == 8364 || D == 8451 || D == 8453 || D == 8457 || D == 8467 || D == 8470 || 8481 <= D && D <= 8482 || D == 8486 || D == 8491 || 8531 <= D && D <= 8532 || 8539 <= D && D <= 8542 || 8544 <= D && D <= 8555 || 8560 <= D && D <= 8569 || D == 8585 || 8592 <= D && D <= 8601 || 8632 <= D && D <= 8633 || D == 8658 || D == 8660 || D == 8679 || D == 8704 || 8706 <= D && D <= 8707 || 8711 <= D && D <= 8712 || D == 8715 || D == 8719 || D == 8721 || D == 8725 || D == 8730 || 8733 <= D && D <= 8736 || D == 8739 || D == 8741 || 8743 <= D && D <= 8748 || D == 8750 || 8756 <= D && D <= 8759 || 8764 <= D && D <= 8765 || D == 8776 || D == 8780 || D == 8786 || 8800 <= D && D <= 8801 || 8804 <= D && D <= 8807 || 8810 <= D && D <= 8811 || 8814 <= D && D <= 8815 || 8834 <= D && D <= 8835 || 8838 <= D && D <= 8839 || D == 8853 || D == 8857 || D == 8869 || D == 8895 || D == 8978 || 9312 <= D && D <= 9449 || 9451 <= D && D <= 9547 || 9552 <= D && D <= 9587 || 9600 <= D && D <= 9615 || 9618 <= D && D <= 9621 || 9632 <= D && D <= 9633 || 9635 <= D && D <= 9641 || 9650 <= D && D <= 9651 || 9654 <= D && D <= 9655 || 9660 <= D && D <= 9661 || 9664 <= D && D <= 9665 || 9670 <= D && D <= 9672 || D == 9675 || 9678 <= D && D <= 9681 || 9698 <= D && D <= 9701 || D == 9711 || 9733 <= D && D <= 9734 || D == 9737 || 9742 <= D && D <= 9743 || 9748 <= D && D <= 9749 || D == 9756 || D == 9758 || D == 9792 || D == 9794 || 9824 <= D && D <= 9825 || 9827 <= D && D <= 9829 || 9831 <= D && D <= 9834 || 9836 <= D && D <= 9837 || D == 9839 || 9886 <= D && D <= 9887 || 9918 <= D && D <= 9919 || 9924 <= D && D <= 9933 || 9935 <= D && D <= 9953 || D == 9955 || 9960 <= D && D <= 9983 || D == 10045 || D == 10071 || 10102 <= D && D <= 10111 || 11093 <= D && D <= 11097 || 12872 <= D && D <= 12879 || 57344 <= D && D <= 63743 || 65024 <= D && D <= 65039 || D == 65533 || 127232 <= D && D <= 127242 || 127248 <= D && D <= 127277 || 127280 <= D && D <= 127337 || 127344 <= D && D <= 127386 || 917760 <= D && D <= 917999 || 983040 <= D && D <= 1048573 || 1048576 <= D && D <= 1114109 ? "A" : "N";
491
- }, u.characterLength = function(e) {
492
- var s = this.eastAsianWidth(e);
493
- return s == "F" || s == "W" || s == "A" ? 2 : 1;
494
- };
495
- function F(e) {
496
- return e.match(/[\uD800-\uDBFF][\uDC00-\uDFFF]|[^\uD800-\uDFFF]/g) || [];
497
- }
498
- u.length = function(e) {
499
- for (var s = F(e), i = 0, D = 0;D < s.length; D++)
500
- i = i + this.characterLength(s[D]);
501
- return i;
502
- }, u.slice = function(e, s, i) {
503
- textLen = u.length(e), s = s || 0, i = i || 1, s < 0 && (s = textLen + s), i < 0 && (i = textLen + i);
504
- for (var D = "", C = 0, o = F(e), E = 0;E < o.length; E++) {
505
- var a = o[E], n = u.length(a);
506
- if (C >= s - (n == 2 ? 1 : 0))
507
- if (C + n <= i)
508
- D += a;
509
- else
510
- break;
511
- C += n;
512
- }
513
- return D;
514
- };
515
- })(P);
516
- X = P.exports;
517
- DD = O(X);
518
- FD = O(uD);
519
- r = { modifier: { reset: [0, 0], bold: [1, 22], dim: [2, 22], italic: [3, 23], underline: [4, 24], overline: [53, 55], inverse: [7, 27], hidden: [8, 28], strikethrough: [9, 29] }, color: { black: [30, 39], red: [31, 39], green: [32, 39], yellow: [33, 39], blue: [34, 39], magenta: [35, 39], cyan: [36, 39], white: [37, 39], blackBright: [90, 39], gray: [90, 39], grey: [90, 39], redBright: [91, 39], greenBright: [92, 39], yellowBright: [93, 39], blueBright: [94, 39], magentaBright: [95, 39], cyanBright: [96, 39], whiteBright: [97, 39] }, bgColor: { bgBlack: [40, 49], bgRed: [41, 49], bgGreen: [42, 49], bgYellow: [43, 49], bgBlue: [44, 49], bgMagenta: [45, 49], bgCyan: [46, 49], bgWhite: [47, 49], bgBlackBright: [100, 49], bgGray: [100, 49], bgGrey: [100, 49], bgRedBright: [101, 49], bgGreenBright: [102, 49], bgYellowBright: [103, 49], bgBlueBright: [104, 49], bgMagentaBright: [105, 49], bgCyanBright: [106, 49], bgWhiteBright: [107, 49] } };
520
- Object.keys(r.modifier);
521
- tD = Object.keys(r.color);
522
- eD = Object.keys(r.bgColor);
523
- [...tD, ...eD];
524
- iD = sD();
525
- v = new Set(["\x1B", "›"]);
526
- y = `${rD}8;;`;
527
- aD = ["up", "down", "left", "right", "space", "enter", "cancel"];
528
- c = { actions: new Set(aD), aliases: new Map([["k", "up"], ["j", "down"], ["h", "left"], ["l", "right"], ["\x03", "cancel"], ["escape", "cancel"]]) };
529
- xD = globalThis.process.platform.startsWith("win");
530
- S = Symbol("clack:cancel");
531
- AD = Object.defineProperty;
532
- fD = class fD extends x {
533
- get cursor() {
534
- return this.value ? 0 : 1;
535
- }
536
- get _value() {
537
- return this.cursor === 0;
538
- }
539
- constructor(u) {
540
- super(u, false), this.value = !!u.initialValue, this.on("value", () => {
541
- this.value = this._value;
542
- }), this.on("confirm", (F) => {
543
- this.output.write(import_sisteransi.cursor.move(0, -1)), this.value = F, this.state = "submit", this.close();
544
- }), this.on("cursor", () => {
545
- this.value = !this.value;
546
- });
547
- }
548
- };
549
- gD = Object.defineProperty;
550
- dD = class extends x {
551
- constructor(u) {
552
- super(u, false), K(this, "options"), K(this, "cursor", 0);
553
- const { options: F } = u;
554
- this.options = Object.entries(F).flatMap(([e, s]) => [{ value: e, group: true, label: e }, ...s.map((i) => ({ ...i, group: e }))]), this.value = [...u.initialValues ?? []], this.cursor = Math.max(this.options.findIndex(({ value: e }) => e === u.cursorAt), 0), this.on("cursor", (e) => {
555
- switch (e) {
556
- case "left":
557
- case "up":
558
- this.cursor = this.cursor === 0 ? this.options.length - 1 : this.cursor - 1;
559
- break;
560
- case "down":
561
- case "right":
562
- this.cursor = this.cursor === this.options.length - 1 ? 0 : this.cursor + 1;
563
- break;
564
- case "space":
565
- this.toggleValue();
566
- break;
567
- }
568
- });
569
- }
570
- getGroupItems(u) {
571
- return this.options.filter((F) => F.group === u);
572
- }
573
- isGroupSelected(u) {
574
- return this.getGroupItems(u).every((F) => this.value.includes(F.value));
575
- }
576
- toggleValue() {
577
- const u = this.options[this.cursor];
578
- if (u.group === true) {
579
- const F = u.value, e = this.getGroupItems(F);
580
- this.isGroupSelected(F) ? this.value = this.value.filter((s) => e.findIndex((i) => i.value === s) === -1) : this.value = [...this.value, ...e.map((s) => s.value)], this.value = Array.from(new Set(this.value));
581
- } else {
582
- const F = this.value.includes(u.value);
583
- this.value = F ? this.value.filter((e) => e !== u.value) : [...this.value, u.value];
512
+ return null;
513
+ }
514
+ var USER_AGENT = "ostacky-installer";
515
+ var init_fs = __esm(() => {
516
+ init_security();
517
+ });
518
+
519
+ // manifest.json
520
+ var manifest_default;
521
+ var init_manifest = __esm(() => {
522
+ manifest_default = {
523
+ version: "0.6.2",
524
+ repo: "JaimeHoracio/Ostacky",
525
+ tag: "v0.6.2",
526
+ agents: [
527
+ {
528
+ name: "ostacky",
529
+ file: "assets/agents/ostacky.md",
530
+ description: "Orquestador con recuperación automática (nunca se congela), ruteo por nivel de impacto, controller MCP con SDK oficial, edición segura con fallback inline, y delegación en OpenSpec + Superpowers",
531
+ version: "0.6.2",
532
+ sha256: "9cd6f45339b897fe002775a3a54f570e47dedd1784fa474d6cd5113594d1bd85"
584
533
  }
585
- }
586
- };
587
- bD = Object.defineProperty;
588
- wD = class extends x {
589
- constructor(u) {
590
- super(u, false), Y(this, "options"), Y(this, "cursor", 0), this.options = u.options, this.value = [...u.initialValues ?? []], this.cursor = Math.max(this.options.findIndex(({ value: F }) => F === u.cursorAt), 0), this.on("key", (F) => {
591
- F === "a" && this.toggleAll();
592
- }), this.on("cursor", (F) => {
593
- switch (F) {
594
- case "left":
595
- case "up":
596
- this.cursor = this.cursor === 0 ? this.options.length - 1 : this.cursor - 1;
597
- break;
598
- case "down":
599
- case "right":
600
- this.cursor = this.cursor === this.options.length - 1 ? 0 : this.cursor + 1;
601
- break;
602
- case "space":
603
- this.toggleValue();
604
- break;
605
- }
606
- });
607
- }
608
- get _value() {
609
- return this.options[this.cursor].value;
610
- }
611
- toggleAll() {
612
- const u = this.value.length === this.options.length;
613
- this.value = u ? [] : this.options.map((F) => F.value);
614
- }
615
- toggleValue() {
616
- const u = this.value.includes(this._value);
617
- this.value = u ? this.value.filter((F) => F !== this._value) : [...this.value, this._value];
618
- }
619
- };
620
- yD = Object.defineProperty;
621
- kD = class kD extends x {
622
- constructor({ mask: u, ...F }) {
623
- super(F), Z(this, "valueWithCursor", ""), Z(this, "_mask", "•"), this._mask = u ?? "•", this.on("finalize", () => {
624
- this.valueWithCursor = this.masked;
625
- }), this.on("value", () => {
626
- if (this.cursor >= this.value.length)
627
- this.valueWithCursor = `${this.masked}${import_picocolors.default.inverse(import_picocolors.default.hidden("_"))}`;
628
- else {
629
- const e = this.masked.slice(0, this.cursor), s = this.masked.slice(this.cursor);
630
- this.valueWithCursor = `${e}${import_picocolors.default.inverse(s[0])}${s.slice(1)}`;
631
- }
632
- });
633
- }
634
- get cursor() {
635
- return this._cursor;
636
- }
637
- get masked() {
638
- return this.value.replaceAll(/./g, this._mask);
639
- }
640
- };
641
- SD = Object.defineProperty;
642
- jD = class jD extends x {
643
- constructor(u) {
644
- super(u, false), q(this, "options"), q(this, "cursor", 0), this.options = u.options, this.cursor = this.options.findIndex(({ value: F }) => F === u.initialValue), this.cursor === -1 && (this.cursor = 0), this.changeValue(), this.on("cursor", (F) => {
645
- switch (F) {
646
- case "left":
647
- case "up":
648
- this.cursor = this.cursor === 0 ? this.options.length - 1 : this.cursor - 1;
649
- break;
650
- case "down":
651
- case "right":
652
- this.cursor = this.cursor === this.options.length - 1 ? 0 : this.cursor + 1;
653
- break;
654
- }
655
- this.changeValue();
656
- });
657
- }
658
- get _value() {
659
- return this.options[this.cursor];
660
- }
661
- changeValue() {
662
- this.value = this._value.value;
663
- }
664
- };
665
- MD = Object.defineProperty;
666
- OD = class OD extends x {
667
- constructor(u) {
668
- super(u, false), H(this, "options"), H(this, "cursor", 0), this.options = u.options;
669
- const F = this.options.map(({ value: [e] }) => e?.toLowerCase());
670
- this.cursor = Math.max(F.indexOf(u.initialValue), 0), this.on("key", (e) => {
671
- if (!F.includes(e))
672
- return;
673
- const s = this.options.find(({ value: [i] }) => i?.toLowerCase() === e);
674
- s && (this.value = s.value, this.state = "submit", this.emit("submit"));
675
- });
676
- }
677
- };
678
- PD = class PD extends x {
679
- get valueWithCursor() {
680
- if (this.state === "submit")
681
- return this.value;
682
- if (this.cursor >= this.value.length)
683
- return `${this.value}█`;
684
- const u = this.value.slice(0, this.cursor), [F, ...e] = this.value.slice(this.cursor);
685
- return `${u}${import_picocolors.default.inverse(F)}${e.join("")}`;
686
- }
687
- get cursor() {
688
- return this._cursor;
689
- }
690
- constructor(u) {
691
- super(u), this.on("finalize", () => {
692
- this.value || (this.value = u.defaultValue);
693
- });
694
- }
534
+ ],
535
+ commands: [
536
+ {
537
+ name: "install-stack",
538
+ file: "assets/commands/install-stack.md",
539
+ description: "Instala el stack tecnológico del proyecto (CodeGraph, skills, OpenSpec, Engram, Context7, controller MCP con SDK oficial)",
540
+ version: "0.6.2",
541
+ sha256: "00dd0562f38aaa8d3d255332a21f190a516f82fb3ce00151fc33f2a7e5f8146b"
542
+ },
543
+ {
544
+ name: "opsx-sync",
545
+ file: "assets/commands/opsx-sync.md",
546
+ description: "Sincroniza delta specs del change activo sin inicializar CodeGraph si ya existe índice",
547
+ version: "0.6.2",
548
+ sha256: "fe0158478f2ca63b315037a85fc1632b77868532e319af6c7384285441767d64"
549
+ }
550
+ ],
551
+ mcpServers: [
552
+ {
553
+ name: "ostacky-controller",
554
+ file: "assets/mcp/ostacky-controller/",
555
+ description: "Máquina de estados persistida con @modelcontextprotocol/server SDK. 20 tools: start_request → discovery → route → execution → sync → done + validate_edit + complete_task + ping + proceed_to_route + abandon integrado",
556
+ version: "0.6.2",
557
+ sha256: "9ee05fa1dd80de42c1b210d9ba85ef4aa34e5b652e2ed5753519b66eca399776"
558
+ },
559
+ {
560
+ name: "openspec",
561
+ file: "assets/mcp/openspec/",
562
+ description: "MCP server local para OpenSpec - proposal, apply, archive, sync de cambios",
563
+ version: "0.6.2",
564
+ sha256: "fa4be28bfc1e75db8f1a037e2580f04a60066c80e8e5934e90e1041020d04609"
565
+ }
566
+ ],
567
+ skills: [
568
+ {
569
+ name: "brainstorming",
570
+ file: "assets/skills/brainstorming/SKILL.md",
571
+ description: "Skill unificado de pensamiento con dos modos: creative-design (producción de diseño → transición a writing-plans o openspec-propose) y open-exploration (exploración libre)",
572
+ version: "0.6.2",
573
+ sha256: "ad474c324aaf78c495dff508268b55274048f272f00501d66eaa3aa5e0483862"
574
+ },
575
+ {
576
+ name: "execution-mode-evaluation",
577
+ file: "assets/skills/execution-mode-evaluation/SKILL.md",
578
+ description: "Skill de análisis de modo de ejecución — output reconciliado con controller snapshot contract (recommendation field)",
579
+ version: "0.6.2",
580
+ sha256: "ae4064dedd3d40ffd3bc7d8d49dab970397555c6f7c1b2c8054e3bda9d4eb73b"
581
+ },
582
+ {
583
+ name: "writing-plans",
584
+ file: "assets/skills/writing-plans/SKILL.md",
585
+ description: "Skill de planificación de implementación (Superpowers) — execution handoff removido, Ostacky decide modo de ejecución",
586
+ version: "0.6.2",
587
+ sha256: "92a3f40dc215cee7b587c2df52ac3a88a129dec0c176059014a5e070ea344c23"
588
+ },
589
+ {
590
+ name: "tdd",
591
+ file: "assets/skills/tdd/SKILL.md",
592
+ description: "Skill de test-driven development (Superpowers)",
593
+ version: "0.6.2",
594
+ sha256: "2932bb3c38b2e41305ec8aa375a7800259eda1bba6bbecfa5b6c4de850b2be43"
595
+ },
596
+ {
597
+ name: "subagent-driven-development",
598
+ file: "assets/skills/subagent-driven-development/SKILL.md",
599
+ description: "Skill de ejecución con subagentes (Superpowers) — ejecuta solo después de confirmación del coordinador Ostacky",
600
+ version: "0.6.2",
601
+ sha256: "cf0f4cc6f5301bfd26784ab91f3b6bb30ed30527fb1658e6caab82ac7cee9ca1"
602
+ },
603
+ {
604
+ name: "dispatching-parallel-agents",
605
+ file: "assets/skills/dispatching-parallel-agents/SKILL.md",
606
+ description: "Skill de dispatch paralelo de agentes (Superpowers)",
607
+ version: "0.6.2",
608
+ sha256: "57e3829cc1217e46e693049eaf910f8fad58c27f6d1ec3e37ab7534993123ab6"
609
+ },
610
+ {
611
+ name: "review",
612
+ file: "assets/skills/review/SKILL.md",
613
+ description: "Skill de revisión de código (Superpowers)",
614
+ version: "0.6.2",
615
+ sha256: "c4a5ecbbaa834ade627a86cebb382c75a9ddab83efedf8f8a3ae1ba24bd7a216"
616
+ },
617
+ {
618
+ name: "receiving-code-review",
619
+ file: "assets/skills/receiving-code-review/SKILL.md",
620
+ description: "Skill de recibir y procesar feedback de code review",
621
+ version: "0.6.2",
622
+ sha256: "8cccf2b6234be4dfbfd426d0ba4b3e26d3ed8f416adaf1d78e8e3b8ef39067df"
623
+ },
624
+ {
625
+ name: "openspec-propose",
626
+ file: "assets/skills/openspec-propose/SKILL.md",
627
+ description: "Skill de generación de proposal (OpenSpec)",
628
+ version: "0.6.2",
629
+ sha256: "f8d38be8e9432d69c43e28c2a2c6ddc860e94e844c79a5b3f78a5c4f8fcf8ce0"
630
+ },
631
+ {
632
+ name: "openspec-apply-change",
633
+ file: "assets/skills/openspec-apply-change/SKILL.md",
634
+ description: "Skill de aplicación de change (OpenSpec)",
635
+ version: "0.6.2",
636
+ sha256: "6c7779ed0dca40d70845dbcbcd5294867cab20eca98c6883a0207c4d10c29518"
637
+ },
638
+ {
639
+ name: "openspec-archive-change",
640
+ file: "assets/skills/openspec-archive-change/SKILL.md",
641
+ description: "Skill de archivo de change (OpenSpec)",
642
+ version: "0.6.2",
643
+ sha256: "0e566b7cd752784a58ef96bec28b0a85c933d72a8c93a5601ca1cd01669a5620"
644
+ },
645
+ {
646
+ name: "openspec-explore",
647
+ file: "assets/skills/openspec-explore/SKILL.md",
648
+ description: "Modo explore para OpenSpec — thinking partner para explorar ideas, investigar problemas y clarificar requisitos antes/durante un cambio",
649
+ version: "0.6.2",
650
+ sha256: "52746b6c51d5ed5026774391d55edac6558f488d68a5b84f9c7064a10e2333bb"
651
+ },
652
+ {
653
+ name: "using-git-worktrees",
654
+ file: "assets/skills/using-git-worktrees/SKILL.md",
655
+ description: "Skill de uso de git worktrees para aislamiento de trabajo",
656
+ version: "0.6.2",
657
+ sha256: "47dfb8b8f35520d3a516c1ac17083eabb0e7458904ef066ce219c48fd0c01037"
658
+ },
659
+ {
660
+ name: "using-superpowers",
661
+ file: "assets/skills/using-superpowers/SKILL.md",
662
+ description: "Skill de orquestación de Superpowers skills",
663
+ version: "0.6.2",
664
+ sha256: "f66cb61561a7fa23df40d9450459f4109ffc2f7a6f07efa74a8c1fcb96f105bd"
665
+ },
666
+ {
667
+ name: "writing-skills",
668
+ file: "assets/skills/writing-skills/SKILL.md",
669
+ description: "Skill de creación y edición de skills",
670
+ version: "0.6.2",
671
+ sha256: "397725e389ce4a80ef6864ec793d1b6f1ae158d1e33db56b8f5ff5167b3938fa"
672
+ },
673
+ {
674
+ name: "graceful-degradation",
675
+ file: "assets/skills/graceful-degradation/SKILL.md",
676
+ description: "Skill de degradación graceful cuando múltiples tools están indisponibles",
677
+ version: "0.6.2",
678
+ sha256: "e32b136c5dfce5b4e7eeddabd3d60866203f700002705ff65ccdec7826f01d71"
679
+ }
680
+ ]
695
681
  };
696
682
  });
697
683
 
698
- // node_modules/@clack/prompts/dist/index.mjs
699
- var exports_dist = {};
700
- __export(exports_dist, {
701
- updateSettings: () => hD,
702
- text: () => ue,
703
- tasks: () => xe,
704
- spinner: () => L2,
705
- selectKey: () => he,
706
- select: () => de,
707
- password: () => $e,
708
- outro: () => fe,
709
- note: () => ye,
710
- multiselect: () => pe,
711
- log: () => v2,
712
- isCancel: () => BD,
713
- intro: () => we,
714
- groupMultiselect: () => ge,
715
- group: () => be,
716
- confirm: () => me,
717
- cancel: () => ve
718
- });
719
- import { stripVTControlCharacters as T2 } from "node:util";
720
- import p from "node:process";
721
- function X2() {
722
- return p.platform !== "win32" ? p.env.TERM !== "linux" : !!p.env.CI || !!p.env.WT_SESSION || !!p.env.TERMINUS_SUBLIME || p.env.ConEmuTask === "{cmd::Cmder}" || p.env.TERM_PROGRAM === "Terminus-Sublime" || p.env.TERM_PROGRAM === "vscode" || p.env.TERM === "xterm-256color" || p.env.TERM === "alacritty" || p.env.TERMINAL_EMULATOR === "JetBrains-JediTerm";
684
+ // src/cache.ts
685
+ import { existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
686
+ import { join as join2, dirname as dirname2 } from "path";
687
+ function getCacheRoot(projectRoot) {
688
+ return join2(projectRoot, ".opencode", "cache");
723
689
  }
724
- var import_picocolors2, import_sisteransi2, E, u = (s, n) => E ? s : n, ee, A2, B, S2, te, a, m2, j2, R2, V2, M2, G2, se, N2, re, ie, ne, ae, oe, ce, le, y2 = (s) => {
725
- switch (s) {
726
- case "initial":
727
- case "active":
728
- return import_picocolors2.default.cyan(ee);
729
- case "cancel":
730
- return import_picocolors2.default.red(A2);
731
- case "error":
732
- return import_picocolors2.default.yellow(B);
733
- case "submit":
734
- return import_picocolors2.default.green(S2);
735
- }
736
- }, k2 = (s) => {
737
- const { cursor: n, options: t, style: i } = s, r2 = s.maxItems ?? Number.POSITIVE_INFINITY, c2 = Math.max(process.stdout.rows - 4, 0), o = Math.min(c2, Math.max(r2, 5));
738
- let l2 = 0;
739
- n >= l2 + o - 3 ? l2 = Math.max(Math.min(n - o + 3, t.length - o), 0) : n < l2 + 2 && (l2 = Math.max(n - 2, 0));
740
- const $2 = o < t.length && l2 > 0, d2 = o < t.length && l2 + o < t.length;
741
- return t.slice(l2, l2 + o).map((w2, b2, C) => {
742
- const I2 = b2 === 0 && $2, x2 = b2 === C.length - 1 && d2;
743
- return I2 || x2 ? import_picocolors2.default.dim("...") : i(w2, b2 + l2 === n);
744
- });
745
- }, ue = (s) => new PD({ validate: s.validate, placeholder: s.placeholder, defaultValue: s.defaultValue, initialValue: s.initialValue, render() {
746
- const n = `${import_picocolors2.default.gray(a)}
747
- ${y2(this.state)} ${s.message}
748
- `, t = s.placeholder ? import_picocolors2.default.inverse(s.placeholder[0]) + import_picocolors2.default.dim(s.placeholder.slice(1)) : import_picocolors2.default.inverse(import_picocolors2.default.hidden("_")), i = this.value ? this.valueWithCursor : t;
749
- switch (this.state) {
750
- case "error":
751
- return `${n.trim()}
752
- ${import_picocolors2.default.yellow(a)} ${i}
753
- ${import_picocolors2.default.yellow(m2)} ${import_picocolors2.default.yellow(this.error)}
754
- `;
755
- case "submit":
756
- return `${n}${import_picocolors2.default.gray(a)} ${import_picocolors2.default.dim(this.value || s.placeholder)}`;
757
- case "cancel":
758
- return `${n}${import_picocolors2.default.gray(a)} ${import_picocolors2.default.strikethrough(import_picocolors2.default.dim(this.value ?? ""))}${this.value?.trim() ? `
759
- ${import_picocolors2.default.gray(a)}` : ""}`;
760
- default:
761
- return `${n}${import_picocolors2.default.cyan(a)} ${i}
762
- ${import_picocolors2.default.cyan(m2)}
763
- `;
764
- }
765
- } }).prompt(), $e = (s) => new kD({ validate: s.validate, mask: s.mask ?? se, render() {
766
- const n = `${import_picocolors2.default.gray(a)}
767
- ${y2(this.state)} ${s.message}
768
- `, t = this.valueWithCursor, i = this.masked;
769
- switch (this.state) {
770
- case "error":
771
- return `${n.trim()}
772
- ${import_picocolors2.default.yellow(a)} ${i}
773
- ${import_picocolors2.default.yellow(m2)} ${import_picocolors2.default.yellow(this.error)}
774
- `;
775
- case "submit":
776
- return `${n}${import_picocolors2.default.gray(a)} ${import_picocolors2.default.dim(i)}`;
777
- case "cancel":
778
- return `${n}${import_picocolors2.default.gray(a)} ${import_picocolors2.default.strikethrough(import_picocolors2.default.dim(i ?? ""))}${i ? `
779
- ${import_picocolors2.default.gray(a)}` : ""}`;
780
- default:
781
- return `${n}${import_picocolors2.default.cyan(a)} ${t}
782
- ${import_picocolors2.default.cyan(m2)}
783
- `;
690
+ function cacheKey(projectRoot, repo, tag, filePath) {
691
+ const repoSlug = repo.replace("/", "__");
692
+ return join2(getCacheRoot(projectRoot), repoSlug, tag, filePath);
693
+ }
694
+ function getCached(projectRoot, repo, tag, filePath, expectedHash) {
695
+ const cachePath = cacheKey(projectRoot, repo, tag, filePath);
696
+ if (!existsSync2(cachePath))
697
+ return null;
698
+ try {
699
+ const content = readFileSync2(cachePath, "utf-8");
700
+ if (expectedHash && sha256(content) !== expectedHash)
701
+ return null;
702
+ return content;
703
+ } catch {
704
+ return null;
784
705
  }
785
- } }).prompt(), me = (s) => {
786
- const n = s.active ?? "Yes", t = s.inactive ?? "No";
787
- return new fD({ active: n, inactive: t, initialValue: s.initialValue ?? true, render() {
788
- const i = `${import_picocolors2.default.gray(a)}
789
- ${y2(this.state)} ${s.message}
790
- `, r2 = this.value ? n : t;
791
- switch (this.state) {
792
- case "submit":
793
- return `${i}${import_picocolors2.default.gray(a)} ${import_picocolors2.default.dim(r2)}`;
794
- case "cancel":
795
- return `${i}${import_picocolors2.default.gray(a)} ${import_picocolors2.default.strikethrough(import_picocolors2.default.dim(r2))}
796
- ${import_picocolors2.default.gray(a)}`;
797
- default:
798
- return `${i}${import_picocolors2.default.cyan(a)} ${this.value ? `${import_picocolors2.default.green(j2)} ${n}` : `${import_picocolors2.default.dim(R2)} ${import_picocolors2.default.dim(n)}`} ${import_picocolors2.default.dim("/")} ${this.value ? `${import_picocolors2.default.dim(R2)} ${import_picocolors2.default.dim(t)}` : `${import_picocolors2.default.green(j2)} ${t}`}
799
- ${import_picocolors2.default.cyan(m2)}
800
- `;
801
- }
802
- } }).prompt();
803
- }, de = (s) => {
804
- const n = (t, i) => {
805
- const r2 = t.label ?? String(t.value);
806
- switch (i) {
807
- case "selected":
808
- return `${import_picocolors2.default.dim(r2)}`;
809
- case "active":
810
- return `${import_picocolors2.default.green(j2)} ${r2} ${t.hint ? import_picocolors2.default.dim(`(${t.hint})`) : ""}`;
811
- case "cancelled":
812
- return `${import_picocolors2.default.strikethrough(import_picocolors2.default.dim(r2))}`;
813
- default:
814
- return `${import_picocolors2.default.dim(R2)} ${import_picocolors2.default.dim(r2)}`;
815
- }
816
- };
817
- return new jD({ options: s.options, initialValue: s.initialValue, render() {
818
- const t = `${import_picocolors2.default.gray(a)}
819
- ${y2(this.state)} ${s.message}
820
- `;
821
- switch (this.state) {
822
- case "submit":
823
- return `${t}${import_picocolors2.default.gray(a)} ${n(this.options[this.cursor], "selected")}`;
824
- case "cancel":
825
- return `${t}${import_picocolors2.default.gray(a)} ${n(this.options[this.cursor], "cancelled")}
826
- ${import_picocolors2.default.gray(a)}`;
827
- default:
828
- return `${t}${import_picocolors2.default.cyan(a)} ${k2({ cursor: this.cursor, options: this.options, maxItems: s.maxItems, style: (i, r2) => n(i, r2 ? "active" : "inactive") }).join(`
829
- ${import_picocolors2.default.cyan(a)} `)}
830
- ${import_picocolors2.default.cyan(m2)}
831
- `;
832
- }
833
- } }).prompt();
834
- }, he = (s) => {
835
- const n = (t, i = "inactive") => {
836
- const r2 = t.label ?? String(t.value);
837
- return i === "selected" ? `${import_picocolors2.default.dim(r2)}` : i === "cancelled" ? `${import_picocolors2.default.strikethrough(import_picocolors2.default.dim(r2))}` : i === "active" ? `${import_picocolors2.default.bgCyan(import_picocolors2.default.gray(` ${t.value} `))} ${r2} ${t.hint ? import_picocolors2.default.dim(`(${t.hint})`) : ""}` : `${import_picocolors2.default.gray(import_picocolors2.default.bgWhite(import_picocolors2.default.inverse(` ${t.value} `)))} ${r2} ${t.hint ? import_picocolors2.default.dim(`(${t.hint})`) : ""}`;
838
- };
839
- return new OD({ options: s.options, initialValue: s.initialValue, render() {
840
- const t = `${import_picocolors2.default.gray(a)}
841
- ${y2(this.state)} ${s.message}
842
- `;
843
- switch (this.state) {
844
- case "submit":
845
- return `${t}${import_picocolors2.default.gray(a)} ${n(this.options.find((i) => i.value === this.value) ?? s.options[0], "selected")}`;
846
- case "cancel":
847
- return `${t}${import_picocolors2.default.gray(a)} ${n(this.options[0], "cancelled")}
848
- ${import_picocolors2.default.gray(a)}`;
849
- default:
850
- return `${t}${import_picocolors2.default.cyan(a)} ${this.options.map((i, r2) => n(i, r2 === this.cursor ? "active" : "inactive")).join(`
851
- ${import_picocolors2.default.cyan(a)} `)}
852
- ${import_picocolors2.default.cyan(m2)}
853
- `;
854
- }
855
- } }).prompt();
856
- }, pe = (s) => {
857
- const n = (t, i) => {
858
- const r2 = t.label ?? String(t.value);
859
- return i === "active" ? `${import_picocolors2.default.cyan(V2)} ${r2} ${t.hint ? import_picocolors2.default.dim(`(${t.hint})`) : ""}` : i === "selected" ? `${import_picocolors2.default.green(M2)} ${import_picocolors2.default.dim(r2)}` : i === "cancelled" ? `${import_picocolors2.default.strikethrough(import_picocolors2.default.dim(r2))}` : i === "active-selected" ? `${import_picocolors2.default.green(M2)} ${r2} ${t.hint ? import_picocolors2.default.dim(`(${t.hint})`) : ""}` : i === "submitted" ? `${import_picocolors2.default.dim(r2)}` : `${import_picocolors2.default.dim(G2)} ${import_picocolors2.default.dim(r2)}`;
860
- };
861
- return new wD({ options: s.options, initialValues: s.initialValues, required: s.required ?? true, cursorAt: s.cursorAt, validate(t) {
862
- if (this.required && t.length === 0)
863
- return `Please select at least one option.
864
- ${import_picocolors2.default.reset(import_picocolors2.default.dim(`Press ${import_picocolors2.default.gray(import_picocolors2.default.bgWhite(import_picocolors2.default.inverse(" space ")))} to select, ${import_picocolors2.default.gray(import_picocolors2.default.bgWhite(import_picocolors2.default.inverse(" enter ")))} to submit`))}`;
865
- }, render() {
866
- const t = `${import_picocolors2.default.gray(a)}
867
- ${y2(this.state)} ${s.message}
868
- `, i = (r2, c2) => {
869
- const o = this.value.includes(r2.value);
870
- return c2 && o ? n(r2, "active-selected") : o ? n(r2, "selected") : n(r2, c2 ? "active" : "inactive");
871
- };
872
- switch (this.state) {
873
- case "submit":
874
- return `${t}${import_picocolors2.default.gray(a)} ${this.options.filter(({ value: r2 }) => this.value.includes(r2)).map((r2) => n(r2, "submitted")).join(import_picocolors2.default.dim(", ")) || import_picocolors2.default.dim("none")}`;
875
- case "cancel": {
876
- const r2 = this.options.filter(({ value: c2 }) => this.value.includes(c2)).map((c2) => n(c2, "cancelled")).join(import_picocolors2.default.dim(", "));
877
- return `${t}${import_picocolors2.default.gray(a)} ${r2.trim() ? `${r2}
878
- ${import_picocolors2.default.gray(a)}` : ""}`;
879
- }
880
- case "error": {
881
- const r2 = this.error.split(`
882
- `).map((c2, o) => o === 0 ? `${import_picocolors2.default.yellow(m2)} ${import_picocolors2.default.yellow(c2)}` : ` ${c2}`).join(`
883
- `);
884
- return `${t + import_picocolors2.default.yellow(a)} ${k2({ options: this.options, cursor: this.cursor, maxItems: s.maxItems, style: i }).join(`
885
- ${import_picocolors2.default.yellow(a)} `)}
886
- ${r2}
887
- `;
888
- }
889
- default:
890
- return `${t}${import_picocolors2.default.cyan(a)} ${k2({ options: this.options, cursor: this.cursor, maxItems: s.maxItems, style: i }).join(`
891
- ${import_picocolors2.default.cyan(a)} `)}
892
- ${import_picocolors2.default.cyan(m2)}
893
- `;
706
+ }
707
+ function putCache(projectRoot, repo, tag, filePath, content) {
708
+ const cachePath = cacheKey(projectRoot, repo, tag, filePath);
709
+ const dir = dirname2(cachePath);
710
+ if (!existsSync2(dir))
711
+ mkdirSync2(dir, { recursive: true });
712
+ writeFileSync2(cachePath, content, "utf-8");
713
+ }
714
+ var init_cache = __esm(() => {
715
+ init_security();
716
+ });
717
+
718
+ // src/github.ts
719
+ import { fileURLToPath } from "url";
720
+ import { dirname as dirname3, join as join3 } from "path";
721
+ function getBundledSkillPath(name) {
722
+ validateFilePath(name);
723
+ return join3(BUNDLED_SKILLS_DIR, name);
724
+ }
725
+ function getBundledMcpPath(name) {
726
+ validateFilePath(name);
727
+ return join3(BUNDLED_MCP_DIR, name);
728
+ }
729
+ function getRawUrl(repo, tag, path) {
730
+ return `${GITHUB_RAW}/${repo}/${tag}/${path}`;
731
+ }
732
+ async function fetchLatestReleaseTag(repo) {
733
+ try {
734
+ const res = await fetch(`https://api.github.com/repos/${repo}/releases/latest`, {
735
+ signal: AbortSignal.timeout(5000),
736
+ headers: { "User-Agent": USER_AGENT }
737
+ });
738
+ if (res.ok) {
739
+ const data = await res.json();
740
+ return data.tag_name ?? null;
894
741
  }
895
- } }).prompt();
896
- }, ge = (s) => {
897
- const n = (t, i, r2 = []) => {
898
- const c2 = t.label ?? String(t.value), o = typeof t.group == "string", l2 = o && (r2[r2.indexOf(t) + 1] ?? { group: true }), $2 = o && l2.group === true, d2 = o ? `${$2 ? m2 : a} ` : "";
899
- return i === "active" ? `${import_picocolors2.default.dim(d2)}${import_picocolors2.default.cyan(V2)} ${c2} ${t.hint ? import_picocolors2.default.dim(`(${t.hint})`) : ""}` : i === "group-active" ? `${d2}${import_picocolors2.default.cyan(V2)} ${import_picocolors2.default.dim(c2)}` : i === "group-active-selected" ? `${d2}${import_picocolors2.default.green(M2)} ${import_picocolors2.default.dim(c2)}` : i === "selected" ? `${import_picocolors2.default.dim(d2)}${import_picocolors2.default.green(M2)} ${import_picocolors2.default.dim(c2)}` : i === "cancelled" ? `${import_picocolors2.default.strikethrough(import_picocolors2.default.dim(c2))}` : i === "active-selected" ? `${import_picocolors2.default.dim(d2)}${import_picocolors2.default.green(M2)} ${c2} ${t.hint ? import_picocolors2.default.dim(`(${t.hint})`) : ""}` : i === "submitted" ? `${import_picocolors2.default.dim(c2)}` : `${import_picocolors2.default.dim(d2)}${import_picocolors2.default.dim(G2)} ${import_picocolors2.default.dim(c2)}`;
900
- };
901
- return new dD({ options: s.options, initialValues: s.initialValues, required: s.required ?? true, cursorAt: s.cursorAt, validate(t) {
902
- if (this.required && t.length === 0)
903
- return `Please select at least one option.
904
- ${import_picocolors2.default.reset(import_picocolors2.default.dim(`Press ${import_picocolors2.default.gray(import_picocolors2.default.bgWhite(import_picocolors2.default.inverse(" space ")))} to select, ${import_picocolors2.default.gray(import_picocolors2.default.bgWhite(import_picocolors2.default.inverse(" enter ")))} to submit`))}`;
905
- }, render() {
906
- const t = `${import_picocolors2.default.gray(a)}
907
- ${y2(this.state)} ${s.message}
908
- `;
909
- switch (this.state) {
910
- case "submit":
911
- return `${t}${import_picocolors2.default.gray(a)} ${this.options.filter(({ value: i }) => this.value.includes(i)).map((i) => n(i, "submitted")).join(import_picocolors2.default.dim(", "))}`;
912
- case "cancel": {
913
- const i = this.options.filter(({ value: r2 }) => this.value.includes(r2)).map((r2) => n(r2, "cancelled")).join(import_picocolors2.default.dim(", "));
914
- return `${t}${import_picocolors2.default.gray(a)} ${i.trim() ? `${i}
915
- ${import_picocolors2.default.gray(a)}` : ""}`;
916
- }
917
- case "error": {
918
- const i = this.error.split(`
919
- `).map((r2, c2) => c2 === 0 ? `${import_picocolors2.default.yellow(m2)} ${import_picocolors2.default.yellow(r2)}` : ` ${r2}`).join(`
920
- `);
921
- return `${t}${import_picocolors2.default.yellow(a)} ${this.options.map((r2, c2, o) => {
922
- const l2 = this.value.includes(r2.value) || r2.group === true && this.isGroupSelected(`${r2.value}`), $2 = c2 === this.cursor;
923
- return !$2 && typeof r2.group == "string" && this.options[this.cursor].value === r2.group ? n(r2, l2 ? "group-active-selected" : "group-active", o) : $2 && l2 ? n(r2, "active-selected", o) : l2 ? n(r2, "selected", o) : n(r2, $2 ? "active" : "inactive", o);
924
- }).join(`
925
- ${import_picocolors2.default.yellow(a)} `)}
926
- ${i}
927
- `;
928
- }
929
- default:
930
- return `${t}${import_picocolors2.default.cyan(a)} ${this.options.map((i, r2, c2) => {
931
- const o = this.value.includes(i.value) || i.group === true && this.isGroupSelected(`${i.value}`), l2 = r2 === this.cursor;
932
- return !l2 && typeof i.group == "string" && this.options[this.cursor].value === i.group ? n(i, o ? "group-active-selected" : "group-active", c2) : l2 && o ? n(i, "active-selected", c2) : o ? n(i, "selected", c2) : n(i, l2 ? "active" : "inactive", c2);
933
- }).join(`
934
- ${import_picocolors2.default.cyan(a)} `)}
935
- ${import_picocolors2.default.cyan(m2)}
936
- `;
742
+ } catch {}
743
+ try {
744
+ const res = await fetch(`https://github.com/${repo}/releases/latest`, {
745
+ redirect: "manual",
746
+ signal: AbortSignal.timeout(5000),
747
+ headers: { "User-Agent": USER_AGENT }
748
+ });
749
+ const loc = res.headers.get("location") ?? "";
750
+ const m3 = loc.match(/releases\/tag\/(v[^/]+)$/);
751
+ if (m3)
752
+ return m3[1];
753
+ } catch {}
754
+ return null;
755
+ }
756
+ async function fetchManifest(tag) {
757
+ const resolvedTag = tag ?? manifest_default.tag;
758
+ try {
759
+ const url = getRawUrl(manifest_default.repo, resolvedTag, "manifest.json");
760
+ const response = await fetch(url, {
761
+ signal: AbortSignal.timeout(5000),
762
+ headers: { "User-Agent": USER_AGENT }
763
+ });
764
+ if (response.ok) {
765
+ return await response.json();
937
766
  }
938
- } }).prompt();
939
- }, ye = (s = "", n = "") => {
940
- const t = `
941
- ${s}
942
- `.split(`
943
- `), i = T2(n).length, r2 = Math.max(t.reduce((o, l2) => {
944
- const $2 = T2(l2);
945
- return $2.length > o ? $2.length : o;
946
- }, 0), i) + 2, c2 = t.map((o) => `${import_picocolors2.default.gray(a)} ${import_picocolors2.default.dim(o)}${" ".repeat(r2 - T2(o).length)}${import_picocolors2.default.gray(a)}`).join(`
947
- `);
948
- process.stdout.write(`${import_picocolors2.default.gray(a)}
949
- ${import_picocolors2.default.green(S2)} ${import_picocolors2.default.reset(n)} ${import_picocolors2.default.gray(N2.repeat(Math.max(r2 - i - 1, 1)) + re)}
950
- ${c2}
951
- ${import_picocolors2.default.gray(ie + N2.repeat(r2 + 2) + ne)}
952
- `);
953
- }, ve = (s = "") => {
954
- process.stdout.write(`${import_picocolors2.default.gray(m2)} ${import_picocolors2.default.red(s)}
955
-
956
- `);
957
- }, we = (s = "") => {
958
- process.stdout.write(`${import_picocolors2.default.gray(te)} ${s}
959
- `);
960
- }, fe = (s = "") => {
961
- process.stdout.write(`${import_picocolors2.default.gray(a)}
962
- ${import_picocolors2.default.gray(m2)} ${s}
767
+ } catch {}
768
+ return manifest_default;
769
+ }
770
+ async function fetchLatestManifest() {
771
+ const latestTag = await fetchLatestReleaseTag(manifest_default.repo);
772
+ const currentTag = manifest_default.tag;
773
+ const isNew = latestTag !== null && latestTag !== currentTag;
774
+ const manifest = await fetchManifest(latestTag ?? currentTag);
775
+ return { manifest, isNew, latestTag };
776
+ }
777
+ async function downloadFile(manifest, filePath) {
778
+ validateFilePath(filePath);
779
+ const item = [
780
+ ...manifest.agents,
781
+ ...manifest.commands,
782
+ ...manifest.skills ?? [],
783
+ ...manifest.mcpServers ?? []
784
+ ].find((i) => i.file === filePath);
785
+ const expectedHash = item?.sha256 ?? null;
786
+ const projectRoot = findProjectRoot();
787
+ const cached = getCached(projectRoot, manifest.repo, manifest.tag, filePath, expectedHash);
788
+ if (cached !== null)
789
+ return cached;
790
+ const url = getRawUrl(manifest.repo, manifest.tag, filePath);
791
+ const response = await fetch(url, {
792
+ headers: { "User-Agent": USER_AGENT },
793
+ signal: AbortSignal.timeout(30000)
794
+ });
795
+ if (!response.ok) {
796
+ throw new Error(`Error descargando ${url}: ${response.status} ${response.statusText}`);
797
+ }
798
+ const content = await response.text();
799
+ verifyChecksum(content, expectedHash, filePath);
800
+ putCache(projectRoot, manifest.repo, manifest.tag, filePath, content);
801
+ return content;
802
+ }
803
+ var GITHUB_RAW = "https://raw.githubusercontent.com", __filename2, __dirname2, PACKAGE_ROOT, BUNDLED_SKILLS_DIR, BUNDLED_MCP_DIR;
804
+ var init_github = __esm(() => {
805
+ init_manifest();
806
+ init_cache();
807
+ init_security();
808
+ init_fs();
809
+ __filename2 = fileURLToPath(import.meta.url);
810
+ __dirname2 = dirname3(__filename2);
811
+ PACKAGE_ROOT = join3(__dirname2, "..");
812
+ BUNDLED_SKILLS_DIR = join3(PACKAGE_ROOT, "assets", "skills");
813
+ BUNDLED_MCP_DIR = join3(PACKAGE_ROOT, "assets", "mcp");
814
+ });
963
815
 
964
- `);
965
- }, v2, L2 = () => {
966
- const s = E ? ["◒", "◐", "◓", "◑"] : ["•", "o", "O", "0"], n = E ? 80 : 120, t = process.env.CI === "true";
967
- let i, r2, c2 = false, o = "", l2;
968
- const $2 = (h2) => {
969
- const g2 = h2 > 1 ? "Something went wrong" : "Canceled";
970
- c2 && P2(g2, h2);
971
- }, d2 = () => $2(2), w2 = () => $2(1), b2 = () => {
972
- process.on("uncaughtExceptionMonitor", d2), process.on("unhandledRejection", d2), process.on("SIGINT", w2), process.on("SIGTERM", w2), process.on("exit", $2);
973
- }, C = () => {
974
- process.removeListener("uncaughtExceptionMonitor", d2), process.removeListener("unhandledRejection", d2), process.removeListener("SIGINT", w2), process.removeListener("SIGTERM", w2), process.removeListener("exit", $2);
975
- }, I2 = () => {
976
- if (l2 === undefined)
977
- return;
978
- t && process.stdout.write(`
979
- `);
980
- const h2 = l2.split(`
981
- `);
982
- process.stdout.write(import_sisteransi2.cursor.move(-999, h2.length - 1)), process.stdout.write(import_sisteransi2.erase.down(h2.length));
983
- }, x2 = (h2) => h2.replace(/\.+$/, ""), O2 = (h2 = "") => {
984
- c2 = true, i = cD(), o = x2(h2), process.stdout.write(`${import_picocolors2.default.gray(a)}
985
- `);
986
- let g2 = 0, f2 = 0;
987
- b2(), r2 = setInterval(() => {
988
- if (t && o === l2)
989
- return;
990
- I2(), l2 = o;
991
- const W2 = import_picocolors2.default.magenta(s[g2]), _2 = t ? "..." : ".".repeat(Math.floor(f2)).slice(0, 3);
992
- process.stdout.write(`${W2} ${o}${_2}`), g2 = g2 + 1 < s.length ? g2 + 1 : 0, f2 = f2 < s.length ? f2 + 0.125 : 0;
993
- }, n);
994
- }, P2 = (h2 = "", g2 = 0) => {
995
- c2 = false, clearInterval(r2), I2();
996
- const f2 = g2 === 0 ? import_picocolors2.default.green(S2) : g2 === 1 ? import_picocolors2.default.red(A2) : import_picocolors2.default.red(B);
997
- o = x2(h2 ?? o), process.stdout.write(`${f2} ${o}
998
- `), C(), i();
999
- };
1000
- return { start: O2, stop: P2, message: (h2 = "") => {
1001
- o = x2(h2 ?? o);
1002
- } };
1003
- }, be = async (s, n) => {
1004
- const t = {}, i = Object.keys(s);
1005
- for (const r2 of i) {
1006
- const c2 = s[r2], o = await c2({ results: t })?.catch((l2) => {
1007
- throw l2;
816
+ // src/lockfile.ts
817
+ var exports_lockfile = {};
818
+ __export(exports_lockfile, {
819
+ writeLockfile: () => writeLockfile,
820
+ removeFromLockfile: () => removeFromLockfile,
821
+ readLockfile: () => readLockfile,
822
+ getLockfilePath: () => getLockfilePath,
823
+ getInstalledVersion: () => getInstalledVersion,
824
+ clearLockfile: () => clearLockfile
825
+ });
826
+ import { existsSync as existsSync3, readFileSync as readFileSync3, writeFileSync as writeFileSync3 } from "fs";
827
+ import { join as join4 } from "path";
828
+ function getLockfilePath(opencodeRoot) {
829
+ return join4(opencodeRoot, LOCKFILE_NAME);
830
+ }
831
+ function readLockfile(opencodeRoot) {
832
+ const lockPath = getLockfilePath(opencodeRoot);
833
+ if (!existsSync3(lockPath))
834
+ return null;
835
+ try {
836
+ return JSON.parse(readFileSync3(lockPath, "utf-8"));
837
+ } catch {
838
+ return null;
839
+ }
840
+ }
841
+ function writeLockfile(opencodeRoot, lockfile) {
842
+ writeFileSync3(getLockfilePath(opencodeRoot), JSON.stringify(lockfile, null, 2), "utf-8");
843
+ }
844
+ function getInstalledVersion(lockfile, type, name) {
845
+ return lockfile?.[type]?.[name]?.version ?? null;
846
+ }
847
+ function removeFromLockfile(opencodeRoot, type, name) {
848
+ const lockfile = readLockfile(opencodeRoot);
849
+ if (!lockfile)
850
+ return;
851
+ if (!lockfile[type])
852
+ return;
853
+ if (!(name in lockfile[type]))
854
+ return;
855
+ delete lockfile[type][name];
856
+ writeLockfile(opencodeRoot, lockfile);
857
+ }
858
+ function clearLockfile(opencodeRoot) {
859
+ const lockfile = readLockfile(opencodeRoot);
860
+ if (!lockfile) {
861
+ writeLockfile(opencodeRoot, {
862
+ version: LOCKFILE_VERSION,
863
+ lockedAt: new Date().toISOString(),
864
+ repo: "",
865
+ tag: "",
866
+ agents: {},
867
+ commands: {},
868
+ skills: {},
869
+ mcpServers: {}
1008
870
  });
1009
- if (typeof n?.onCancel == "function" && BD(o)) {
1010
- t[r2] = "canceled", n.onCancel({ results: t });
871
+ return;
872
+ }
873
+ lockfile.agents = {};
874
+ lockfile.commands = {};
875
+ lockfile.skills = {};
876
+ lockfile.mcpServers = {};
877
+ lockfile.lockedAt = new Date().toISOString();
878
+ writeLockfile(opencodeRoot, lockfile);
879
+ }
880
+ var LOCKFILE_NAME = "ostacky-lock.json", LOCKFILE_VERSION;
881
+ var init_lockfile = __esm(() => {
882
+ init_manifest();
883
+ LOCKFILE_VERSION = manifest_default.version;
884
+ });
885
+
886
+ // src/config.ts
887
+ var exports_config = {};
888
+ __export(exports_config, {
889
+ writeOpenCodeConfig: () => writeOpenCodeConfig,
890
+ stripJsoncComments: () => stripJsoncComments,
891
+ setMcpEntryAtProjectRoot: () => setMcpEntryAtProjectRoot,
892
+ setMcpEntry: () => setMcpEntry,
893
+ readOpenCodeConfig: () => readOpenCodeConfig,
894
+ patchOpenCodeConfig: () => patchOpenCodeConfig,
895
+ findOpenCodeConfig: () => findOpenCodeConfig,
896
+ ensureOpenCodeConfig: () => ensureOpenCodeConfig,
897
+ ensureMcpEntryAtProjectRoot: () => ensureMcpEntryAtProjectRoot,
898
+ ensureMcpEntry: () => ensureMcpEntry
899
+ });
900
+ import { existsSync as existsSync4, readFileSync as readFileSync4, renameSync as renameSync2, rmSync as rmSync2, writeFileSync as writeFileSync4 } from "fs";
901
+ import { join as join5 } from "path";
902
+ function stripJsoncComments(text) {
903
+ let result = "";
904
+ let i = 0;
905
+ let inString = false;
906
+ while (i < text.length) {
907
+ const char = text[i];
908
+ const next = text[i + 1];
909
+ if (inString) {
910
+ if (char === "\\") {
911
+ result += char + (next ?? "");
912
+ i += 2;
913
+ continue;
914
+ }
915
+ if (char === '"')
916
+ inString = false;
917
+ result += char;
918
+ i++;
1011
919
  continue;
1012
920
  }
1013
- t[r2] = o;
1014
- }
1015
- return t;
1016
- }, xe = async (s) => {
1017
- for (const n of s) {
1018
- if (n.enabled === false)
921
+ if (char === '"') {
922
+ inString = true;
923
+ result += char;
924
+ i++;
1019
925
  continue;
1020
- const t = L2();
1021
- t.start(n.title);
1022
- const i = await n.task(t.message);
1023
- t.stop(i || n.title);
1024
- }
1025
- };
1026
- var init_dist2 = __esm(() => {
1027
- init_dist();
1028
- init_dist();
1029
- import_picocolors2 = __toESM(require_picocolors(), 1);
1030
- import_sisteransi2 = __toESM(require_src(), 1);
1031
- E = X2();
1032
- ee = u("◆", "*");
1033
- A2 = u("■", "x");
1034
- B = u("▲", "x");
1035
- S2 = u("◇", "o");
1036
- te = u("┌", "T");
1037
- a = u("│", "|");
1038
- m2 = u("└", "—");
1039
- j2 = u("●", ">");
1040
- R2 = u("○", " ");
1041
- V2 = u("◻", "[•]");
1042
- M2 = u("◼", "[+]");
1043
- G2 = u("◻", "[ ]");
1044
- se = u("▪", "•");
1045
- N2 = u("─", "-");
1046
- re = u("╮", "+");
1047
- ie = u("├", "+");
1048
- ne = u("╯", "+");
1049
- ae = u("●", "•");
1050
- oe = u("◆", "*");
1051
- ce = u("▲", "!");
1052
- le = u("■", "x");
1053
- v2 = { message: (s = "", { symbol: n = import_picocolors2.default.gray(a) } = {}) => {
1054
- const t = [`${import_picocolors2.default.gray(a)}`];
1055
- if (s) {
1056
- const [i, ...r2] = s.split(`
1057
- `);
1058
- t.push(`${n} ${i}`, ...r2.map((c2) => `${import_picocolors2.default.gray(a)} ${c2}`));
1059
926
  }
1060
- process.stdout.write(`${t.join(`
1061
- `)}
1062
- `);
1063
- }, info: (s) => {
1064
- v2.message(s, { symbol: import_picocolors2.default.blue(ae) });
1065
- }, success: (s) => {
1066
- v2.message(s, { symbol: import_picocolors2.default.green(oe) });
1067
- }, step: (s) => {
1068
- v2.message(s, { symbol: import_picocolors2.default.green(S2) });
1069
- }, warn: (s) => {
1070
- v2.message(s, { symbol: import_picocolors2.default.yellow(ce) });
1071
- }, warning: (s) => {
1072
- v2.warn(s);
1073
- }, error: (s) => {
1074
- v2.message(s, { symbol: import_picocolors2.default.red(le) });
1075
- } };
927
+ if (char === "/" && next === "/") {
928
+ while (i < text.length && text[i] !== `
929
+ `)
930
+ i++;
931
+ continue;
932
+ }
933
+ if (char === "/" && next === "*") {
934
+ i += 2;
935
+ while (i < text.length && !(text[i] === "*" && text[i + 1] === "/"))
936
+ i++;
937
+ i += 2;
938
+ continue;
939
+ }
940
+ result += char;
941
+ i++;
942
+ }
943
+ return result.replace(/,\s*([}\]])/g, "$1");
944
+ }
945
+ function readOpenCodeConfig(configPath) {
946
+ const raw = readFileSync4(configPath, "utf-8");
947
+ try {
948
+ return JSON.parse(stripJsoncComments(raw));
949
+ } catch {
950
+ return null;
951
+ }
952
+ }
953
+ function writeOpenCodeConfig(configPath, config) {
954
+ const tmpPath = `${configPath}.tmp.${process.pid}.${Date.now()}`;
955
+ try {
956
+ writeFileSync4(tmpPath, JSON.stringify(config, null, 2) + `
957
+ `, "utf-8");
958
+ renameSync2(tmpPath, configPath);
959
+ } finally {
960
+ if (existsSync4(tmpPath))
961
+ rmSync2(tmpPath, { force: true });
962
+ }
963
+ }
964
+ function ensureOpenCodeConfig(projectRoot) {
965
+ const existing = findOpenCodeConfig(projectRoot);
966
+ if (existing)
967
+ return existing;
968
+ const configPath = join5(projectRoot, "opencode.json");
969
+ writeOpenCodeConfig(configPath, {
970
+ $schema: "https://opencode.ai/config.json",
971
+ mcp: {}
972
+ });
973
+ return configPath;
974
+ }
975
+ function findOpenCodeConfig(projectRoot) {
976
+ const candidates = ["opencode.json", "opencode.jsonc"];
977
+ for (const name of candidates) {
978
+ const full = join5(projectRoot, name);
979
+ if (existsSync4(full))
980
+ return full;
981
+ }
982
+ return null;
983
+ }
984
+ function setMcpEntry(name, entry) {
985
+ setMcpEntryAtProjectRoot(findProjectRoot(), name, entry);
986
+ }
987
+ function setMcpEntryAtProjectRoot(projectRoot, name, entry) {
988
+ const configPath = ensureOpenCodeConfig(projectRoot);
989
+ const config = readOpenCodeConfig(configPath);
990
+ if (!config)
991
+ throw new Error(`Error parseando ${configPath}`);
992
+ if (!config.mcp)
993
+ config.mcp = {};
994
+ config.mcp[name] = entry;
995
+ writeOpenCodeConfig(configPath, config);
996
+ }
997
+ function ensureMcpEntry(name, entry) {
998
+ ensureMcpEntryAtProjectRoot(findProjectRoot(), name, entry);
999
+ }
1000
+ function ensureMcpEntryAtProjectRoot(projectRoot, name, entry) {
1001
+ const configPath = ensureOpenCodeConfig(projectRoot);
1002
+ const config = readOpenCodeConfig(configPath);
1003
+ if (!config)
1004
+ throw new Error(`Error parseando ${configPath}`);
1005
+ if (!config.mcp)
1006
+ config.mcp = {};
1007
+ const mcp = config.mcp;
1008
+ if (!mcp[name]) {
1009
+ mcp[name] = entry;
1010
+ writeOpenCodeConfig(configPath, config);
1011
+ }
1012
+ }
1013
+ function patchOpenCodeConfig(projectRoot = findProjectRoot()) {
1014
+ const configPath = findOpenCodeConfig(projectRoot);
1015
+ if (!configPath) {
1016
+ return {
1017
+ success: false,
1018
+ message: "No se encontró opencode.json ni opencode.jsonc"
1019
+ };
1020
+ }
1021
+ const config = readOpenCodeConfig(configPath);
1022
+ if (!config) {
1023
+ return {
1024
+ success: false,
1025
+ message: `Error parseando ${configPath}`
1026
+ };
1027
+ }
1028
+ let changed = false;
1029
+ if ("plugin" in config) {
1030
+ delete config.plugin;
1031
+ changed = true;
1032
+ }
1033
+ if (changed) {
1034
+ writeOpenCodeConfig(configPath, config);
1035
+ return { success: true, message: "Config actualizada (plugin legacy eliminado)" };
1036
+ }
1037
+ return { success: true, message: "Config de OpenCode ya está limpia" };
1038
+ }
1039
+ var init_config = __esm(() => {
1040
+ init_fs();
1076
1041
  });
1077
1042
 
1078
- // src/security.ts
1079
- var exports_security = {};
1080
- __export(exports_security, {
1081
- verifyChecksum: () => verifyChecksum,
1082
- validateFilePath: () => validateFilePath,
1083
- sha256: () => sha256
1043
+ // src/stack.ts
1044
+ var exports_stack = {};
1045
+ __export(exports_stack, {
1046
+ verifyMcpServers: () => verifyMcpServers,
1047
+ uninstallStackConfig: () => uninstallStackConfig,
1048
+ uninstallEngramConfig: () => uninstallEngramConfig,
1049
+ setupOpenSpec: () => setupOpenSpec,
1050
+ setupContext7: () => setupContext7,
1051
+ installStack: () => installStack,
1052
+ installEngram: () => installEngram,
1053
+ installCodeGraph: () => installCodeGraph,
1054
+ buildLocalMcpCommand: () => buildLocalMcpCommand,
1055
+ buildEngramDownloadUrl: () => buildEngramDownloadUrl
1084
1056
  });
1085
- import { createHash } from "crypto";
1086
- function validateFilePath(filePath) {
1087
- if (filePath.includes("..") || filePath.startsWith("/") || filePath.startsWith("\\") || /^[a-zA-Z]:/.test(filePath)) {
1088
- throw new Error(`Ruta de archivo inválida: "${filePath}"`);
1089
- }
1057
+ import { chmodSync, copyFileSync as copyFileSync3, existsSync as existsSync6, mkdirSync as mkdirSync4, rmSync as rmSync4, unlinkSync as unlinkSync3 } from "fs";
1058
+ import { basename as basename2, dirname as dirname5, join as join7, resolve as resolve2 } from "path";
1059
+ import { execFileSync as execFileSync3 } from "child_process";
1060
+ function resolveToolInstallLocation(toolsDir) {
1061
+ const resolvedToolsDir = resolve2(toolsDir ?? join7(findProjectRoot(), ".opencode", "tools"));
1062
+ const possibleOpenCodeDir = dirname5(resolvedToolsDir);
1063
+ return {
1064
+ projectRoot: basename2(possibleOpenCodeDir) === ".opencode" ? dirname5(possibleOpenCodeDir) : findProjectRoot(),
1065
+ toolsDir: resolvedToolsDir
1066
+ };
1090
1067
  }
1091
- function sha256(content) {
1092
- return createHash("sha256").update(content, "utf-8").digest("hex");
1068
+ function runTool(binary, args, cwd, timeout = 30000) {
1069
+ const invocation = getCommandInvocation(binary, args);
1070
+ execFileSync3(invocation.command, invocation.args, {
1071
+ cwd,
1072
+ stdio: "pipe",
1073
+ timeout
1074
+ });
1093
1075
  }
1094
- function verifyChecksum(content, expectedHash, label) {
1095
- if (!expectedHash)
1096
- return;
1097
- const actual = sha256(content);
1098
- if (actual !== expectedHash) {
1099
- throw new Error(`Checksum inválido para "${label}"
1100
- esperado: ${expectedHash}
1101
- recibido: ${actual}`);
1076
+ function findToolBinary(toolDir, name) {
1077
+ const binDir = join7(toolDir, "bin");
1078
+ for (const executable of getExecutableNames(name)) {
1079
+ const candidate = join7(binDir, executable);
1080
+ if (existsSync6(candidate))
1081
+ return candidate;
1102
1082
  }
1083
+ return findBinaryInDir(toolDir, name);
1103
1084
  }
1104
- var init_security = () => {};
1105
-
1106
- // src/fs.ts
1107
- import {
1108
- existsSync,
1109
- mkdirSync,
1110
- unlinkSync,
1111
- readdirSync,
1112
- statSync,
1113
- copyFileSync,
1114
- readFileSync,
1115
- rmSync,
1116
- createWriteStream
1117
- } from "fs";
1118
- import { createHash as createHash2 } from "crypto";
1119
- import { join, resolve, dirname, relative } from "path";
1120
- import { execSync } from "child_process";
1121
- function findOpenCodeDir(startDir = process.cwd()) {
1122
- let current = resolve(startDir);
1123
- while (true) {
1124
- const opencodeDir = join(current, ".opencode");
1125
- if (existsSync(opencodeDir))
1126
- return opencodeDir;
1127
- if (existsSync(join(current, ".git")))
1128
- return null;
1129
- const parent = dirname(current);
1130
- if (parent === current)
1131
- return null;
1132
- current = parent;
1085
+ function configureLocalTool(projectRoot, name, command) {
1086
+ setMcpEntryAtProjectRoot(projectRoot, name, {
1087
+ type: "local",
1088
+ command,
1089
+ enabled: true
1090
+ });
1091
+ }
1092
+ function buildLocalMcpCommand(executable, args, platform = process.platform) {
1093
+ const invocation = getCommandInvocation(executable, args, platform);
1094
+ return [invocation.command, ...invocation.args];
1095
+ }
1096
+ function copyEngramPlugin(projectRoot) {
1097
+ const pluginSource = join7(PACKAGE_ROOT, "assets", "plugins", "engram.ts");
1098
+ const pluginsDir = join7(projectRoot, ".opencode", "plugins");
1099
+ if (!existsSync6(pluginSource)) {
1100
+ throw new Error(`Plugin bundleado de Engram no encontrado: ${pluginSource}`);
1133
1101
  }
1102
+ mkdirSync4(pluginsDir, { recursive: true });
1103
+ copyFileSync3(pluginSource, join7(pluginsDir, "engram.ts"));
1134
1104
  }
1135
- function findProjectRoot(startDir = process.cwd()) {
1136
- let current = resolve(startDir);
1137
- while (true) {
1138
- if (existsSync(join(current, ".opencode")) || existsSync(join(current, ".git"))) {
1139
- return current;
1105
+ function buildEngramDownloadUrl(tag, platform = process.platform, arch = process.arch) {
1106
+ const target = getEngramReleaseTarget(platform, arch);
1107
+ if (!target)
1108
+ return null;
1109
+ const extension = platform === "win32" ? "zip" : "tar.gz";
1110
+ return `https://github.com/Gentleman-Programming/engram/releases/download/${tag}/engram_${tag.replace(/^v/, "")}_${target.replace("-", "_")}.${extension}`;
1111
+ }
1112
+ async function installCodeGraph(toolsDir) {
1113
+ const location = resolveToolInstallLocation(toolsDir);
1114
+ const { projectRoot } = location;
1115
+ const cgToolDir = join7(location.toolsDir, "codegraph");
1116
+ if (!existsSync6(cgToolDir))
1117
+ mkdirSync4(cgToolDir, { recursive: true });
1118
+ const target = detectPlatformTarget();
1119
+ if (!target) {
1120
+ return {
1121
+ success: false,
1122
+ message: `Plataforma no soportada para descarga local: ${process.platform}/${process.arch}. Instalá CodeGraph manualmente.`
1123
+ };
1124
+ }
1125
+ let localBin = findToolBinary(cgToolDir, "codegraph");
1126
+ let archivePromotion = null;
1127
+ const failAfterExtraction = (message) => {
1128
+ try {
1129
+ archivePromotion?.rollback();
1130
+ } catch {}
1131
+ return { success: false, message };
1132
+ };
1133
+ if (localBin) {
1134
+ try {
1135
+ runTool(localBin, ["--version"], projectRoot, 1e4);
1136
+ } catch {
1137
+ try {
1138
+ rmSync4(cgToolDir, { recursive: true, force: true });
1139
+ } catch {}
1140
+ localBin = null;
1141
+ }
1142
+ }
1143
+ if (!localBin) {
1144
+ const tag = await fetchLatestReleaseTag("colbymchenry/codegraph");
1145
+ if (!tag) {
1146
+ return {
1147
+ success: false,
1148
+ message: "No se pudo obtener la última versión de CodeGraph desde GitHub."
1149
+ };
1150
+ }
1151
+ const ext = process.platform === "win32" ? "zip" : "tar.gz";
1152
+ const url = `https://github.com/colbymchenry/codegraph/releases/download/${tag}/codegraph-${target}.${ext}`;
1153
+ try {
1154
+ archivePromotion = await downloadAndExtractWithRetry(url, cgToolDir, 1, 180000, 2);
1155
+ } catch (e2) {
1156
+ return {
1157
+ success: false,
1158
+ message: `Error descargando CodeGraph ${tag}: ${e2.message}`
1159
+ };
1160
+ }
1161
+ localBin = findToolBinary(cgToolDir, "codegraph");
1162
+ if (!localBin) {
1163
+ return failAfterExtraction(`Descarga de CodeGraph ${tag} completada pero no se encontró el binario en ${join7(cgToolDir, "bin")}.`);
1164
+ }
1165
+ if (process.platform !== "win32") {
1166
+ try {
1167
+ chmodSync(localBin, 493);
1168
+ } catch {}
1140
1169
  }
1141
- const parent = dirname(current);
1142
- if (parent === current)
1143
- return resolve(startDir);
1144
- current = parent;
1145
1170
  }
1146
- }
1147
- function ensureOpenCodePaths(opencodeDir) {
1148
- const paths = {
1149
- root: opencodeDir,
1150
- agents: join(opencodeDir, "agents"),
1151
- commands: join(opencodeDir, "commands"),
1152
- plugins: join(opencodeDir, "plugins"),
1153
- skills: join(opencodeDir, "skills"),
1154
- mcp: join(opencodeDir, "mcp"),
1155
- tools: join(opencodeDir, "tools")
1156
- };
1157
- for (const dir of [paths.root, paths.agents, paths.commands, paths.plugins, paths.skills, paths.mcp, paths.tools]) {
1158
- if (!existsSync(dir))
1159
- mkdirSync(dir, { recursive: true });
1171
+ try {
1172
+ runTool(localBin, ["--version"], projectRoot, 1e4);
1173
+ } catch (error) {
1174
+ return failAfterExtraction(`CodeGraph fue extraído pero no se puede ejecutar: ${error.message}`);
1160
1175
  }
1161
- return paths;
1162
- }
1163
- function ensureToolDirs(toolsDir, toolNames) {
1164
- for (const name of toolNames) {
1165
- const dir = join(toolsDir, name);
1166
- if (!existsSync(dir))
1167
- mkdirSync(dir, { recursive: true });
1176
+ let indexWarning = null;
1177
+ try {
1178
+ runTool(localBin, ["init", "-i"], projectRoot, 120000);
1179
+ } catch (error) {
1180
+ indexWarning = `El índice no se pudo inicializar todavía: ${error.message}`;
1168
1181
  }
1182
+ try {
1183
+ configureLocalTool(projectRoot, "codegraph", buildLocalMcpCommand(localBin, ["serve", "--mcp"]));
1184
+ } catch (error) {
1185
+ return failAfterExtraction(`CodeGraph fue instalado pero no se pudo configurar el MCP: ${error.message}`);
1186
+ }
1187
+ archivePromotion?.commit();
1188
+ return {
1189
+ success: true,
1190
+ message: indexWarning ? `CodeGraph instalado y configurado para OpenCode. ${indexWarning}` : "CodeGraph instalado localmente y configurado para OpenCode"
1191
+ };
1169
1192
  }
1170
- function createOpenCodeDir(baseDir) {
1171
- return ensureOpenCodePaths(join(baseDir, ".opencode"));
1193
+ function setupOpenSpec(projectRoot = findProjectRoot()) {
1194
+ const useBun = isCommandAvailable("bun");
1195
+ try {
1196
+ const invocation = getCommandInvocation(useBun ? "bunx" : "npx", useBun ? ["openspec", "init", "--tools", "opencode", "--force"] : ["--yes", "openspec", "init", "--tools", "opencode", "--force"]);
1197
+ execFileSync3(invocation.command, invocation.args, {
1198
+ stdio: "pipe",
1199
+ timeout: 120000,
1200
+ cwd: projectRoot
1201
+ });
1202
+ return { success: true, message: "OpenSpec configurado para OpenCode" };
1203
+ } catch (e2) {
1204
+ return {
1205
+ success: false,
1206
+ message: `Error configurando OpenSpec: ${e2.message}`
1207
+ };
1208
+ }
1172
1209
  }
1173
- function copyDirRecursive(src, dest, skipGenerated = false) {
1174
- if (!existsSync(dest))
1175
- mkdirSync(dest, { recursive: true });
1176
- for (const entry of readdirSync(src)) {
1177
- if (skipGenerated && (entry === "node_modules" || entry === "package-lock.json"))
1178
- continue;
1179
- const srcPath = join(src, entry);
1180
- const destPath = join(dest, entry);
1181
- const stat = statSync(srcPath);
1182
- if (stat.isDirectory()) {
1183
- copyDirRecursive(srcPath, destPath, skipGenerated);
1184
- } else {
1185
- copyFileSync(srcPath, destPath);
1210
+ async function installEngram(toolsDir) {
1211
+ const location = resolveToolInstallLocation(toolsDir);
1212
+ const { projectRoot } = location;
1213
+ const engramToolDir = join7(location.toolsDir, "engram");
1214
+ const engramBinDir = join7(engramToolDir, "bin");
1215
+ if (!existsSync6(engramBinDir))
1216
+ mkdirSync4(engramBinDir, { recursive: true });
1217
+ const localBin = join7(engramBinDir, getExecutableName("engram"));
1218
+ let archivePromotion = null;
1219
+ const failAfterExtraction = (message) => {
1220
+ try {
1221
+ archivePromotion?.rollback();
1222
+ } catch {}
1223
+ return { success: false, message };
1224
+ };
1225
+ if (existsSync6(localBin)) {
1226
+ try {
1227
+ runTool(localBin, ["--version"], projectRoot, 1e4);
1228
+ } catch {
1229
+ try {
1230
+ unlinkSync3(localBin);
1231
+ } catch {}
1186
1232
  }
1187
1233
  }
1188
- }
1189
- function computeTreeHash(dir) {
1190
- const lines = [];
1191
- walkForHash(dir, dir, lines);
1192
- const combined = lines.sort().join(`
1193
- `);
1194
- return createHash2("sha256").update(combined, "utf-8").digest("hex");
1195
- }
1196
- function walkForHash(root, current, lines) {
1197
- for (const entry of readdirSync(current)) {
1198
- if (entry === "node_modules" || entry === "package-lock.json")
1199
- continue;
1200
- const full = join(current, entry);
1201
- const stat = statSync(full);
1202
- if (stat.isDirectory()) {
1203
- walkForHash(root, full, lines);
1204
- } else {
1205
- const rel = relative(root, full);
1206
- const content = readFileSync(full, "utf-8");
1207
- lines.push(`${rel}:${sha256(content)}`);
1234
+ if (!existsSync6(localBin)) {
1235
+ const globalBin = findExecutablePath("engram");
1236
+ const useGlobalBinary = globalBin && (process.platform !== "win32" || globalBin.toLowerCase().endsWith(".exe"));
1237
+ if (useGlobalBinary) {
1238
+ try {
1239
+ runTool(globalBin, ["--version"], projectRoot, 1e4);
1240
+ mkdirSync4(engramBinDir, { recursive: true });
1241
+ copyFileSync3(globalBin, localBin);
1242
+ } catch {
1243
+ try {
1244
+ unlinkSync3(localBin);
1245
+ } catch {}
1246
+ }
1208
1247
  }
1209
1248
  }
1210
- }
1211
- function isCommandAvailable(cmd) {
1212
- try {
1213
- if (process.platform === "win32") {
1214
- execSync(`where ${cmd} >nul 2>&1`);
1215
- } else {
1216
- execSync(`which ${cmd} >/dev/null 2>&1`);
1249
+ if (!existsSync6(localBin)) {
1250
+ const tag = await fetchLatestReleaseTag("Gentleman-Programming/engram");
1251
+ if (!tag) {
1252
+ return {
1253
+ success: false,
1254
+ message: "No se pudo obtener la última versión de Engram desde GitHub."
1255
+ };
1256
+ }
1257
+ const url = buildEngramDownloadUrl(tag);
1258
+ if (!url) {
1259
+ return {
1260
+ success: false,
1261
+ message: `Plataforma no soportada para descargar Engram: ${process.platform}/${process.arch}.`
1262
+ };
1263
+ }
1264
+ try {
1265
+ archivePromotion = await downloadAndExtractWithRetry(url, engramToolDir, 0, 120000, 2);
1266
+ } catch (e2) {
1267
+ return {
1268
+ success: false,
1269
+ message: `Error descargando Engram ${tag}: ${e2.message}`
1270
+ };
1271
+ }
1272
+ mkdirSync4(engramBinDir, { recursive: true });
1273
+ const found = findBinaryInDir(engramToolDir, "engram");
1274
+ if (!found) {
1275
+ return failAfterExtraction(`Descarga de Engram ${tag} completada pero no se encontró el binario en ${localBin}.`);
1276
+ }
1277
+ try {
1278
+ if (found !== localBin)
1279
+ copyFileSync3(found, localBin);
1280
+ } catch (error) {
1281
+ return failAfterExtraction(`Engram fue descargado pero no se pudo materializar el binario local: ${error.message}`);
1282
+ }
1283
+ if (process.platform !== "win32") {
1284
+ try {
1285
+ chmodSync(localBin, 493);
1286
+ } catch {}
1217
1287
  }
1218
- return true;
1219
- } catch {
1220
- return false;
1221
1288
  }
1222
- }
1223
- function findExecutablePath(cmd) {
1224
1289
  try {
1225
- const result = execSync(process.platform === "win32" ? `where ${cmd}` : `which ${cmd}`, { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
1226
- return result || null;
1227
- } catch {
1228
- return null;
1290
+ runTool(localBin, ["--version"], projectRoot, 1e4);
1291
+ copyEngramPlugin(projectRoot);
1292
+ configureLocalTool(projectRoot, "engram", buildLocalMcpCommand(localBin, ["mcp"]));
1293
+ } catch (error) {
1294
+ return failAfterExtraction(`Engram fue instalado pero no se pudo verificar o configurar: ${error.message}`);
1229
1295
  }
1296
+ archivePromotion?.commit();
1297
+ return { success: true, message: "Engram instalado localmente y configurado para OpenCode (MCP + plugin)" };
1230
1298
  }
1231
- function getBunInstallCommand() {
1232
- const platform = process.platform;
1233
- if (platform === "darwin" || platform === "linux") {
1234
- return {
1235
- command: "curl -fsSL https://bun.com/install | bash",
1236
- note: platform === "linux" ? "Requires 'unzip' package (sudo apt install unzip)" : undefined
1237
- };
1299
+ function setupContext7(toolsDir) {
1300
+ const location = resolveToolInstallLocation(toolsDir);
1301
+ const { projectRoot } = location;
1302
+ const ctx7ToolDir = join7(location.toolsDir, "context7");
1303
+ if (!existsSync6(ctx7ToolDir))
1304
+ mkdirSync4(ctx7ToolDir, { recursive: true });
1305
+ try {
1306
+ ensureMcpEntryAtProjectRoot(projectRoot, "context7", {
1307
+ type: "remote",
1308
+ url: "https://mcp.context7.com/mcp",
1309
+ enabled: true
1310
+ });
1311
+ } catch (error) {
1312
+ return { success: false, message: `No se pudo registrar Context7: ${error.message}` };
1238
1313
  }
1239
- if (platform === "win32") {
1314
+ const useBun = isCommandAvailable("bun");
1315
+ try {
1316
+ const invocation = getCommandInvocation(useBun ? "bunx" : "npx", useBun ? ["ctx7", "setup", "--opencode"] : ["--yes", "ctx7", "setup", "--opencode"]);
1317
+ execFileSync3(invocation.command, invocation.args, {
1318
+ stdio: "pipe",
1319
+ timeout: 60000,
1320
+ cwd: projectRoot
1321
+ });
1322
+ return { success: true, message: "Context7 configurado (MCP + skill instalado)" };
1323
+ } catch {
1240
1324
  return {
1241
- command: 'powershell -c "irm bun.sh/install.ps1|iex"',
1242
- note: "Requires Windows 10 v1809 or later"
1325
+ success: true,
1326
+ message: "Context7 MCP registrado (skill opcional no instalada — corrí `npx ctx7 setup --opencode` manualmente si la querés)"
1243
1327
  };
1244
1328
  }
1245
- return {
1246
- command: "npm install -g bun",
1247
- note: "Cross-platform fallback"
1248
- };
1249
1329
  }
1250
- function checkBunAvailability() {
1251
- const bunPath = findExecutablePath("bun");
1252
- if (bunPath) {
1253
- let version;
1254
- try {
1255
- version = execSync("bun --version", {
1256
- encoding: "utf-8",
1257
- stdio: ["pipe", "pipe", "pipe"]
1258
- }).trim();
1259
- } catch {}
1260
- return { available: true, path: bunPath, version };
1261
- }
1262
- const { command, note } = getBunInstallCommand();
1330
+ async function installStack(toolsDir) {
1331
+ const { projectRoot } = resolveToolInstallLocation(toolsDir);
1263
1332
  return {
1264
- available: false,
1265
- installCommand: command,
1266
- installNote: note
1333
+ codegraph: await installCodeGraph(toolsDir),
1334
+ openspec: setupOpenSpec(projectRoot),
1335
+ engram: await installEngram(toolsDir),
1336
+ context7: setupContext7(toolsDir),
1337
+ config: patchOpenCodeConfig(projectRoot)
1267
1338
  };
1268
1339
  }
1269
- function detectPlatformTarget() {
1270
- const platform = process.platform;
1271
- const arch = process.arch;
1272
- let os;
1273
- let cpu;
1274
- if (platform === "darwin")
1275
- os = "darwin";
1276
- else if (platform === "linux")
1277
- os = "linux";
1278
- else if (platform === "win32")
1279
- os = "win32";
1280
- else
1281
- return null;
1282
- if (arch === "arm64")
1283
- cpu = "arm64";
1284
- else if (arch === "x64")
1285
- cpu = "x64";
1286
- else
1287
- return null;
1288
- return `${os}-${cpu}`;
1340
+ function uninstallEngramConfig() {
1341
+ const projectRoot = findProjectRoot();
1342
+ const configPath = findOpenCodeConfig(projectRoot);
1343
+ if (!configPath) {
1344
+ return { success: false, message: "No se encontró opencode.json ni opencode.jsonc" };
1345
+ }
1346
+ const config = readOpenCodeConfig(configPath);
1347
+ if (!config) {
1348
+ return { success: false, message: `Error parseando ${configPath}` };
1349
+ }
1350
+ const mcp = config.mcp;
1351
+ if (mcp && "engram" in mcp) {
1352
+ delete mcp.engram;
1353
+ if (Object.keys(mcp).length === 0) {
1354
+ delete config.mcp;
1355
+ }
1356
+ writeOpenCodeConfig(configPath, config);
1357
+ return { success: true, message: "Config de Engram eliminada de opencode.json" };
1358
+ }
1359
+ return { success: true, message: "Engram no estaba configurado en este proyecto" };
1289
1360
  }
1290
- function downloadToFile(url, dest, timeoutMs = 180000) {
1291
- return new Promise((resolve2, reject) => {
1292
- const file = createWriteStream(dest);
1293
- file.on("finish", () => resolve2());
1294
- file.on("error", (err) => reject(err));
1295
- const controller = new AbortController;
1296
- const timer = setTimeout(() => controller.abort(), timeoutMs);
1297
- fetch(url, { signal: controller.signal, headers: { "User-Agent": USER_AGENT } }).then((res) => {
1298
- if (!res.ok || !res.body) {
1299
- reject(new Error(`HTTP ${res.status} ${res.statusText} descargando ${url}`));
1300
- return;
1301
- }
1302
- const writable = new WritableStream({
1303
- write(chunk) {
1304
- return new Promise((ok, fail) => file.write(Buffer.from(chunk), (err) => err ? fail(err) : ok()));
1305
- },
1306
- close() {
1307
- file.end();
1361
+ function uninstallStackConfig(paths) {
1362
+ const projectRoot = dirname5(paths.root);
1363
+ const removed = [];
1364
+ const configPath = findOpenCodeConfig(projectRoot);
1365
+ if (configPath) {
1366
+ const config = readOpenCodeConfig(configPath);
1367
+ if (config) {
1368
+ const mcp = config.mcp;
1369
+ let changed = false;
1370
+ if (mcp) {
1371
+ for (const name of ["codegraph", "context7", "engram"]) {
1372
+ if (name in mcp) {
1373
+ delete mcp[name];
1374
+ removed.push(`mcp.${name}`);
1375
+ changed = true;
1376
+ }
1308
1377
  }
1309
- });
1310
- return res.body.pipeTo(writable);
1311
- }).then(() => {
1312
- clearTimeout(timer);
1313
- }).catch((err) => {
1314
- clearTimeout(timer);
1315
- file.destroy();
1316
- try {
1317
- unlinkSync(dest);
1318
- } catch {}
1319
- reject(err);
1320
- });
1321
- });
1322
- }
1323
- async function downloadAndExtract(url, destDir, stripComponents = 1, timeoutMs = 180000) {
1324
- const tmp = join(destDir, `.download-${Date.now()}`);
1325
- if (!existsSync(tmp))
1326
- mkdirSync(tmp, { recursive: true });
1327
- const archivePath = join(tmp, url.endsWith(".zip") ? "archive.zip" : "archive.tar.gz");
1328
- try {
1329
- await downloadToFile(url, archivePath, timeoutMs);
1330
- if (!existsSync(destDir))
1331
- mkdirSync(destDir, { recursive: true });
1332
- if (process.platform === "win32" && url.endsWith(".zip")) {
1333
- execSync(`powershell -NoProfile -Command "Expand-Archive -Path '${archivePath}' -DestinationPath '${destDir}' -Force"`, { stdio: "pipe", timeout: 60000 });
1334
- } else {
1335
- const stripArg = stripComponents > 0 ? `--strip-components=${stripComponents}` : "";
1336
- execSync(`tar -xzf "${archivePath}" -C "${destDir}" ${stripArg}`, {
1337
- stdio: "pipe",
1338
- timeout: 60000
1339
- });
1378
+ if (Object.keys(mcp).length === 0) {
1379
+ delete config.mcp;
1380
+ changed = true;
1381
+ }
1382
+ }
1383
+ if (changed) {
1384
+ writeOpenCodeConfig(configPath, config);
1385
+ }
1340
1386
  }
1341
- } finally {
1387
+ }
1388
+ const codegraphDir = join7(projectRoot, ".codegraph");
1389
+ if (existsSync6(codegraphDir)) {
1342
1390
  try {
1343
- rmSync(tmp, { recursive: true, force: true });
1391
+ rmSync4(codegraphDir, { recursive: true, force: true });
1392
+ removed.push(".codegraph/");
1344
1393
  } catch {}
1345
1394
  }
1346
- }
1347
- async function downloadAndExtractWithRetry(url, destDir, stripComponents = 1, timeoutMs = 180000, maxRetries = 2) {
1348
- let lastError = null;
1349
- for (let attempt = 0;attempt <= maxRetries; attempt++) {
1395
+ if (existsSync6(paths.tools)) {
1350
1396
  try {
1351
- await downloadAndExtract(url, destDir, stripComponents, timeoutMs);
1352
- return;
1353
- } catch (err) {
1354
- lastError = err;
1355
- if (attempt < maxRetries) {
1356
- const delay = 1000 * Math.pow(2, attempt);
1357
- console.error(`[download] Intento ${attempt + 1} falló: ${lastError.message}. Reintentando en ${delay}ms...`);
1358
- await new Promise((r2) => setTimeout(r2, delay));
1359
- }
1360
- }
1397
+ rmSync4(paths.tools, { recursive: true, force: true });
1398
+ removed.push(".opencode/tools/");
1399
+ } catch {}
1361
1400
  }
1362
- throw lastError;
1401
+ if (removed.length === 0) {
1402
+ return { success: true, message: "No había configuración del stack para remover" };
1403
+ }
1404
+ return {
1405
+ success: true,
1406
+ message: `Removido: ${removed.join(", ")}. Los binarios globales (codegraph, engram) no se tocaron.`
1407
+ };
1363
1408
  }
1364
- function findBinaryInDir(dir, name) {
1365
- const entries = readdirSync(dir);
1366
- for (const entry of entries) {
1367
- const full = join(dir, entry);
1368
- const stat = statSync(full);
1369
- if (stat.isDirectory()) {
1370
- const found = findBinaryInDir(full, name);
1371
- if (found)
1372
- return found;
1373
- } else if (entry === name || entry === name + ".exe") {
1374
- return full;
1409
+ function verifyMcpServers(projectRoot) {
1410
+ const opencodeDir = findOpenCodeDir(projectRoot);
1411
+ const mcpBase = opencodeDir ? join7(opencodeDir, "mcp") : join7(projectRoot, ".opencode", "mcp");
1412
+ const controllerPath = join7(mcpBase, "ostacky-controller", "index.js");
1413
+ const openspecPath = join7(mcpBase, "openspec", "index.js");
1414
+ const result = {
1415
+ ostackyController: {
1416
+ exists: existsSync6(controllerPath),
1417
+ path: controllerPath
1418
+ },
1419
+ openspec: {
1420
+ exists: existsSync6(openspecPath),
1421
+ path: openspecPath
1375
1422
  }
1423
+ };
1424
+ if (!result.ostackyController.exists) {
1425
+ result.ostackyController.error = "ostacky-controller MCP server not found";
1376
1426
  }
1377
- return null;
1427
+ if (!result.openspec.exists) {
1428
+ result.openspec.error = "openspec MCP server not found";
1429
+ }
1430
+ return result;
1378
1431
  }
1379
- var USER_AGENT = "ostacky-installer";
1380
- var init_fs = __esm(() => {
1381
- init_security();
1382
- });
1383
-
1384
- // manifest.json
1385
- var manifest_default;
1386
- var init_manifest = __esm(() => {
1387
- manifest_default = {
1388
- version: "0.6.1",
1389
- repo: "JaimeHoracio/Ostacky",
1390
- tag: "v0.6.1",
1391
- agents: [
1392
- {
1393
- name: "ostacky",
1394
- file: "assets/agents/ostacky.md",
1395
- description: "Orquestador con recuperación automática (nunca se congela), ruteo por nivel de impacto, controller MCP con SDK oficial, edición segura con fallback inline, y delegación en OpenSpec + Superpowers",
1396
- version: "0.6.1",
1397
- sha256: "206963fd98b0af4580338407d1df11c30ecd0c18b984f73eb4b624555c263f55"
1398
- }
1399
- ],
1400
- commands: [
1401
- {
1402
- name: "install-stack",
1403
- file: "assets/commands/install-stack.md",
1404
- description: "Instala el stack tecnológico del proyecto (CodeGraph, skills, OpenSpec, Engram, Context7, controller MCP con SDK oficial)",
1405
- version: "0.6.1",
1406
- sha256: "6741c7e08a04a56b1857b76eabf0b3207911a255639ffc3ef329fb18229d8984"
1407
- },
1408
- {
1409
- name: "opsx-sync",
1410
- file: "assets/commands/opsx-sync.md",
1411
- description: "Sincroniza delta specs del change activo sin inicializar CodeGraph si ya existe índice",
1412
- version: "0.6.1",
1413
- sha256: "ed9948f1910743b672e1dfad496bc96972a224a98b063232be39290d43068c50"
1414
- }
1415
- ],
1416
- mcpServers: [
1417
- {
1418
- name: "ostacky-controller",
1419
- file: "assets/mcp/ostacky-controller/",
1420
- description: "Máquina de estados persistida con @modelcontextprotocol/server SDK. 20 tools: start_request → discovery → route → execution → sync → done + validate_edit + complete_task + ping + proceed_to_route + abandon integrado",
1421
- version: "0.6.1",
1422
- sha256: "63c9dfe7af992dc21e097a6c9902c539827cbe563165731bc997f6b776cc9aaf"
1423
- },
1424
- {
1425
- name: "openspec",
1426
- file: "assets/mcp/openspec/",
1427
- description: "MCP server local para OpenSpec - proposal, apply, archive, sync de cambios",
1428
- version: "0.6.1",
1429
- sha256: "fa4be28bfc1e75db8f1a037e2580f04a60066c80e8e5934e90e1041020d04609"
1430
- }
1431
- ],
1432
- skills: [
1433
- {
1434
- name: "brainstorming",
1435
- file: "assets/skills/brainstorming/SKILL.md",
1436
- description: "Skill unificado de pensamiento con dos modos: creative-design (producción de diseño → transición a writing-plans o openspec-propose) y open-exploration (exploración libre)",
1437
- version: "0.6.1",
1438
- sha256: "d1051ded927d57dcf72c33fa0d6116c7d0103ef36f5a7f9e22f7b3da78f9c74e"
1439
- },
1440
- {
1441
- name: "execution-mode-evaluation",
1442
- file: "assets/skills/execution-mode-evaluation/SKILL.md",
1443
- description: "Skill de análisis de modo de ejecución — output reconciliado con controller snapshot contract (recommendation field)",
1444
- version: "0.6.1",
1445
- sha256: "5c37f6f4132378f863c99102bbde8bab478160ced82a2ea1025f958275d8e881"
1446
- },
1447
- {
1448
- name: "writing-plans",
1449
- file: "assets/skills/writing-plans/SKILL.md",
1450
- description: "Skill de planificación de implementación (Superpowers) — execution handoff removido, Ostacky decide modo de ejecución",
1451
- version: "0.6.1",
1452
- sha256: "e681af5e607e7ae4b6a1c0760a4f1d1d292a028d2b6989df3afb9be8dcc81c61"
1453
- },
1454
- {
1455
- name: "tdd",
1456
- file: "assets/skills/tdd/SKILL.md",
1457
- description: "Skill de test-driven development (Superpowers)",
1458
- version: "0.6.1",
1459
- sha256: "9f5a25e61e049d473a854a5401cec947329e830aa902db7c31f91a160ac19890"
1460
- },
1461
- {
1462
- name: "subagent-driven-development",
1463
- file: "assets/skills/subagent-driven-development/SKILL.md",
1464
- description: "Skill de ejecución con subagentes (Superpowers) — ejecuta solo después de confirmación del coordinador Ostacky",
1465
- version: "0.6.1",
1466
- sha256: "65d87f2b3ae1da5d08b6760938ab7009e0e226182ec1d88d322a230754ac9d8e"
1467
- },
1468
- {
1469
- name: "dispatching-parallel-agents",
1470
- file: "assets/skills/dispatching-parallel-agents/SKILL.md",
1471
- description: "Skill de dispatch paralelo de agentes (Superpowers)",
1472
- version: "0.6.1",
1473
- sha256: "2d93480e4b9c0f516861a765977ae08b6e02dc113dc456068ef8026bcb950fcb"
1474
- },
1475
- {
1476
- name: "review",
1477
- file: "assets/skills/review/SKILL.md",
1478
- description: "Skill de revisión de código (Superpowers)",
1479
- version: "0.6.1",
1480
- sha256: "14831d9ef3746ef6e2e6047c868fe7aa296d01f0644227ce776fe99436357b1a"
1481
- },
1482
- {
1483
- name: "receiving-code-review",
1484
- file: "assets/skills/receiving-code-review/SKILL.md",
1485
- description: "Skill de recibir y procesar feedback de code review",
1486
- version: "0.6.1",
1487
- sha256: "0a5780e8a41539d15428114b7c46f36670acc16aba0db3348d36be1175433872"
1488
- },
1489
- {
1490
- name: "openspec-propose",
1491
- file: "assets/skills/openspec-propose/SKILL.md",
1492
- description: "Skill de generación de proposal (OpenSpec)",
1493
- version: "0.6.1",
1494
- sha256: "c50d478fd96ec5a60080012d5d87a09b54787884b4b0fa7d8631e7bee6c8c80d"
1495
- },
1496
- {
1497
- name: "openspec-apply-change",
1498
- file: "assets/skills/openspec-apply-change/SKILL.md",
1499
- description: "Skill de aplicación de change (OpenSpec)",
1500
- version: "0.6.1",
1501
- sha256: "723a492f2ef2df3337e8e841ae84f4f5d0f8621e534c8ea76540ee3a796ff527"
1502
- },
1503
- {
1504
- name: "openspec-archive-change",
1505
- file: "assets/skills/openspec-archive-change/SKILL.md",
1506
- description: "Skill de archivo de change (OpenSpec)",
1507
- version: "0.6.1",
1508
- sha256: "dc2422d0ff9a54e3ed9b016df2bad0dfa6cca9adaee02bb4563ce7525cc56f40"
1509
- },
1510
- {
1511
- name: "openspec-explore",
1512
- file: "assets/skills/openspec-explore/SKILL.md",
1513
- description: "Modo explore para OpenSpec — thinking partner para explorar ideas, investigar problemas y clarificar requisitos antes/durante un cambio",
1514
- version: "0.6.1",
1515
- sha256: "6e162c0b38dedd2ee70d0be9179af1a9716e78ac786511d5b49ebeb0fffc14a0"
1516
- },
1517
- {
1518
- name: "using-git-worktrees",
1519
- file: "assets/skills/using-git-worktrees/SKILL.md",
1520
- description: "Skill de uso de git worktrees para aislamiento de trabajo",
1521
- version: "0.6.1",
1522
- sha256: "3829b79c1d36b1bc9d148153b07f66265599a19494f648731273e3e6d1a0d65c"
1523
- },
1524
- {
1525
- name: "using-superpowers",
1526
- file: "assets/skills/using-superpowers/SKILL.md",
1527
- description: "Skill de orquestación de Superpowers skills",
1528
- version: "0.6.1",
1529
- sha256: "d0153c2bdac88c5a409d439d137b8f04fecda005cc7722f1ca83b2211bfda115"
1530
- },
1531
- {
1532
- name: "writing-skills",
1533
- file: "assets/skills/writing-skills/SKILL.md",
1534
- description: "Skill de creación y edición de skills",
1535
- version: "0.6.1",
1536
- sha256: "371da06aad8a546389785140248698b6401730f34c2ab00b4b9304e5a51e1eb4"
1537
- },
1538
- {
1539
- name: "graceful-degradation",
1540
- file: "assets/skills/graceful-degradation/SKILL.md",
1541
- description: "Skill de degradación graceful cuando múltiples tools están indisponibles",
1542
- version: "0.6.1",
1543
- sha256: "92ea3381b5610d9041797868a5887fb358d185d80ebb753bdae3f9f9abb4d790"
1544
- }
1545
- ]
1546
- };
1432
+ var init_stack = __esm(() => {
1433
+ init_fs();
1434
+ init_config();
1435
+ init_github();
1547
1436
  });
1548
-
1549
- // src/cache.ts
1550
- import { existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
1551
- import { join as join2, dirname as dirname2 } from "path";
1552
- function getCacheRoot(projectRoot) {
1553
- return join2(projectRoot, ".opencode", "cache");
1554
- }
1555
- function cacheKey(projectRoot, repo, tag, filePath) {
1556
- const repoSlug = repo.replace("/", "__");
1557
- return join2(getCacheRoot(projectRoot), repoSlug, tag, filePath);
1558
- }
1559
- function getCached(projectRoot, repo, tag, filePath, expectedHash) {
1560
- const cachePath = cacheKey(projectRoot, repo, tag, filePath);
1561
- if (!existsSync2(cachePath))
1562
- return null;
1563
- try {
1564
- const content = readFileSync2(cachePath, "utf-8");
1565
- if (expectedHash && sha256(content) !== expectedHash)
1566
- return null;
1567
- return content;
1568
- } catch {
1569
- return null;
1437
+ // package.json
1438
+ var package_default = {
1439
+ name: "ostacky",
1440
+ version: "0.6.2",
1441
+ description: "Instalador interactivo de agentes y comandos para OpenCode",
1442
+ type: "module",
1443
+ bin: {
1444
+ ostacky: "./dist/cli.js"
1445
+ },
1446
+ scripts: {
1447
+ prebuild: "bun run scripts/sync-version.ts",
1448
+ dev: "bun run src/cli.ts",
1449
+ build: "bun build src/cli.ts --target=node --format=esm --outfile dist/cli.js && bun scripts/add-shebang.ts",
1450
+ start: "node dist/cli.js",
1451
+ test: "bun test",
1452
+ "check:skills": "bun run scripts/check-skill-sync.ts",
1453
+ "check:skills:fix": "bun run scripts/check-skill-sync.ts --fix",
1454
+ "hash:check": "bun run scripts/update-manifest-hashes.ts --check",
1455
+ "hash:update": "bun run scripts/update-manifest-hashes.ts",
1456
+ prepublishOnly: "bun run build"
1457
+ },
1458
+ files: [
1459
+ "dist/",
1460
+ "assets/",
1461
+ "manifest.json",
1462
+ "LICENSE"
1463
+ ],
1464
+ keywords: [
1465
+ "opencode",
1466
+ "installer",
1467
+ "cli",
1468
+ "agent"
1469
+ ],
1470
+ license: "MIT",
1471
+ dependencies: {
1472
+ "@clack/prompts": "^0.9.0"
1473
+ },
1474
+ devDependencies: {
1475
+ "@types/bun": "latest",
1476
+ typescript: "^5.0.0"
1477
+ },
1478
+ publishConfig: {
1479
+ access: "public"
1480
+ },
1481
+ engines: {
1482
+ node: ">=20.0.0"
1570
1483
  }
1571
- }
1572
- function putCache(projectRoot, repo, tag, filePath, content) {
1573
- const cachePath = cacheKey(projectRoot, repo, tag, filePath);
1574
- const dir = dirname2(cachePath);
1575
- if (!existsSync2(dir))
1576
- mkdirSync2(dir, { recursive: true });
1577
- writeFileSync2(cachePath, content, "utf-8");
1578
- }
1579
- var init_cache = __esm(() => {
1580
- init_security();
1484
+ };
1485
+
1486
+ // node_modules/@clack/prompts/dist/index.mjs
1487
+ var exports_dist = {};
1488
+ __export(exports_dist, {
1489
+ updateSettings: () => hD,
1490
+ text: () => ue,
1491
+ tasks: () => xe,
1492
+ spinner: () => L2,
1493
+ selectKey: () => he,
1494
+ select: () => de,
1495
+ password: () => $e,
1496
+ outro: () => fe,
1497
+ note: () => ye,
1498
+ multiselect: () => pe,
1499
+ log: () => v2,
1500
+ isCancel: () => BD,
1501
+ intro: () => we,
1502
+ groupMultiselect: () => ge,
1503
+ group: () => be,
1504
+ confirm: () => me,
1505
+ cancel: () => ve
1581
1506
  });
1507
+ import { stripVTControlCharacters as T2 } from "node:util";
1582
1508
 
1583
- // src/github.ts
1584
- import { fileURLToPath } from "url";
1585
- import { dirname as dirname3, join as join3 } from "path";
1586
- function getBundledSkillPath(name) {
1587
- validateFilePath(name);
1588
- return join3(BUNDLED_SKILLS_DIR, name);
1509
+ // node_modules/@clack/core/dist/index.mjs
1510
+ var import_sisteransi = __toESM(require_src(), 1);
1511
+ var import_picocolors = __toESM(require_picocolors(), 1);
1512
+ import { stdin as $, stdout as j } from "node:process";
1513
+ import * as f from "node:readline";
1514
+ import M from "node:readline";
1515
+ import { WriteStream as U } from "node:tty";
1516
+ function J({ onlyFirst: t = false } = {}) {
1517
+ const F = ["[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]+)*|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?(?:\\u0007|\\u001B\\u005C|\\u009C))", "(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-nq-uy=><~]))"].join("|");
1518
+ return new RegExp(F, t ? undefined : "g");
1589
1519
  }
1590
- function getBundledMcpPath(name) {
1591
- validateFilePath(name);
1592
- return join3(BUNDLED_MCP_DIR, name);
1520
+ var Q = J();
1521
+ function T(t) {
1522
+ if (typeof t != "string")
1523
+ throw new TypeError(`Expected a \`string\`, got \`${typeof t}\``);
1524
+ return t.replace(Q, "");
1593
1525
  }
1594
- function getRawUrl(repo, tag, path) {
1595
- return `${GITHUB_RAW}/${repo}/${tag}/${path}`;
1526
+ function O(t) {
1527
+ return t && t.__esModule && Object.prototype.hasOwnProperty.call(t, "default") ? t.default : t;
1596
1528
  }
1597
- async function fetchLatestReleaseTag(repo) {
1598
- try {
1599
- const res = await fetch(`https://api.github.com/repos/${repo}/releases/latest`, {
1600
- signal: AbortSignal.timeout(5000),
1601
- headers: { "User-Agent": USER_AGENT }
1602
- });
1603
- if (res.ok) {
1604
- const data = await res.json();
1605
- return data.tag_name ?? null;
1529
+ var P = { exports: {} };
1530
+ (function(t) {
1531
+ var u = {};
1532
+ t.exports = u, u.eastAsianWidth = function(e) {
1533
+ var s = e.charCodeAt(0), i = e.length == 2 ? e.charCodeAt(1) : 0, D = s;
1534
+ return 55296 <= s && s <= 56319 && 56320 <= i && i <= 57343 && (s &= 1023, i &= 1023, D = s << 10 | i, D += 65536), D == 12288 || 65281 <= D && D <= 65376 || 65504 <= D && D <= 65510 ? "F" : D == 8361 || 65377 <= D && D <= 65470 || 65474 <= D && D <= 65479 || 65482 <= D && D <= 65487 || 65490 <= D && D <= 65495 || 65498 <= D && D <= 65500 || 65512 <= D && D <= 65518 ? "H" : 4352 <= D && D <= 4447 || 4515 <= D && D <= 4519 || 4602 <= D && D <= 4607 || 9001 <= D && D <= 9002 || 11904 <= D && D <= 11929 || 11931 <= D && D <= 12019 || 12032 <= D && D <= 12245 || 12272 <= D && D <= 12283 || 12289 <= D && D <= 12350 || 12353 <= D && D <= 12438 || 12441 <= D && D <= 12543 || 12549 <= D && D <= 12589 || 12593 <= D && D <= 12686 || 12688 <= D && D <= 12730 || 12736 <= D && D <= 12771 || 12784 <= D && D <= 12830 || 12832 <= D && D <= 12871 || 12880 <= D && D <= 13054 || 13056 <= D && D <= 19903 || 19968 <= D && D <= 42124 || 42128 <= D && D <= 42182 || 43360 <= D && D <= 43388 || 44032 <= D && D <= 55203 || 55216 <= D && D <= 55238 || 55243 <= D && D <= 55291 || 63744 <= D && D <= 64255 || 65040 <= D && D <= 65049 || 65072 <= D && D <= 65106 || 65108 <= D && D <= 65126 || 65128 <= D && D <= 65131 || 110592 <= D && D <= 110593 || 127488 <= D && D <= 127490 || 127504 <= D && D <= 127546 || 127552 <= D && D <= 127560 || 127568 <= D && D <= 127569 || 131072 <= D && D <= 194367 || 177984 <= D && D <= 196605 || 196608 <= D && D <= 262141 ? "W" : 32 <= D && D <= 126 || 162 <= D && D <= 163 || 165 <= D && D <= 166 || D == 172 || D == 175 || 10214 <= D && D <= 10221 || 10629 <= D && D <= 10630 ? "Na" : D == 161 || D == 164 || 167 <= D && D <= 168 || D == 170 || 173 <= D && D <= 174 || 176 <= D && D <= 180 || 182 <= D && D <= 186 || 188 <= D && D <= 191 || D == 198 || D == 208 || 215 <= D && D <= 216 || 222 <= D && D <= 225 || D == 230 || 232 <= D && D <= 234 || 236 <= D && D <= 237 || D == 240 || 242 <= D && D <= 243 || 247 <= D && D <= 250 || D == 252 || D == 254 || D == 257 || D == 273 || D == 275 || D == 283 || 294 <= D && D <= 295 || D == 299 || 305 <= D && D <= 307 || D == 312 || 319 <= D && D <= 322 || D == 324 || 328 <= D && D <= 331 || D == 333 || 338 <= D && D <= 339 || 358 <= D && D <= 359 || D == 363 || D == 462 || D == 464 || D == 466 || D == 468 || D == 470 || D == 472 || D == 474 || D == 476 || D == 593 || D == 609 || D == 708 || D == 711 || 713 <= D && D <= 715 || D == 717 || D == 720 || 728 <= D && D <= 731 || D == 733 || D == 735 || 768 <= D && D <= 879 || 913 <= D && D <= 929 || 931 <= D && D <= 937 || 945 <= D && D <= 961 || 963 <= D && D <= 969 || D == 1025 || 1040 <= D && D <= 1103 || D == 1105 || D == 8208 || 8211 <= D && D <= 8214 || 8216 <= D && D <= 8217 || 8220 <= D && D <= 8221 || 8224 <= D && D <= 8226 || 8228 <= D && D <= 8231 || D == 8240 || 8242 <= D && D <= 8243 || D == 8245 || D == 8251 || D == 8254 || D == 8308 || D == 8319 || 8321 <= D && D <= 8324 || D == 8364 || D == 8451 || D == 8453 || D == 8457 || D == 8467 || D == 8470 || 8481 <= D && D <= 8482 || D == 8486 || D == 8491 || 8531 <= D && D <= 8532 || 8539 <= D && D <= 8542 || 8544 <= D && D <= 8555 || 8560 <= D && D <= 8569 || D == 8585 || 8592 <= D && D <= 8601 || 8632 <= D && D <= 8633 || D == 8658 || D == 8660 || D == 8679 || D == 8704 || 8706 <= D && D <= 8707 || 8711 <= D && D <= 8712 || D == 8715 || D == 8719 || D == 8721 || D == 8725 || D == 8730 || 8733 <= D && D <= 8736 || D == 8739 || D == 8741 || 8743 <= D && D <= 8748 || D == 8750 || 8756 <= D && D <= 8759 || 8764 <= D && D <= 8765 || D == 8776 || D == 8780 || D == 8786 || 8800 <= D && D <= 8801 || 8804 <= D && D <= 8807 || 8810 <= D && D <= 8811 || 8814 <= D && D <= 8815 || 8834 <= D && D <= 8835 || 8838 <= D && D <= 8839 || D == 8853 || D == 8857 || D == 8869 || D == 8895 || D == 8978 || 9312 <= D && D <= 9449 || 9451 <= D && D <= 9547 || 9552 <= D && D <= 9587 || 9600 <= D && D <= 9615 || 9618 <= D && D <= 9621 || 9632 <= D && D <= 9633 || 9635 <= D && D <= 9641 || 9650 <= D && D <= 9651 || 9654 <= D && D <= 9655 || 9660 <= D && D <= 9661 || 9664 <= D && D <= 9665 || 9670 <= D && D <= 9672 || D == 9675 || 9678 <= D && D <= 9681 || 9698 <= D && D <= 9701 || D == 9711 || 9733 <= D && D <= 9734 || D == 9737 || 9742 <= D && D <= 9743 || 9748 <= D && D <= 9749 || D == 9756 || D == 9758 || D == 9792 || D == 9794 || 9824 <= D && D <= 9825 || 9827 <= D && D <= 9829 || 9831 <= D && D <= 9834 || 9836 <= D && D <= 9837 || D == 9839 || 9886 <= D && D <= 9887 || 9918 <= D && D <= 9919 || 9924 <= D && D <= 9933 || 9935 <= D && D <= 9953 || D == 9955 || 9960 <= D && D <= 9983 || D == 10045 || D == 10071 || 10102 <= D && D <= 10111 || 11093 <= D && D <= 11097 || 12872 <= D && D <= 12879 || 57344 <= D && D <= 63743 || 65024 <= D && D <= 65039 || D == 65533 || 127232 <= D && D <= 127242 || 127248 <= D && D <= 127277 || 127280 <= D && D <= 127337 || 127344 <= D && D <= 127386 || 917760 <= D && D <= 917999 || 983040 <= D && D <= 1048573 || 1048576 <= D && D <= 1114109 ? "A" : "N";
1535
+ }, u.characterLength = function(e) {
1536
+ var s = this.eastAsianWidth(e);
1537
+ return s == "F" || s == "W" || s == "A" ? 2 : 1;
1538
+ };
1539
+ function F(e) {
1540
+ return e.match(/[\uD800-\uDBFF][\uDC00-\uDFFF]|[^\uD800-\uDFFF]/g) || [];
1541
+ }
1542
+ u.length = function(e) {
1543
+ for (var s = F(e), i = 0, D = 0;D < s.length; D++)
1544
+ i = i + this.characterLength(s[D]);
1545
+ return i;
1546
+ }, u.slice = function(e, s, i) {
1547
+ textLen = u.length(e), s = s || 0, i = i || 1, s < 0 && (s = textLen + s), i < 0 && (i = textLen + i);
1548
+ for (var D = "", C = 0, o = F(e), E = 0;E < o.length; E++) {
1549
+ var a = o[E], n = u.length(a);
1550
+ if (C >= s - (n == 2 ? 1 : 0))
1551
+ if (C + n <= i)
1552
+ D += a;
1553
+ else
1554
+ break;
1555
+ C += n;
1556
+ }
1557
+ return D;
1558
+ };
1559
+ })(P);
1560
+ var X = P.exports;
1561
+ var DD = O(X);
1562
+ var uD = function() {
1563
+ return /\uD83C\uDFF4\uDB40\uDC67\uDB40\uDC62(?:\uDB40\uDC77\uDB40\uDC6C\uDB40\uDC73|\uDB40\uDC73\uDB40\uDC63\uDB40\uDC74|\uDB40\uDC65\uDB40\uDC6E\uDB40\uDC67)\uDB40\uDC7F|(?:\uD83E\uDDD1\uD83C\uDFFF\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFF\u200D\uD83E\uDD1D\u200D(?:\uD83D[\uDC68\uDC69]))(?:\uD83C[\uDFFB-\uDFFE])|(?:\uD83E\uDDD1\uD83C\uDFFE\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFE\u200D\uD83E\uDD1D\u200D(?:\uD83D[\uDC68\uDC69]))(?:\uD83C[\uDFFB-\uDFFD\uDFFF])|(?:\uD83E\uDDD1\uD83C\uDFFD\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFD\u200D\uD83E\uDD1D\u200D(?:\uD83D[\uDC68\uDC69]))(?:\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF])|(?:\uD83E\uDDD1\uD83C\uDFFC\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFC\u200D\uD83E\uDD1D\u200D(?:\uD83D[\uDC68\uDC69]))(?:\uD83C[\uDFFB\uDFFD-\uDFFF])|(?:\uD83E\uDDD1\uD83C\uDFFB\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFB\u200D\uD83E\uDD1D\u200D(?:\uD83D[\uDC68\uDC69]))(?:\uD83C[\uDFFC-\uDFFF])|\uD83D\uDC68(?:\uD83C\uDFFB(?:\u200D(?:\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFF])|\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFF]))|\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFC-\uDFFF])|[\u2695\u2696\u2708]\uFE0F|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD]))?|(?:\uD83C[\uDFFC-\uDFFF])\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFF])|\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFF]))|\u200D(?:\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83D\uDC68|(?:\uD83D[\uDC68\uDC69])\u200D(?:\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67]))|\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67])|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFF\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFE])|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFE\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFD\uDFFF])|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFD\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF])|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFC\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB\uDFFD-\uDFFF])|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|(?:\uD83C\uDFFF\u200D[\u2695\u2696\u2708]|\uD83C\uDFFE\u200D[\u2695\u2696\u2708]|\uD83C\uDFFD\u200D[\u2695\u2696\u2708]|\uD83C\uDFFC\u200D[\u2695\u2696\u2708]|\u200D[\u2695\u2696\u2708])\uFE0F|\u200D(?:(?:\uD83D[\uDC68\uDC69])\u200D(?:\uD83D[\uDC66\uDC67])|\uD83D[\uDC66\uDC67])|\uD83C\uDFFF|\uD83C\uDFFE|\uD83C\uDFFD|\uD83C\uDFFC)?|(?:\uD83D\uDC69(?:\uD83C\uDFFB\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D(?:\uD83D[\uDC68\uDC69])|\uD83D[\uDC68\uDC69])|(?:\uD83C[\uDFFC-\uDFFF])\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D(?:\uD83D[\uDC68\uDC69])|\uD83D[\uDC68\uDC69]))|\uD83E\uDDD1(?:\uD83C[\uDFFB-\uDFFF])\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1)(?:\uD83C[\uDFFB-\uDFFF])|\uD83D\uDC69\u200D\uD83D\uDC69\u200D(?:\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67]))|\uD83D\uDC69(?:\u200D(?:\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D(?:\uD83D[\uDC68\uDC69])|\uD83D[\uDC68\uDC69])|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFF\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFE\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFD\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFC\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFB\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD]))|\uD83E\uDDD1(?:\u200D(?:\uD83E\uDD1D\u200D\uD83E\uDDD1|\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFF\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFE\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFD\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFC\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFB\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD]))|\uD83D\uDC69\u200D\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC69\u200D\uD83D\uDC69\u200D(?:\uD83D[\uDC66\uDC67])|\uD83D\uDC69\u200D\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67])|(?:\uD83D\uDC41\uFE0F\u200D\uD83D\uDDE8|\uD83E\uDDD1(?:\uD83C\uDFFF\u200D[\u2695\u2696\u2708]|\uD83C\uDFFE\u200D[\u2695\u2696\u2708]|\uD83C\uDFFD\u200D[\u2695\u2696\u2708]|\uD83C\uDFFC\u200D[\u2695\u2696\u2708]|\uD83C\uDFFB\u200D[\u2695\u2696\u2708]|\u200D[\u2695\u2696\u2708])|\uD83D\uDC69(?:\uD83C\uDFFF\u200D[\u2695\u2696\u2708]|\uD83C\uDFFE\u200D[\u2695\u2696\u2708]|\uD83C\uDFFD\u200D[\u2695\u2696\u2708]|\uD83C\uDFFC\u200D[\u2695\u2696\u2708]|\uD83C\uDFFB\u200D[\u2695\u2696\u2708]|\u200D[\u2695\u2696\u2708])|\uD83D\uDE36\u200D\uD83C\uDF2B|\uD83C\uDFF3\uFE0F\u200D\u26A7|\uD83D\uDC3B\u200D\u2744|(?:(?:\uD83C[\uDFC3\uDFC4\uDFCA]|\uD83D[\uDC6E\uDC70\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6]|\uD83E[\uDD26\uDD35\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD-\uDDCF\uDDD4\uDDD6-\uDDDD])(?:\uD83C[\uDFFB-\uDFFF])|\uD83D\uDC6F|\uD83E[\uDD3C\uDDDE\uDDDF])\u200D[\u2640\u2642]|(?:\u26F9|\uD83C[\uDFCB\uDFCC]|\uD83D\uDD75)(?:\uFE0F|\uD83C[\uDFFB-\uDFFF])\u200D[\u2640\u2642]|\uD83C\uDFF4\u200D\u2620|(?:\uD83C[\uDFC3\uDFC4\uDFCA]|\uD83D[\uDC6E\uDC70\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6]|\uD83E[\uDD26\uDD35\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD-\uDDCF\uDDD4\uDDD6-\uDDDD])\u200D[\u2640\u2642]|[\xA9\xAE\u203C\u2049\u2122\u2139\u2194-\u2199\u21A9\u21AA\u2328\u23CF\u23ED-\u23EF\u23F1\u23F2\u23F8-\u23FA\u24C2\u25AA\u25AB\u25B6\u25C0\u25FB\u25FC\u2600-\u2604\u260E\u2611\u2618\u2620\u2622\u2623\u2626\u262A\u262E\u262F\u2638-\u263A\u2640\u2642\u265F\u2660\u2663\u2665\u2666\u2668\u267B\u267E\u2692\u2694-\u2697\u2699\u269B\u269C\u26A0\u26A7\u26B0\u26B1\u26C8\u26CF\u26D1\u26D3\u26E9\u26F0\u26F1\u26F4\u26F7\u26F8\u2702\u2708\u2709\u270F\u2712\u2714\u2716\u271D\u2721\u2733\u2734\u2744\u2747\u2763\u27A1\u2934\u2935\u2B05-\u2B07\u3030\u303D\u3297\u3299]|\uD83C[\uDD70\uDD71\uDD7E\uDD7F\uDE02\uDE37\uDF21\uDF24-\uDF2C\uDF36\uDF7D\uDF96\uDF97\uDF99-\uDF9B\uDF9E\uDF9F\uDFCD\uDFCE\uDFD4-\uDFDF\uDFF5\uDFF7]|\uD83D[\uDC3F\uDCFD\uDD49\uDD4A\uDD6F\uDD70\uDD73\uDD76-\uDD79\uDD87\uDD8A-\uDD8D\uDDA5\uDDA8\uDDB1\uDDB2\uDDBC\uDDC2-\uDDC4\uDDD1-\uDDD3\uDDDC-\uDDDE\uDDE1\uDDE3\uDDE8\uDDEF\uDDF3\uDDFA\uDECB\uDECD-\uDECF\uDEE0-\uDEE5\uDEE9\uDEF0\uDEF3])\uFE0F|\uD83C\uDFF3\uFE0F\u200D\uD83C\uDF08|\uD83D\uDC69\u200D\uD83D\uDC67|\uD83D\uDC69\u200D\uD83D\uDC66|\uD83D\uDE35\u200D\uD83D\uDCAB|\uD83D\uDE2E\u200D\uD83D\uDCA8|\uD83D\uDC15\u200D\uD83E\uDDBA|\uD83E\uDDD1(?:\uD83C\uDFFF|\uD83C\uDFFE|\uD83C\uDFFD|\uD83C\uDFFC|\uD83C\uDFFB)?|\uD83D\uDC69(?:\uD83C\uDFFF|\uD83C\uDFFE|\uD83C\uDFFD|\uD83C\uDFFC|\uD83C\uDFFB)?|\uD83C\uDDFD\uD83C\uDDF0|\uD83C\uDDF6\uD83C\uDDE6|\uD83C\uDDF4\uD83C\uDDF2|\uD83D\uDC08\u200D\u2B1B|\u2764\uFE0F\u200D(?:\uD83D\uDD25|\uD83E\uDE79)|\uD83D\uDC41\uFE0F|\uD83C\uDFF3\uFE0F|\uD83C\uDDFF(?:\uD83C[\uDDE6\uDDF2\uDDFC])|\uD83C\uDDFE(?:\uD83C[\uDDEA\uDDF9])|\uD83C\uDDFC(?:\uD83C[\uDDEB\uDDF8])|\uD83C\uDDFB(?:\uD83C[\uDDE6\uDDE8\uDDEA\uDDEC\uDDEE\uDDF3\uDDFA])|\uD83C\uDDFA(?:\uD83C[\uDDE6\uDDEC\uDDF2\uDDF3\uDDF8\uDDFE\uDDFF])|\uD83C\uDDF9(?:\uD83C[\uDDE6\uDDE8\uDDE9\uDDEB-\uDDED\uDDEF-\uDDF4\uDDF7\uDDF9\uDDFB\uDDFC\uDDFF])|\uD83C\uDDF8(?:\uD83C[\uDDE6-\uDDEA\uDDEC-\uDDF4\uDDF7-\uDDF9\uDDFB\uDDFD-\uDDFF])|\uD83C\uDDF7(?:\uD83C[\uDDEA\uDDF4\uDDF8\uDDFA\uDDFC])|\uD83C\uDDF5(?:\uD83C[\uDDE6\uDDEA-\uDDED\uDDF0-\uDDF3\uDDF7-\uDDF9\uDDFC\uDDFE])|\uD83C\uDDF3(?:\uD83C[\uDDE6\uDDE8\uDDEA-\uDDEC\uDDEE\uDDF1\uDDF4\uDDF5\uDDF7\uDDFA\uDDFF])|\uD83C\uDDF2(?:\uD83C[\uDDE6\uDDE8-\uDDED\uDDF0-\uDDFF])|\uD83C\uDDF1(?:\uD83C[\uDDE6-\uDDE8\uDDEE\uDDF0\uDDF7-\uDDFB\uDDFE])|\uD83C\uDDF0(?:\uD83C[\uDDEA\uDDEC-\uDDEE\uDDF2\uDDF3\uDDF5\uDDF7\uDDFC\uDDFE\uDDFF])|\uD83C\uDDEF(?:\uD83C[\uDDEA\uDDF2\uDDF4\uDDF5])|\uD83C\uDDEE(?:\uD83C[\uDDE8-\uDDEA\uDDF1-\uDDF4\uDDF6-\uDDF9])|\uD83C\uDDED(?:\uD83C[\uDDF0\uDDF2\uDDF3\uDDF7\uDDF9\uDDFA])|\uD83C\uDDEC(?:\uD83C[\uDDE6\uDDE7\uDDE9-\uDDEE\uDDF1-\uDDF3\uDDF5-\uDDFA\uDDFC\uDDFE])|\uD83C\uDDEB(?:\uD83C[\uDDEE-\uDDF0\uDDF2\uDDF4\uDDF7])|\uD83C\uDDEA(?:\uD83C[\uDDE6\uDDE8\uDDEA\uDDEC\uDDED\uDDF7-\uDDFA])|\uD83C\uDDE9(?:\uD83C[\uDDEA\uDDEC\uDDEF\uDDF0\uDDF2\uDDF4\uDDFF])|\uD83C\uDDE8(?:\uD83C[\uDDE6\uDDE8\uDDE9\uDDEB-\uDDEE\uDDF0-\uDDF5\uDDF7\uDDFA-\uDDFF])|\uD83C\uDDE7(?:\uD83C[\uDDE6\uDDE7\uDDE9-\uDDEF\uDDF1-\uDDF4\uDDF6-\uDDF9\uDDFB\uDDFC\uDDFE\uDDFF])|\uD83C\uDDE6(?:\uD83C[\uDDE8-\uDDEC\uDDEE\uDDF1\uDDF2\uDDF4\uDDF6-\uDDFA\uDDFC\uDDFD\uDDFF])|[#\*0-9]\uFE0F\u20E3|\u2764\uFE0F|(?:\uD83C[\uDFC3\uDFC4\uDFCA]|\uD83D[\uDC6E\uDC70\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6]|\uD83E[\uDD26\uDD35\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD-\uDDCF\uDDD4\uDDD6-\uDDDD])(?:\uD83C[\uDFFB-\uDFFF])|(?:\u26F9|\uD83C[\uDFCB\uDFCC]|\uD83D\uDD75)(?:\uFE0F|\uD83C[\uDFFB-\uDFFF])|\uD83C\uDFF4|(?:[\u270A\u270B]|\uD83C[\uDF85\uDFC2\uDFC7]|\uD83D[\uDC42\uDC43\uDC46-\uDC50\uDC66\uDC67\uDC6B-\uDC6D\uDC72\uDC74-\uDC76\uDC78\uDC7C\uDC83\uDC85\uDC8F\uDC91\uDCAA\uDD7A\uDD95\uDD96\uDE4C\uDE4F\uDEC0\uDECC]|\uD83E[\uDD0C\uDD0F\uDD18-\uDD1C\uDD1E\uDD1F\uDD30-\uDD34\uDD36\uDD77\uDDB5\uDDB6\uDDBB\uDDD2\uDDD3\uDDD5])(?:\uD83C[\uDFFB-\uDFFF])|(?:[\u261D\u270C\u270D]|\uD83D[\uDD74\uDD90])(?:\uFE0F|\uD83C[\uDFFB-\uDFFF])|[\u270A\u270B]|\uD83C[\uDF85\uDFC2\uDFC7]|\uD83D[\uDC08\uDC15\uDC3B\uDC42\uDC43\uDC46-\uDC50\uDC66\uDC67\uDC6B-\uDC6D\uDC72\uDC74-\uDC76\uDC78\uDC7C\uDC83\uDC85\uDC8F\uDC91\uDCAA\uDD7A\uDD95\uDD96\uDE2E\uDE35\uDE36\uDE4C\uDE4F\uDEC0\uDECC]|\uD83E[\uDD0C\uDD0F\uDD18-\uDD1C\uDD1E\uDD1F\uDD30-\uDD34\uDD36\uDD77\uDDB5\uDDB6\uDDBB\uDDD2\uDDD3\uDDD5]|\uD83C[\uDFC3\uDFC4\uDFCA]|\uD83D[\uDC6E\uDC70\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6]|\uD83E[\uDD26\uDD35\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD-\uDDCF\uDDD4\uDDD6-\uDDDD]|\uD83D\uDC6F|\uD83E[\uDD3C\uDDDE\uDDDF]|[\u231A\u231B\u23E9-\u23EC\u23F0\u23F3\u25FD\u25FE\u2614\u2615\u2648-\u2653\u267F\u2693\u26A1\u26AA\u26AB\u26BD\u26BE\u26C4\u26C5\u26CE\u26D4\u26EA\u26F2\u26F3\u26F5\u26FA\u26FD\u2705\u2728\u274C\u274E\u2753-\u2755\u2757\u2795-\u2797\u27B0\u27BF\u2B1B\u2B1C\u2B50\u2B55]|\uD83C[\uDC04\uDCCF\uDD8E\uDD91-\uDD9A\uDE01\uDE1A\uDE2F\uDE32-\uDE36\uDE38-\uDE3A\uDE50\uDE51\uDF00-\uDF20\uDF2D-\uDF35\uDF37-\uDF7C\uDF7E-\uDF84\uDF86-\uDF93\uDFA0-\uDFC1\uDFC5\uDFC6\uDFC8\uDFC9\uDFCF-\uDFD3\uDFE0-\uDFF0\uDFF8-\uDFFF]|\uD83D[\uDC00-\uDC07\uDC09-\uDC14\uDC16-\uDC3A\uDC3C-\uDC3E\uDC40\uDC44\uDC45\uDC51-\uDC65\uDC6A\uDC79-\uDC7B\uDC7D-\uDC80\uDC84\uDC88-\uDC8E\uDC90\uDC92-\uDCA9\uDCAB-\uDCFC\uDCFF-\uDD3D\uDD4B-\uDD4E\uDD50-\uDD67\uDDA4\uDDFB-\uDE2D\uDE2F-\uDE34\uDE37-\uDE44\uDE48-\uDE4A\uDE80-\uDEA2\uDEA4-\uDEB3\uDEB7-\uDEBF\uDEC1-\uDEC5\uDED0-\uDED2\uDED5-\uDED7\uDEEB\uDEEC\uDEF4-\uDEFC\uDFE0-\uDFEB]|\uD83E[\uDD0D\uDD0E\uDD10-\uDD17\uDD1D\uDD20-\uDD25\uDD27-\uDD2F\uDD3A\uDD3F-\uDD45\uDD47-\uDD76\uDD78\uDD7A-\uDDB4\uDDB7\uDDBA\uDDBC-\uDDCB\uDDD0\uDDE0-\uDDFF\uDE70-\uDE74\uDE78-\uDE7A\uDE80-\uDE86\uDE90-\uDEA8\uDEB0-\uDEB6\uDEC0-\uDEC2\uDED0-\uDED6]|(?:[\u231A\u231B\u23E9-\u23EC\u23F0\u23F3\u25FD\u25FE\u2614\u2615\u2648-\u2653\u267F\u2693\u26A1\u26AA\u26AB\u26BD\u26BE\u26C4\u26C5\u26CE\u26D4\u26EA\u26F2\u26F3\u26F5\u26FA\u26FD\u2705\u270A\u270B\u2728\u274C\u274E\u2753-\u2755\u2757\u2795-\u2797\u27B0\u27BF\u2B1B\u2B1C\u2B50\u2B55]|\uD83C[\uDC04\uDCCF\uDD8E\uDD91-\uDD9A\uDDE6-\uDDFF\uDE01\uDE1A\uDE2F\uDE32-\uDE36\uDE38-\uDE3A\uDE50\uDE51\uDF00-\uDF20\uDF2D-\uDF35\uDF37-\uDF7C\uDF7E-\uDF93\uDFA0-\uDFCA\uDFCF-\uDFD3\uDFE0-\uDFF0\uDFF4\uDFF8-\uDFFF]|\uD83D[\uDC00-\uDC3E\uDC40\uDC42-\uDCFC\uDCFF-\uDD3D\uDD4B-\uDD4E\uDD50-\uDD67\uDD7A\uDD95\uDD96\uDDA4\uDDFB-\uDE4F\uDE80-\uDEC5\uDECC\uDED0-\uDED2\uDED5-\uDED7\uDEEB\uDEEC\uDEF4-\uDEFC\uDFE0-\uDFEB]|\uD83E[\uDD0C-\uDD3A\uDD3C-\uDD45\uDD47-\uDD78\uDD7A-\uDDCB\uDDCD-\uDDFF\uDE70-\uDE74\uDE78-\uDE7A\uDE80-\uDE86\uDE90-\uDEA8\uDEB0-\uDEB6\uDEC0-\uDEC2\uDED0-\uDED6])|(?:[#\*0-9\xA9\xAE\u203C\u2049\u2122\u2139\u2194-\u2199\u21A9\u21AA\u231A\u231B\u2328\u23CF\u23E9-\u23F3\u23F8-\u23FA\u24C2\u25AA\u25AB\u25B6\u25C0\u25FB-\u25FE\u2600-\u2604\u260E\u2611\u2614\u2615\u2618\u261D\u2620\u2622\u2623\u2626\u262A\u262E\u262F\u2638-\u263A\u2640\u2642\u2648-\u2653\u265F\u2660\u2663\u2665\u2666\u2668\u267B\u267E\u267F\u2692-\u2697\u2699\u269B\u269C\u26A0\u26A1\u26A7\u26AA\u26AB\u26B0\u26B1\u26BD\u26BE\u26C4\u26C5\u26C8\u26CE\u26CF\u26D1\u26D3\u26D4\u26E9\u26EA\u26F0-\u26F5\u26F7-\u26FA\u26FD\u2702\u2705\u2708-\u270D\u270F\u2712\u2714\u2716\u271D\u2721\u2728\u2733\u2734\u2744\u2747\u274C\u274E\u2753-\u2755\u2757\u2763\u2764\u2795-\u2797\u27A1\u27B0\u27BF\u2934\u2935\u2B05-\u2B07\u2B1B\u2B1C\u2B50\u2B55\u3030\u303D\u3297\u3299]|\uD83C[\uDC04\uDCCF\uDD70\uDD71\uDD7E\uDD7F\uDD8E\uDD91-\uDD9A\uDDE6-\uDDFF\uDE01\uDE02\uDE1A\uDE2F\uDE32-\uDE3A\uDE50\uDE51\uDF00-\uDF21\uDF24-\uDF93\uDF96\uDF97\uDF99-\uDF9B\uDF9E-\uDFF0\uDFF3-\uDFF5\uDFF7-\uDFFF]|\uD83D[\uDC00-\uDCFD\uDCFF-\uDD3D\uDD49-\uDD4E\uDD50-\uDD67\uDD6F\uDD70\uDD73-\uDD7A\uDD87\uDD8A-\uDD8D\uDD90\uDD95\uDD96\uDDA4\uDDA5\uDDA8\uDDB1\uDDB2\uDDBC\uDDC2-\uDDC4\uDDD1-\uDDD3\uDDDC-\uDDDE\uDDE1\uDDE3\uDDE8\uDDEF\uDDF3\uDDFA-\uDE4F\uDE80-\uDEC5\uDECB-\uDED2\uDED5-\uDED7\uDEE0-\uDEE5\uDEE9\uDEEB\uDEEC\uDEF0\uDEF3-\uDEFC\uDFE0-\uDFEB]|\uD83E[\uDD0C-\uDD3A\uDD3C-\uDD45\uDD47-\uDD78\uDD7A-\uDDCB\uDDCD-\uDDFF\uDE70-\uDE74\uDE78-\uDE7A\uDE80-\uDE86\uDE90-\uDEA8\uDEB0-\uDEB6\uDEC0-\uDEC2\uDED0-\uDED6])\uFE0F|(?:[\u261D\u26F9\u270A-\u270D]|\uD83C[\uDF85\uDFC2-\uDFC4\uDFC7\uDFCA-\uDFCC]|\uD83D[\uDC42\uDC43\uDC46-\uDC50\uDC66-\uDC78\uDC7C\uDC81-\uDC83\uDC85-\uDC87\uDC8F\uDC91\uDCAA\uDD74\uDD75\uDD7A\uDD90\uDD95\uDD96\uDE45-\uDE47\uDE4B-\uDE4F\uDEA3\uDEB4-\uDEB6\uDEC0\uDECC]|\uD83E[\uDD0C\uDD0F\uDD18-\uDD1F\uDD26\uDD30-\uDD39\uDD3C-\uDD3E\uDD77\uDDB5\uDDB6\uDDB8\uDDB9\uDDBB\uDDCD-\uDDCF\uDDD1-\uDDDD])/g;
1564
+ };
1565
+ var FD = O(uD);
1566
+ function A(t, u = {}) {
1567
+ if (typeof t != "string" || t.length === 0 || (u = { ambiguousIsNarrow: true, ...u }, t = T(t), t.length === 0))
1568
+ return 0;
1569
+ t = t.replace(FD(), " ");
1570
+ const F = u.ambiguousIsNarrow ? 1 : 2;
1571
+ let e = 0;
1572
+ for (const s of t) {
1573
+ const i = s.codePointAt(0);
1574
+ if (i <= 31 || i >= 127 && i <= 159 || i >= 768 && i <= 879)
1575
+ continue;
1576
+ switch (DD.eastAsianWidth(s)) {
1577
+ case "F":
1578
+ case "W":
1579
+ e += 2;
1580
+ break;
1581
+ case "A":
1582
+ e += F;
1583
+ break;
1584
+ default:
1585
+ e += 1;
1606
1586
  }
1607
- } catch {}
1608
- try {
1609
- const res = await fetch(`https://github.com/${repo}/releases/latest`, {
1610
- redirect: "manual",
1611
- signal: AbortSignal.timeout(5000),
1612
- headers: { "User-Agent": USER_AGENT }
1613
- });
1614
- const loc = res.headers.get("location") ?? "";
1615
- const m3 = loc.match(/releases\/tag\/(v[^/]+)$/);
1616
- if (m3)
1617
- return m3[1];
1618
- } catch {}
1619
- return null;
1587
+ }
1588
+ return e;
1620
1589
  }
1621
- async function fetchManifest(tag) {
1622
- const resolvedTag = tag ?? manifest_default.tag;
1623
- try {
1624
- const url = getRawUrl(manifest_default.repo, resolvedTag, "manifest.json");
1625
- const response = await fetch(url, {
1626
- signal: AbortSignal.timeout(5000),
1627
- headers: { "User-Agent": USER_AGENT }
1628
- });
1629
- if (response.ok) {
1630
- return await response.json();
1590
+ var m = 10;
1591
+ var L = (t = 0) => (u) => `\x1B[${u + t}m`;
1592
+ var N = (t = 0) => (u) => `\x1B[${38 + t};5;${u}m`;
1593
+ var I = (t = 0) => (u, F, e) => `\x1B[${38 + t};2;${u};${F};${e}m`;
1594
+ var r = { modifier: { reset: [0, 0], bold: [1, 22], dim: [2, 22], italic: [3, 23], underline: [4, 24], overline: [53, 55], inverse: [7, 27], hidden: [8, 28], strikethrough: [9, 29] }, color: { black: [30, 39], red: [31, 39], green: [32, 39], yellow: [33, 39], blue: [34, 39], magenta: [35, 39], cyan: [36, 39], white: [37, 39], blackBright: [90, 39], gray: [90, 39], grey: [90, 39], redBright: [91, 39], greenBright: [92, 39], yellowBright: [93, 39], blueBright: [94, 39], magentaBright: [95, 39], cyanBright: [96, 39], whiteBright: [97, 39] }, bgColor: { bgBlack: [40, 49], bgRed: [41, 49], bgGreen: [42, 49], bgYellow: [43, 49], bgBlue: [44, 49], bgMagenta: [45, 49], bgCyan: [46, 49], bgWhite: [47, 49], bgBlackBright: [100, 49], bgGray: [100, 49], bgGrey: [100, 49], bgRedBright: [101, 49], bgGreenBright: [102, 49], bgYellowBright: [103, 49], bgBlueBright: [104, 49], bgMagentaBright: [105, 49], bgCyanBright: [106, 49], bgWhiteBright: [107, 49] } };
1595
+ Object.keys(r.modifier);
1596
+ var tD = Object.keys(r.color);
1597
+ var eD = Object.keys(r.bgColor);
1598
+ [...tD, ...eD];
1599
+ function sD() {
1600
+ const t = new Map;
1601
+ for (const [u, F] of Object.entries(r)) {
1602
+ for (const [e, s] of Object.entries(F))
1603
+ r[e] = { open: `\x1B[${s[0]}m`, close: `\x1B[${s[1]}m` }, F[e] = r[e], t.set(s[0], s[1]);
1604
+ Object.defineProperty(r, u, { value: F, enumerable: false });
1605
+ }
1606
+ return Object.defineProperty(r, "codes", { value: t, enumerable: false }), r.color.close = "\x1B[39m", r.bgColor.close = "\x1B[49m", r.color.ansi = L(), r.color.ansi256 = N(), r.color.ansi16m = I(), r.bgColor.ansi = L(m), r.bgColor.ansi256 = N(m), r.bgColor.ansi16m = I(m), Object.defineProperties(r, { rgbToAnsi256: { value: (u, F, e) => u === F && F === e ? u < 8 ? 16 : u > 248 ? 231 : Math.round((u - 8) / 247 * 24) + 232 : 16 + 36 * Math.round(u / 255 * 5) + 6 * Math.round(F / 255 * 5) + Math.round(e / 255 * 5), enumerable: false }, hexToRgb: { value: (u) => {
1607
+ const F = /[a-f\d]{6}|[a-f\d]{3}/i.exec(u.toString(16));
1608
+ if (!F)
1609
+ return [0, 0, 0];
1610
+ let [e] = F;
1611
+ e.length === 3 && (e = [...e].map((i) => i + i).join(""));
1612
+ const s = Number.parseInt(e, 16);
1613
+ return [s >> 16 & 255, s >> 8 & 255, s & 255];
1614
+ }, enumerable: false }, hexToAnsi256: { value: (u) => r.rgbToAnsi256(...r.hexToRgb(u)), enumerable: false }, ansi256ToAnsi: { value: (u) => {
1615
+ if (u < 8)
1616
+ return 30 + u;
1617
+ if (u < 16)
1618
+ return 90 + (u - 8);
1619
+ let F, e, s;
1620
+ if (u >= 232)
1621
+ F = ((u - 232) * 10 + 8) / 255, e = F, s = F;
1622
+ else {
1623
+ u -= 16;
1624
+ const C = u % 36;
1625
+ F = Math.floor(u / 36) / 5, e = Math.floor(C / 6) / 5, s = C % 6 / 5;
1631
1626
  }
1632
- } catch {}
1633
- return manifest_default;
1634
- }
1635
- async function fetchLatestManifest() {
1636
- const latestTag = await fetchLatestReleaseTag(manifest_default.repo);
1637
- const currentTag = manifest_default.tag;
1638
- const isNew = latestTag !== null && latestTag !== currentTag;
1639
- const manifest = await fetchManifest(latestTag ?? currentTag);
1640
- return { manifest, isNew, latestTag };
1627
+ const i = Math.max(F, e, s) * 2;
1628
+ if (i === 0)
1629
+ return 30;
1630
+ let D = 30 + (Math.round(s) << 2 | Math.round(e) << 1 | Math.round(F));
1631
+ return i === 2 && (D += 60), D;
1632
+ }, enumerable: false }, rgbToAnsi: { value: (u, F, e) => r.ansi256ToAnsi(r.rgbToAnsi256(u, F, e)), enumerable: false }, hexToAnsi: { value: (u) => r.ansi256ToAnsi(r.hexToAnsi256(u)), enumerable: false } }), r;
1641
1633
  }
1642
- async function downloadFile(manifest, filePath) {
1643
- validateFilePath(filePath);
1644
- const item = [
1645
- ...manifest.agents,
1646
- ...manifest.commands,
1647
- ...manifest.skills ?? [],
1648
- ...manifest.mcpServers ?? []
1649
- ].find((i) => i.file === filePath);
1650
- const expectedHash = item?.sha256 ?? null;
1651
- const projectRoot = findProjectRoot();
1652
- const cached = getCached(projectRoot, manifest.repo, manifest.tag, filePath, expectedHash);
1653
- if (cached !== null)
1654
- return cached;
1655
- const url = getRawUrl(manifest.repo, manifest.tag, filePath);
1656
- const response = await fetch(url, {
1657
- headers: { "User-Agent": USER_AGENT },
1658
- signal: AbortSignal.timeout(30000)
1659
- });
1660
- if (!response.ok) {
1661
- throw new Error(`Error descargando ${url}: ${response.status} ${response.statusText}`);
1634
+ var iD = sD();
1635
+ var v = new Set(["\x1B", "›"]);
1636
+ var CD = 39;
1637
+ var w = "\x07";
1638
+ var W = "[";
1639
+ var rD = "]";
1640
+ var R = "m";
1641
+ var y = `${rD}8;;`;
1642
+ var V = (t) => `${v.values().next().value}${W}${t}${R}`;
1643
+ var z = (t) => `${v.values().next().value}${y}${t}${w}`;
1644
+ var ED = (t) => t.split(" ").map((u) => A(u));
1645
+ var _ = (t, u, F) => {
1646
+ const e = [...u];
1647
+ let s = false, i = false, D = A(T(t[t.length - 1]));
1648
+ for (const [C, o] of e.entries()) {
1649
+ const E = A(o);
1650
+ if (D + E <= F ? t[t.length - 1] += o : (t.push(o), D = 0), v.has(o) && (s = true, i = e.slice(C + 1).join("").startsWith(y)), s) {
1651
+ i ? o === w && (s = false, i = false) : o === R && (s = false);
1652
+ continue;
1653
+ }
1654
+ D += E, D === F && C < e.length - 1 && (t.push(""), D = 0);
1662
1655
  }
1663
- const content = await response.text();
1664
- verifyChecksum(content, expectedHash, filePath);
1665
- putCache(projectRoot, manifest.repo, manifest.tag, filePath, content);
1666
- return content;
1667
- }
1668
- var GITHUB_RAW = "https://raw.githubusercontent.com", __filename2, __dirname2, PACKAGE_ROOT, BUNDLED_SKILLS_DIR, BUNDLED_MCP_DIR;
1669
- var init_github = __esm(() => {
1670
- init_manifest();
1671
- init_cache();
1672
- init_security();
1673
- init_fs();
1674
- __filename2 = fileURLToPath(import.meta.url);
1675
- __dirname2 = dirname3(__filename2);
1676
- PACKAGE_ROOT = join3(__dirname2, "..");
1677
- BUNDLED_SKILLS_DIR = join3(PACKAGE_ROOT, "assets", "skills");
1678
- BUNDLED_MCP_DIR = join3(PACKAGE_ROOT, "assets", "mcp");
1679
- });
1680
-
1681
- // src/lockfile.ts
1682
- var exports_lockfile = {};
1683
- __export(exports_lockfile, {
1684
- writeLockfile: () => writeLockfile,
1685
- removeFromLockfile: () => removeFromLockfile,
1686
- readLockfile: () => readLockfile,
1687
- getLockfilePath: () => getLockfilePath,
1688
- getInstalledVersion: () => getInstalledVersion,
1689
- clearLockfile: () => clearLockfile
1690
- });
1691
- import { existsSync as existsSync3, readFileSync as readFileSync3, writeFileSync as writeFileSync3 } from "fs";
1692
- import { join as join4 } from "path";
1693
- function getLockfilePath(opencodeRoot) {
1694
- return join4(opencodeRoot, LOCKFILE_NAME);
1695
- }
1696
- function readLockfile(opencodeRoot) {
1697
- const lockPath = getLockfilePath(opencodeRoot);
1698
- if (!existsSync3(lockPath))
1699
- return null;
1700
- try {
1701
- return JSON.parse(readFileSync3(lockPath, "utf-8"));
1702
- } catch {
1703
- return null;
1656
+ !D && t[t.length - 1].length > 0 && t.length > 1 && (t[t.length - 2] += t.pop());
1657
+ };
1658
+ var nD = (t) => {
1659
+ const u = t.split(" ");
1660
+ let F = u.length;
1661
+ for (;F > 0 && !(A(u[F - 1]) > 0); )
1662
+ F--;
1663
+ return F === u.length ? t : u.slice(0, F).join(" ") + u.slice(F).join("");
1664
+ };
1665
+ var oD = (t, u, F = {}) => {
1666
+ if (F.trim !== false && t.trim() === "")
1667
+ return "";
1668
+ let e = "", s, i;
1669
+ const D = ED(t);
1670
+ let C = [""];
1671
+ for (const [E, a] of t.split(" ").entries()) {
1672
+ F.trim !== false && (C[C.length - 1] = C[C.length - 1].trimStart());
1673
+ let n = A(C[C.length - 1]);
1674
+ if (E !== 0 && (n >= u && (F.wordWrap === false || F.trim === false) && (C.push(""), n = 0), (n > 0 || F.trim === false) && (C[C.length - 1] += " ", n++)), F.hard && D[E] > u) {
1675
+ const B = u - n, p = 1 + Math.floor((D[E] - B - 1) / u);
1676
+ Math.floor((D[E] - 1) / u) < p && C.push(""), _(C, a, u);
1677
+ continue;
1678
+ }
1679
+ if (n + D[E] > u && n > 0 && D[E] > 0) {
1680
+ if (F.wordWrap === false && n < u) {
1681
+ _(C, a, u);
1682
+ continue;
1683
+ }
1684
+ C.push("");
1685
+ }
1686
+ if (n + D[E] > u && F.wordWrap === false) {
1687
+ _(C, a, u);
1688
+ continue;
1689
+ }
1690
+ C[C.length - 1] += a;
1691
+ }
1692
+ F.trim !== false && (C = C.map((E) => nD(E)));
1693
+ const o = [...C.join(`
1694
+ `)];
1695
+ for (const [E, a] of o.entries()) {
1696
+ if (e += a, v.has(a)) {
1697
+ const { groups: B } = new RegExp(`(?:\\${W}(?<code>\\d+)m|\\${y}(?<uri>.*)${w})`).exec(o.slice(E).join("")) || { groups: {} };
1698
+ if (B.code !== undefined) {
1699
+ const p = Number.parseFloat(B.code);
1700
+ s = p === CD ? undefined : p;
1701
+ } else
1702
+ B.uri !== undefined && (i = B.uri.length === 0 ? undefined : B.uri);
1703
+ }
1704
+ const n = iD.codes.get(Number(s));
1705
+ o[E + 1] === `
1706
+ ` ? (i && (e += z("")), s && n && (e += V(n))) : a === `
1707
+ ` && (s && n && (e += V(s)), i && (e += z(i)));
1704
1708
  }
1709
+ return e;
1710
+ };
1711
+ function G(t, u, F) {
1712
+ return String(t).normalize().replace(/\r\n/g, `
1713
+ `).split(`
1714
+ `).map((e) => oD(e, u, F)).join(`
1715
+ `);
1705
1716
  }
1706
- function writeLockfile(opencodeRoot, lockfile) {
1707
- writeFileSync3(getLockfilePath(opencodeRoot), JSON.stringify(lockfile, null, 2), "utf-8");
1717
+ var aD = ["up", "down", "left", "right", "space", "enter", "cancel"];
1718
+ var c = { actions: new Set(aD), aliases: new Map([["k", "up"], ["j", "down"], ["h", "left"], ["l", "right"], ["\x03", "cancel"], ["escape", "cancel"]]) };
1719
+ function hD(t) {
1720
+ for (const u in t) {
1721
+ const F = u;
1722
+ if (!Object.hasOwn(t, F))
1723
+ continue;
1724
+ const e = t[F];
1725
+ switch (F) {
1726
+ case "aliases": {
1727
+ for (const s in e)
1728
+ Object.hasOwn(e, s) && (c.aliases.has(s) || c.aliases.set(s, e[s]));
1729
+ break;
1730
+ }
1731
+ }
1732
+ }
1708
1733
  }
1709
- function getInstalledVersion(lockfile, type, name) {
1710
- return lockfile?.[type]?.[name]?.version ?? null;
1734
+ function k(t, u) {
1735
+ if (typeof t == "string")
1736
+ return c.aliases.get(t) === u;
1737
+ for (const F of t)
1738
+ if (F !== undefined && k(F, u))
1739
+ return true;
1740
+ return false;
1711
1741
  }
1712
- function removeFromLockfile(opencodeRoot, type, name) {
1713
- const lockfile = readLockfile(opencodeRoot);
1714
- if (!lockfile)
1715
- return;
1716
- if (!lockfile[type])
1717
- return;
1718
- if (!(name in lockfile[type]))
1742
+ function lD(t, u) {
1743
+ if (t === u)
1719
1744
  return;
1720
- delete lockfile[type][name];
1721
- writeLockfile(opencodeRoot, lockfile);
1745
+ const F = t.split(`
1746
+ `), e = u.split(`
1747
+ `), s = [];
1748
+ for (let i = 0;i < Math.max(F.length, e.length); i++)
1749
+ F[i] !== e[i] && s.push(i);
1750
+ return s;
1722
1751
  }
1723
- function clearLockfile(opencodeRoot) {
1724
- const lockfile = readLockfile(opencodeRoot);
1725
- if (!lockfile) {
1726
- writeLockfile(opencodeRoot, {
1727
- version: LOCKFILE_VERSION,
1728
- lockedAt: new Date().toISOString(),
1729
- repo: "",
1730
- tag: "",
1731
- agents: {},
1732
- commands: {},
1733
- skills: {},
1734
- mcpServers: {}
1752
+ var xD = globalThis.process.platform.startsWith("win");
1753
+ var S = Symbol("clack:cancel");
1754
+ function BD(t) {
1755
+ return t === S;
1756
+ }
1757
+ function d(t, u) {
1758
+ const F = t;
1759
+ F.isTTY && F.setRawMode(u);
1760
+ }
1761
+ function cD({ input: t = $, output: u = j, overwrite: F = true, hideCursor: e = true } = {}) {
1762
+ const s = f.createInterface({ input: t, output: u, prompt: "", tabSize: 1 });
1763
+ f.emitKeypressEvents(t, s), t.isTTY && t.setRawMode(true);
1764
+ const i = (D, { name: C, sequence: o }) => {
1765
+ const E = String(D);
1766
+ if (k([E, C, o], "cancel")) {
1767
+ e && u.write(import_sisteransi.cursor.show), process.exit(0);
1768
+ return;
1769
+ }
1770
+ if (!F)
1771
+ return;
1772
+ const a = C === "return" ? 0 : -1, n = C === "return" ? -1 : 0;
1773
+ f.moveCursor(u, a, n, () => {
1774
+ f.clearLine(u, 1, () => {
1775
+ t.once("keypress", i);
1776
+ });
1735
1777
  });
1736
- return;
1737
- }
1738
- lockfile.agents = {};
1739
- lockfile.commands = {};
1740
- lockfile.skills = {};
1741
- lockfile.mcpServers = {};
1742
- lockfile.lockedAt = new Date().toISOString();
1743
- writeLockfile(opencodeRoot, lockfile);
1778
+ };
1779
+ return e && u.write(import_sisteransi.cursor.hide), t.once("keypress", i), () => {
1780
+ t.off("keypress", i), e && u.write(import_sisteransi.cursor.show), t.isTTY && !xD && t.setRawMode(false), s.terminal = false, s.close();
1781
+ };
1744
1782
  }
1745
- var LOCKFILE_NAME = "ostacky-lock.json", LOCKFILE_VERSION;
1746
- var init_lockfile = __esm(() => {
1747
- init_manifest();
1748
- LOCKFILE_VERSION = manifest_default.version;
1749
- });
1783
+ var AD = Object.defineProperty;
1784
+ var pD = (t, u, F) => (u in t) ? AD(t, u, { enumerable: true, configurable: true, writable: true, value: F }) : t[u] = F;
1785
+ var h = (t, u, F) => (pD(t, typeof u != "symbol" ? u + "" : u, F), F);
1750
1786
 
1751
- // src/config.ts
1752
- var exports_config = {};
1753
- __export(exports_config, {
1754
- writeOpenCodeConfig: () => writeOpenCodeConfig,
1755
- stripJsoncComments: () => stripJsoncComments,
1756
- setMcpEntry: () => setMcpEntry,
1757
- readOpenCodeConfig: () => readOpenCodeConfig,
1758
- patchOpenCodeConfig: () => patchOpenCodeConfig,
1759
- findOpenCodeConfig: () => findOpenCodeConfig,
1760
- ensureOpenCodeConfig: () => ensureOpenCodeConfig,
1761
- ensureMcpEntry: () => ensureMcpEntry
1762
- });
1763
- import { existsSync as existsSync4, readFileSync as readFileSync4, writeFileSync as writeFileSync4 } from "fs";
1764
- import { join as join5 } from "path";
1765
- function stripJsoncComments(text) {
1766
- let result = "";
1767
- let i = 0;
1768
- let inString = false;
1769
- while (i < text.length) {
1770
- const char = text[i];
1771
- const next = text[i + 1];
1772
- if (inString) {
1773
- if (char === "\\") {
1774
- result += char + (next ?? "");
1775
- i += 2;
1776
- continue;
1787
+ class x {
1788
+ constructor(u, F = true) {
1789
+ h(this, "input"), h(this, "output"), h(this, "_abortSignal"), h(this, "rl"), h(this, "opts"), h(this, "_render"), h(this, "_track", false), h(this, "_prevFrame", ""), h(this, "_subscribers", new Map), h(this, "_cursor", 0), h(this, "state", "initial"), h(this, "error", ""), h(this, "value");
1790
+ const { input: e = $, output: s = j, render: i, signal: D, ...C } = u;
1791
+ this.opts = C, this.onKeypress = this.onKeypress.bind(this), this.close = this.close.bind(this), this.render = this.render.bind(this), this._render = i.bind(this), this._track = F, this._abortSignal = D, this.input = e, this.output = s;
1792
+ }
1793
+ unsubscribe() {
1794
+ this._subscribers.clear();
1795
+ }
1796
+ setSubscriber(u, F) {
1797
+ const e = this._subscribers.get(u) ?? [];
1798
+ e.push(F), this._subscribers.set(u, e);
1799
+ }
1800
+ on(u, F) {
1801
+ this.setSubscriber(u, { cb: F });
1802
+ }
1803
+ once(u, F) {
1804
+ this.setSubscriber(u, { cb: F, once: true });
1805
+ }
1806
+ emit(u, ...F) {
1807
+ const e = this._subscribers.get(u) ?? [], s = [];
1808
+ for (const i of e)
1809
+ i.cb(...F), i.once && s.push(() => e.splice(e.indexOf(i), 1));
1810
+ for (const i of s)
1811
+ i();
1812
+ }
1813
+ prompt() {
1814
+ return new Promise((u, F) => {
1815
+ if (this._abortSignal) {
1816
+ if (this._abortSignal.aborted)
1817
+ return this.state = "cancel", this.close(), u(S);
1818
+ this._abortSignal.addEventListener("abort", () => {
1819
+ this.state = "cancel", this.close();
1820
+ }, { once: true });
1777
1821
  }
1778
- if (char === '"')
1779
- inString = false;
1780
- result += char;
1781
- i++;
1782
- continue;
1783
- }
1784
- if (char === '"') {
1785
- inString = true;
1786
- result += char;
1787
- i++;
1788
- continue;
1789
- }
1790
- if (char === "/" && next === "/") {
1791
- while (i < text.length && text[i] !== `
1792
- `)
1793
- i++;
1794
- continue;
1822
+ const e = new U(0);
1823
+ e._write = (s, i, D) => {
1824
+ this._track && (this.value = this.rl?.line.replace(/\t/g, ""), this._cursor = this.rl?.cursor ?? 0, this.emit("value", this.value)), D();
1825
+ }, this.input.pipe(e), this.rl = M.createInterface({ input: this.input, output: e, tabSize: 2, prompt: "", escapeCodeTimeout: 50 }), M.emitKeypressEvents(this.input, this.rl), this.rl.prompt(), this.opts.initialValue !== undefined && this._track && this.rl.write(this.opts.initialValue), this.input.on("keypress", this.onKeypress), d(this.input, true), this.output.on("resize", this.render), this.render(), this.once("submit", () => {
1826
+ this.output.write(import_sisteransi.cursor.show), this.output.off("resize", this.render), d(this.input, false), u(this.value);
1827
+ }), this.once("cancel", () => {
1828
+ this.output.write(import_sisteransi.cursor.show), this.output.off("resize", this.render), d(this.input, false), u(S);
1829
+ });
1830
+ });
1831
+ }
1832
+ onKeypress(u, F) {
1833
+ if (this.state === "error" && (this.state = "active"), F?.name && (!this._track && c.aliases.has(F.name) && this.emit("cursor", c.aliases.get(F.name)), c.actions.has(F.name) && this.emit("cursor", F.name)), u && (u.toLowerCase() === "y" || u.toLowerCase() === "n") && this.emit("confirm", u.toLowerCase() === "y"), u === "\t" && this.opts.placeholder && (this.value || (this.rl?.write(this.opts.placeholder), this.emit("value", this.opts.placeholder))), u && this.emit("key", u.toLowerCase()), F?.name === "return") {
1834
+ if (this.opts.validate) {
1835
+ const e = this.opts.validate(this.value);
1836
+ e && (this.error = e instanceof Error ? e.message : e, this.state = "error", this.rl?.write(this.value));
1837
+ }
1838
+ this.state !== "error" && (this.state = "submit");
1795
1839
  }
1796
- if (char === "/" && next === "*") {
1797
- i += 2;
1798
- while (i < text.length && !(text[i] === "*" && text[i + 1] === "/"))
1799
- i++;
1800
- i += 2;
1801
- continue;
1840
+ k([u, F?.name, F?.sequence], "cancel") && (this.state = "cancel"), (this.state === "submit" || this.state === "cancel") && this.emit("finalize"), this.render(), (this.state === "submit" || this.state === "cancel") && this.close();
1841
+ }
1842
+ close() {
1843
+ this.input.unpipe(), this.input.removeListener("keypress", this.onKeypress), this.output.write(`
1844
+ `), d(this.input, false), this.rl?.close(), this.rl = undefined, this.emit(`${this.state}`, this.value), this.unsubscribe();
1845
+ }
1846
+ restoreCursor() {
1847
+ const u = G(this._prevFrame, process.stdout.columns, { hard: true }).split(`
1848
+ `).length - 1;
1849
+ this.output.write(import_sisteransi.cursor.move(-999, u * -1));
1850
+ }
1851
+ render() {
1852
+ const u = G(this._render(this) ?? "", process.stdout.columns, { hard: true });
1853
+ if (u !== this._prevFrame) {
1854
+ if (this.state === "initial")
1855
+ this.output.write(import_sisteransi.cursor.hide);
1856
+ else {
1857
+ const F = lD(this._prevFrame, u);
1858
+ if (this.restoreCursor(), F && F?.length === 1) {
1859
+ const e = F[0];
1860
+ this.output.write(import_sisteransi.cursor.move(0, e)), this.output.write(import_sisteransi.erase.lines(1));
1861
+ const s = u.split(`
1862
+ `);
1863
+ this.output.write(s[e]), this._prevFrame = u, this.output.write(import_sisteransi.cursor.move(0, s.length - e - 1));
1864
+ return;
1865
+ }
1866
+ if (F && F?.length > 1) {
1867
+ const e = F[0];
1868
+ this.output.write(import_sisteransi.cursor.move(0, e)), this.output.write(import_sisteransi.erase.down());
1869
+ const s = u.split(`
1870
+ `).slice(e);
1871
+ this.output.write(s.join(`
1872
+ `)), this._prevFrame = u;
1873
+ return;
1874
+ }
1875
+ this.output.write(import_sisteransi.erase.down());
1876
+ }
1877
+ this.output.write(u), this.state === "initial" && (this.state = "active"), this._prevFrame = u;
1802
1878
  }
1803
- result += char;
1804
- i++;
1805
1879
  }
1806
- return result.replace(/,\s*([}\]])/g, "$1");
1807
1880
  }
1808
- function readOpenCodeConfig(configPath) {
1809
- const raw = readFileSync4(configPath, "utf-8");
1810
- try {
1811
- return JSON.parse(stripJsoncComments(raw));
1812
- } catch {
1813
- return null;
1881
+
1882
+ class fD extends x {
1883
+ get cursor() {
1884
+ return this.value ? 0 : 1;
1885
+ }
1886
+ get _value() {
1887
+ return this.cursor === 0;
1888
+ }
1889
+ constructor(u) {
1890
+ super(u, false), this.value = !!u.initialValue, this.on("value", () => {
1891
+ this.value = this._value;
1892
+ }), this.on("confirm", (F) => {
1893
+ this.output.write(import_sisteransi.cursor.move(0, -1)), this.value = F, this.state = "submit", this.close();
1894
+ }), this.on("cursor", () => {
1895
+ this.value = !this.value;
1896
+ });
1814
1897
  }
1815
1898
  }
1816
- function writeOpenCodeConfig(configPath, config) {
1817
- writeFileSync4(configPath, JSON.stringify(config, null, 2) + `
1818
- `, "utf-8");
1819
- }
1820
- function ensureOpenCodeConfig(projectRoot) {
1821
- const existing = findOpenCodeConfig(projectRoot);
1822
- if (existing)
1823
- return existing;
1824
- const configPath = join5(projectRoot, "opencode.json");
1825
- writeOpenCodeConfig(configPath, {
1826
- $schema: "https://opencode.ai/config.json",
1827
- mcp: {}
1828
- });
1829
- return configPath;
1830
- }
1831
- function findOpenCodeConfig(projectRoot) {
1832
- const candidates = ["opencode.json", "opencode.jsonc"];
1833
- for (const name of candidates) {
1834
- const full = join5(projectRoot, name);
1835
- if (existsSync4(full))
1836
- return full;
1899
+ var gD = Object.defineProperty;
1900
+ var vD = (t, u, F) => (u in t) ? gD(t, u, { enumerable: true, configurable: true, writable: true, value: F }) : t[u] = F;
1901
+ var K = (t, u, F) => (vD(t, typeof u != "symbol" ? u + "" : u, F), F);
1902
+ var dD = class extends x {
1903
+ constructor(u) {
1904
+ super(u, false), K(this, "options"), K(this, "cursor", 0);
1905
+ const { options: F } = u;
1906
+ this.options = Object.entries(F).flatMap(([e, s]) => [{ value: e, group: true, label: e }, ...s.map((i) => ({ ...i, group: e }))]), this.value = [...u.initialValues ?? []], this.cursor = Math.max(this.options.findIndex(({ value: e }) => e === u.cursorAt), 0), this.on("cursor", (e) => {
1907
+ switch (e) {
1908
+ case "left":
1909
+ case "up":
1910
+ this.cursor = this.cursor === 0 ? this.options.length - 1 : this.cursor - 1;
1911
+ break;
1912
+ case "down":
1913
+ case "right":
1914
+ this.cursor = this.cursor === this.options.length - 1 ? 0 : this.cursor + 1;
1915
+ break;
1916
+ case "space":
1917
+ this.toggleValue();
1918
+ break;
1919
+ }
1920
+ });
1837
1921
  }
1838
- return null;
1839
- }
1840
- function setMcpEntry(name, entry) {
1841
- const projectRoot = findProjectRoot();
1842
- const configPath = ensureOpenCodeConfig(projectRoot);
1843
- const config = readOpenCodeConfig(configPath);
1844
- if (!config)
1845
- return;
1846
- if (!config.mcp)
1847
- config.mcp = {};
1848
- config.mcp[name] = entry;
1849
- writeOpenCodeConfig(configPath, config);
1850
- }
1851
- function ensureMcpEntry(name, entry) {
1852
- const projectRoot = findProjectRoot();
1853
- const configPath = ensureOpenCodeConfig(projectRoot);
1854
- const config = readOpenCodeConfig(configPath);
1855
- if (!config)
1856
- return;
1857
- if (!config.mcp)
1858
- config.mcp = {};
1859
- const mcp = config.mcp;
1860
- if (!mcp[name]) {
1861
- mcp[name] = entry;
1862
- writeOpenCodeConfig(configPath, config);
1922
+ getGroupItems(u) {
1923
+ return this.options.filter((F) => F.group === u);
1863
1924
  }
1864
- }
1865
- function patchOpenCodeConfig() {
1866
- const projectRoot = findProjectRoot();
1867
- const configPath = findOpenCodeConfig(projectRoot);
1868
- if (!configPath) {
1869
- return {
1870
- success: false,
1871
- message: "No se encontró opencode.json ni opencode.jsonc"
1872
- };
1925
+ isGroupSelected(u) {
1926
+ return this.getGroupItems(u).every((F) => this.value.includes(F.value));
1873
1927
  }
1874
- const config = readOpenCodeConfig(configPath);
1875
- if (!config) {
1876
- return {
1877
- success: false,
1878
- message: `Error parseando ${configPath}`
1879
- };
1928
+ toggleValue() {
1929
+ const u = this.options[this.cursor];
1930
+ if (u.group === true) {
1931
+ const F = u.value, e = this.getGroupItems(F);
1932
+ this.isGroupSelected(F) ? this.value = this.value.filter((s) => e.findIndex((i) => i.value === s) === -1) : this.value = [...this.value, ...e.map((s) => s.value)], this.value = Array.from(new Set(this.value));
1933
+ } else {
1934
+ const F = this.value.includes(u.value);
1935
+ this.value = F ? this.value.filter((e) => e !== u.value) : [...this.value, u.value];
1936
+ }
1880
1937
  }
1881
- let changed = false;
1882
- if ("plugin" in config) {
1883
- delete config.plugin;
1884
- changed = true;
1938
+ };
1939
+ var bD = Object.defineProperty;
1940
+ var mD = (t, u, F) => (u in t) ? bD(t, u, { enumerable: true, configurable: true, writable: true, value: F }) : t[u] = F;
1941
+ var Y = (t, u, F) => (mD(t, typeof u != "symbol" ? u + "" : u, F), F);
1942
+ var wD = class extends x {
1943
+ constructor(u) {
1944
+ super(u, false), Y(this, "options"), Y(this, "cursor", 0), this.options = u.options, this.value = [...u.initialValues ?? []], this.cursor = Math.max(this.options.findIndex(({ value: F }) => F === u.cursorAt), 0), this.on("key", (F) => {
1945
+ F === "a" && this.toggleAll();
1946
+ }), this.on("cursor", (F) => {
1947
+ switch (F) {
1948
+ case "left":
1949
+ case "up":
1950
+ this.cursor = this.cursor === 0 ? this.options.length - 1 : this.cursor - 1;
1951
+ break;
1952
+ case "down":
1953
+ case "right":
1954
+ this.cursor = this.cursor === this.options.length - 1 ? 0 : this.cursor + 1;
1955
+ break;
1956
+ case "space":
1957
+ this.toggleValue();
1958
+ break;
1959
+ }
1960
+ });
1885
1961
  }
1886
- if (changed) {
1887
- writeOpenCodeConfig(configPath, config);
1888
- return { success: true, message: "Config actualizada (plugin legacy eliminado)" };
1962
+ get _value() {
1963
+ return this.options[this.cursor].value;
1964
+ }
1965
+ toggleAll() {
1966
+ const u = this.value.length === this.options.length;
1967
+ this.value = u ? [] : this.options.map((F) => F.value);
1968
+ }
1969
+ toggleValue() {
1970
+ const u = this.value.includes(this._value);
1971
+ this.value = u ? this.value.filter((F) => F !== this._value) : [...this.value, this._value];
1972
+ }
1973
+ };
1974
+ var yD = Object.defineProperty;
1975
+ var _D = (t, u, F) => (u in t) ? yD(t, u, { enumerable: true, configurable: true, writable: true, value: F }) : t[u] = F;
1976
+ var Z = (t, u, F) => (_D(t, typeof u != "symbol" ? u + "" : u, F), F);
1977
+
1978
+ class kD extends x {
1979
+ constructor({ mask: u, ...F }) {
1980
+ super(F), Z(this, "valueWithCursor", ""), Z(this, "_mask", "•"), this._mask = u ?? "•", this.on("finalize", () => {
1981
+ this.valueWithCursor = this.masked;
1982
+ }), this.on("value", () => {
1983
+ if (this.cursor >= this.value.length)
1984
+ this.valueWithCursor = `${this.masked}${import_picocolors.default.inverse(import_picocolors.default.hidden("_"))}`;
1985
+ else {
1986
+ const e = this.masked.slice(0, this.cursor), s = this.masked.slice(this.cursor);
1987
+ this.valueWithCursor = `${e}${import_picocolors.default.inverse(s[0])}${s.slice(1)}`;
1988
+ }
1989
+ });
1990
+ }
1991
+ get cursor() {
1992
+ return this._cursor;
1993
+ }
1994
+ get masked() {
1995
+ return this.value.replaceAll(/./g, this._mask);
1889
1996
  }
1890
- return { success: true, message: "Config de OpenCode ya está limpia" };
1891
1997
  }
1892
- var init_config = __esm(() => {
1893
- init_fs();
1894
- });
1998
+ var SD = Object.defineProperty;
1999
+ var $D = (t, u, F) => (u in t) ? SD(t, u, { enumerable: true, configurable: true, writable: true, value: F }) : t[u] = F;
2000
+ var q = (t, u, F) => ($D(t, typeof u != "symbol" ? u + "" : u, F), F);
1895
2001
 
1896
- // src/stack.ts
1897
- var exports_stack = {};
1898
- __export(exports_stack, {
1899
- verifyMcpServers: () => verifyMcpServers,
1900
- uninstallStackConfig: () => uninstallStackConfig,
1901
- uninstallEngramConfig: () => uninstallEngramConfig,
1902
- setupOpenSpec: () => setupOpenSpec,
1903
- setupContext7: () => setupContext7,
1904
- installStack: () => installStack,
1905
- installEngram: () => installEngram,
1906
- installCodeGraph: () => installCodeGraph
1907
- });
1908
- import { existsSync as existsSync6, mkdirSync as mkdirSync4, copyFileSync as copyFileSync3, unlinkSync as unlinkSync3, rmSync as rmSync3 } from "fs";
1909
- import { join as join7 } from "path";
1910
- import { execSync as execSync3 } from "child_process";
1911
- async function installCodeGraph(toolsDir) {
1912
- const projectRoot = findProjectRoot();
1913
- const cgToolDir = join7(toolsDir ?? join7(projectRoot, ".opencode", "tools"), "codegraph");
1914
- if (!existsSync6(cgToolDir))
1915
- mkdirSync4(cgToolDir, { recursive: true });
1916
- const target = detectPlatformTarget();
1917
- if (!target) {
1918
- return {
1919
- success: false,
1920
- message: `Plataforma no soportada para descarga local: ${process.platform}/${process.arch}. Instalá CodeGraph manualmente.`
1921
- };
2002
+ class jD extends x {
2003
+ constructor(u) {
2004
+ super(u, false), q(this, "options"), q(this, "cursor", 0), this.options = u.options, this.cursor = this.options.findIndex(({ value: F }) => F === u.initialValue), this.cursor === -1 && (this.cursor = 0), this.changeValue(), this.on("cursor", (F) => {
2005
+ switch (F) {
2006
+ case "left":
2007
+ case "up":
2008
+ this.cursor = this.cursor === 0 ? this.options.length - 1 : this.cursor - 1;
2009
+ break;
2010
+ case "down":
2011
+ case "right":
2012
+ this.cursor = this.cursor === this.options.length - 1 ? 0 : this.cursor + 1;
2013
+ break;
2014
+ }
2015
+ this.changeValue();
2016
+ });
1922
2017
  }
1923
- const localBin = join7(cgToolDir, "bin", "codegraph");
1924
- const localBinExe = localBin + (process.platform === "win32" ? ".exe" : "");
1925
- if (existsSync6(localBinExe)) {
1926
- try {
1927
- execSync3(`"${localBinExe}" --version`, { stdio: "pipe", timeout: 1e4 });
1928
- } catch {
1929
- try {
1930
- rmSync3(join7(cgToolDir, "bin"), { recursive: true, force: true });
1931
- } catch {}
1932
- }
2018
+ get _value() {
2019
+ return this.options[this.cursor];
1933
2020
  }
1934
- if (!existsSync6(localBinExe)) {
1935
- const tag = await fetchLatestReleaseTag("colbymchenry/codegraph");
1936
- if (!tag) {
1937
- return {
1938
- success: false,
1939
- message: "No se pudo obtener la última versión de CodeGraph desde GitHub."
1940
- };
1941
- }
1942
- const ext = process.platform === "win32" ? "zip" : "tar.gz";
1943
- const url = `https://github.com/colbymchenry/codegraph/releases/download/${tag}/codegraph-${target}.${ext}`;
1944
- try {
1945
- await downloadAndExtractWithRetry(url, cgToolDir, 1, 180000, 2);
1946
- } catch (e2) {
1947
- return {
1948
- success: false,
1949
- message: `Error descargando CodeGraph ${tag}: ${e2.message}`
1950
- };
1951
- }
1952
- if (!existsSync6(localBinExe)) {
1953
- return {
1954
- success: false,
1955
- message: `Descarga de CodeGraph ${tag} completada pero no se encontró el binario en ${localBinExe}.`
1956
- };
1957
- }
1958
- if (process.platform !== "win32") {
1959
- try {
1960
- execSync3(`chmod +x "${localBinExe}"`, { stdio: "pipe" });
1961
- } catch {}
1962
- }
2021
+ changeValue() {
2022
+ this.value = this._value.value;
1963
2023
  }
1964
- try {
1965
- execSync3(`"${localBinExe}" init -i`, { stdio: "pipe", timeout: 120000, cwd: projectRoot });
1966
- } catch {}
1967
- try {
1968
- execSync3(`"${localBinExe}" install --target opencode --location local --yes`, {
1969
- stdio: "pipe",
1970
- timeout: 30000,
1971
- cwd: projectRoot
2024
+ }
2025
+ var MD = Object.defineProperty;
2026
+ var TD = (t, u, F) => (u in t) ? MD(t, u, { enumerable: true, configurable: true, writable: true, value: F }) : t[u] = F;
2027
+ var H = (t, u, F) => (TD(t, typeof u != "symbol" ? u + "" : u, F), F);
2028
+
2029
+ class OD extends x {
2030
+ constructor(u) {
2031
+ super(u, false), H(this, "options"), H(this, "cursor", 0), this.options = u.options;
2032
+ const F = this.options.map(({ value: [e] }) => e?.toLowerCase());
2033
+ this.cursor = Math.max(F.indexOf(u.initialValue), 0), this.on("key", (e) => {
2034
+ if (!F.includes(e))
2035
+ return;
2036
+ const s = this.options.find(({ value: [i] }) => i?.toLowerCase() === e);
2037
+ s && (this.value = s.value, this.state = "submit", this.emit("submit"));
1972
2038
  });
1973
- } catch {}
1974
- const rootAgentsMd = join7(projectRoot, "AGENTS.md");
1975
- if (existsSync6(rootAgentsMd)) {
1976
- const dest = join7(cgToolDir, "AGENTS.md");
1977
- try {
1978
- copyFileSync3(rootAgentsMd, dest);
1979
- unlinkSync3(rootAgentsMd);
1980
- } catch {}
1981
2039
  }
1982
- setMcpEntry("codegraph", {
1983
- type: "local",
1984
- command: [`.opencode/tools/codegraph/bin/codegraph`, "serve", "--mcp"],
1985
- enabled: true
1986
- });
1987
- return { success: true, message: "CodeGraph instalado localmente en .opencode/tools/codegraph/ y configurado para OpenCode" };
1988
2040
  }
1989
- function setupOpenSpec() {
1990
- const npxCmd = isCommandAvailable("bun") ? "bunx" : "npx --yes";
1991
- try {
1992
- execSync3(`${npxCmd} openspec init --tools opencode --force`, {
1993
- stdio: "pipe",
1994
- timeout: 120000
2041
+
2042
+ class PD extends x {
2043
+ get valueWithCursor() {
2044
+ if (this.state === "submit")
2045
+ return this.value;
2046
+ if (this.cursor >= this.value.length)
2047
+ return `${this.value}█`;
2048
+ const u = this.value.slice(0, this.cursor), [F, ...e] = this.value.slice(this.cursor);
2049
+ return `${u}${import_picocolors.default.inverse(F)}${e.join("")}`;
2050
+ }
2051
+ get cursor() {
2052
+ return this._cursor;
2053
+ }
2054
+ constructor(u) {
2055
+ super(u), this.on("finalize", () => {
2056
+ this.value || (this.value = u.defaultValue);
1995
2057
  });
1996
- return { success: true, message: "OpenSpec configurado para OpenCode" };
1997
- } catch (e2) {
1998
- return {
1999
- success: false,
2000
- message: `Error configurando OpenSpec: ${e2.message}`
2001
- };
2002
2058
  }
2003
2059
  }
2004
- async function installEngram(toolsDir) {
2005
- const projectRoot = findProjectRoot();
2006
- const bunStatus = checkBunAvailability();
2007
- if (!bunStatus.available) {
2008
- console.log(`
2009
- ⚠️ Bun no detectado en el sistema.`);
2010
- console.log(` Para instalar Bun, ejecutá:
2011
- `);
2012
- console.log(` ${bunStatus.installCommand}`);
2013
- if (bunStatus.installNote) {
2014
- console.log(` Nota: ${bunStatus.installNote}`);
2015
- }
2016
- console.log(`
2017
- Documentación: https://bun.com/docs/installation
2018
- `);
2060
+
2061
+ // node_modules/@clack/prompts/dist/index.mjs
2062
+ var import_picocolors2 = __toESM(require_picocolors(), 1);
2063
+ var import_sisteransi2 = __toESM(require_src(), 1);
2064
+ import p from "node:process";
2065
+ function X2() {
2066
+ return p.platform !== "win32" ? p.env.TERM !== "linux" : !!p.env.CI || !!p.env.WT_SESSION || !!p.env.TERMINUS_SUBLIME || p.env.ConEmuTask === "{cmd::Cmder}" || p.env.TERM_PROGRAM === "Terminus-Sublime" || p.env.TERM_PROGRAM === "vscode" || p.env.TERM === "xterm-256color" || p.env.TERM === "alacritty" || p.env.TERMINAL_EMULATOR === "JetBrains-JediTerm";
2067
+ }
2068
+ var E = X2();
2069
+ var u = (s, n) => E ? s : n;
2070
+ var ee = u("◆", "*");
2071
+ var A2 = u("■", "x");
2072
+ var B = u("▲", "x");
2073
+ var S2 = u("◇", "o");
2074
+ var te = u("┌", "T");
2075
+ var a = u("│", "|");
2076
+ var m2 = u("└", "—");
2077
+ var j2 = u("●", ">");
2078
+ var R2 = u("○", " ");
2079
+ var V2 = u("◻", "[•]");
2080
+ var M2 = u("◼", "[+]");
2081
+ var G2 = u("◻", "[ ]");
2082
+ var se = u("▪", "•");
2083
+ var N2 = u("─", "-");
2084
+ var re = u("╮", "+");
2085
+ var ie = u("├", "+");
2086
+ var ne = u("╯", "+");
2087
+ var ae = u("●", "•");
2088
+ var oe = u("◆", "*");
2089
+ var ce = u("▲", "!");
2090
+ var le = u("■", "x");
2091
+ var y2 = (s) => {
2092
+ switch (s) {
2093
+ case "initial":
2094
+ case "active":
2095
+ return import_picocolors2.default.cyan(ee);
2096
+ case "cancel":
2097
+ return import_picocolors2.default.red(A2);
2098
+ case "error":
2099
+ return import_picocolors2.default.yellow(B);
2100
+ case "submit":
2101
+ return import_picocolors2.default.green(S2);
2019
2102
  }
2020
- const globalBin = findExecutablePath("engram");
2021
- if (globalBin) {
2022
- const engramToolDir2 = join7(toolsDir ?? join7(projectRoot, ".opencode", "tools"), "engram");
2023
- const engramBinDir2 = join7(engramToolDir2, "bin");
2024
- if (!existsSync6(engramBinDir2))
2025
- mkdirSync4(engramBinDir2, { recursive: true });
2026
- const localBin2 = join7(engramBinDir2, "engram" + (process.platform === "win32" ? ".exe" : ""));
2027
- if (!existsSync6(localBin2)) {
2028
- try {
2029
- unlinkSync3(localBin2);
2030
- } catch {}
2031
- try {
2032
- if (process.platform !== "win32") {
2033
- execSync3(`ln -s "${globalBin}" "${localBin2}"`, { stdio: "pipe" });
2034
- } else {
2035
- copyFileSync3(globalBin, localBin2);
2036
- }
2037
- } catch {}
2038
- }
2039
- setMcpEntry("engram", {
2040
- type: "local",
2041
- command: [`.opencode/tools/engram/bin/engram`, "mcp"],
2042
- enabled: true
2043
- });
2044
- const pluginSource2 = join7(projectRoot, "assets", "plugins", "engram.ts");
2045
- const pluginsDir2 = join7(projectRoot, ".opencode", "plugins");
2046
- const pluginTarget2 = join7(pluginsDir2, "engram.ts");
2047
- if (existsSync6(pluginSource2)) {
2048
- if (!existsSync6(pluginsDir2))
2049
- mkdirSync4(pluginsDir2, { recursive: true });
2050
- try {
2051
- copyFileSync3(pluginSource2, pluginTarget2);
2052
- } catch {}
2053
- }
2054
- return { success: true, message: `Engram global detectado en ${globalBin} — usando binario global. Plugin copiado a .opencode/plugins/` };
2103
+ };
2104
+ var k2 = (s) => {
2105
+ const { cursor: n, options: t, style: i } = s, r2 = s.maxItems ?? Number.POSITIVE_INFINITY, c2 = Math.max(process.stdout.rows - 4, 0), o = Math.min(c2, Math.max(r2, 5));
2106
+ let l2 = 0;
2107
+ n >= l2 + o - 3 ? l2 = Math.max(Math.min(n - o + 3, t.length - o), 0) : n < l2 + 2 && (l2 = Math.max(n - 2, 0));
2108
+ const $2 = o < t.length && l2 > 0, d2 = o < t.length && l2 + o < t.length;
2109
+ return t.slice(l2, l2 + o).map((w2, b2, C) => {
2110
+ const I2 = b2 === 0 && $2, x2 = b2 === C.length - 1 && d2;
2111
+ return I2 || x2 ? import_picocolors2.default.dim("...") : i(w2, b2 + l2 === n);
2112
+ });
2113
+ };
2114
+ var ue = (s) => new PD({ validate: s.validate, placeholder: s.placeholder, defaultValue: s.defaultValue, initialValue: s.initialValue, render() {
2115
+ const n = `${import_picocolors2.default.gray(a)}
2116
+ ${y2(this.state)} ${s.message}
2117
+ `, t = s.placeholder ? import_picocolors2.default.inverse(s.placeholder[0]) + import_picocolors2.default.dim(s.placeholder.slice(1)) : import_picocolors2.default.inverse(import_picocolors2.default.hidden("_")), i = this.value ? this.valueWithCursor : t;
2118
+ switch (this.state) {
2119
+ case "error":
2120
+ return `${n.trim()}
2121
+ ${import_picocolors2.default.yellow(a)} ${i}
2122
+ ${import_picocolors2.default.yellow(m2)} ${import_picocolors2.default.yellow(this.error)}
2123
+ `;
2124
+ case "submit":
2125
+ return `${n}${import_picocolors2.default.gray(a)} ${import_picocolors2.default.dim(this.value || s.placeholder)}`;
2126
+ case "cancel":
2127
+ return `${n}${import_picocolors2.default.gray(a)} ${import_picocolors2.default.strikethrough(import_picocolors2.default.dim(this.value ?? ""))}${this.value?.trim() ? `
2128
+ ${import_picocolors2.default.gray(a)}` : ""}`;
2129
+ default:
2130
+ return `${n}${import_picocolors2.default.cyan(a)} ${i}
2131
+ ${import_picocolors2.default.cyan(m2)}
2132
+ `;
2055
2133
  }
2056
- const engramToolDir = join7(toolsDir ?? join7(projectRoot, ".opencode", "tools"), "engram");
2057
- const engramBinDir = join7(engramToolDir, "bin");
2058
- if (!existsSync6(engramBinDir))
2059
- mkdirSync4(engramBinDir, { recursive: true });
2060
- const target = detectPlatformTarget();
2061
- if (!target) {
2062
- return {
2063
- success: false,
2064
- message: `Plataforma no soportada para descarga local: ${process.platform}/${process.arch}. Instalá Engram manualmente.`
2065
- };
2134
+ } }).prompt();
2135
+ var $e = (s) => new kD({ validate: s.validate, mask: s.mask ?? se, render() {
2136
+ const n = `${import_picocolors2.default.gray(a)}
2137
+ ${y2(this.state)} ${s.message}
2138
+ `, t = this.valueWithCursor, i = this.masked;
2139
+ switch (this.state) {
2140
+ case "error":
2141
+ return `${n.trim()}
2142
+ ${import_picocolors2.default.yellow(a)} ${i}
2143
+ ${import_picocolors2.default.yellow(m2)} ${import_picocolors2.default.yellow(this.error)}
2144
+ `;
2145
+ case "submit":
2146
+ return `${n}${import_picocolors2.default.gray(a)} ${import_picocolors2.default.dim(i)}`;
2147
+ case "cancel":
2148
+ return `${n}${import_picocolors2.default.gray(a)} ${import_picocolors2.default.strikethrough(import_picocolors2.default.dim(i ?? ""))}${i ? `
2149
+ ${import_picocolors2.default.gray(a)}` : ""}`;
2150
+ default:
2151
+ return `${n}${import_picocolors2.default.cyan(a)} ${t}
2152
+ ${import_picocolors2.default.cyan(m2)}
2153
+ `;
2066
2154
  }
2067
- const localBin = join7(engramBinDir, "engram" + (process.platform === "win32" ? ".exe" : ""));
2068
- if (existsSync6(localBin)) {
2069
- try {
2070
- execSync3(`"${localBin}" --version`, { stdio: "pipe", timeout: 1e4 });
2071
- } catch {
2072
- try {
2073
- unlinkSync3(localBin);
2074
- } catch {}
2155
+ } }).prompt();
2156
+ var me = (s) => {
2157
+ const n = s.active ?? "Yes", t = s.inactive ?? "No";
2158
+ return new fD({ active: n, inactive: t, initialValue: s.initialValue ?? true, render() {
2159
+ const i = `${import_picocolors2.default.gray(a)}
2160
+ ${y2(this.state)} ${s.message}
2161
+ `, r2 = this.value ? n : t;
2162
+ switch (this.state) {
2163
+ case "submit":
2164
+ return `${i}${import_picocolors2.default.gray(a)} ${import_picocolors2.default.dim(r2)}`;
2165
+ case "cancel":
2166
+ return `${i}${import_picocolors2.default.gray(a)} ${import_picocolors2.default.strikethrough(import_picocolors2.default.dim(r2))}
2167
+ ${import_picocolors2.default.gray(a)}`;
2168
+ default:
2169
+ return `${i}${import_picocolors2.default.cyan(a)} ${this.value ? `${import_picocolors2.default.green(j2)} ${n}` : `${import_picocolors2.default.dim(R2)} ${import_picocolors2.default.dim(n)}`} ${import_picocolors2.default.dim("/")} ${this.value ? `${import_picocolors2.default.dim(R2)} ${import_picocolors2.default.dim(t)}` : `${import_picocolors2.default.green(j2)} ${t}`}
2170
+ ${import_picocolors2.default.cyan(m2)}
2171
+ `;
2075
2172
  }
2076
- }
2077
- if (!existsSync6(localBin)) {
2078
- const tag = await fetchLatestReleaseTag("Gentleman-Programming/engram");
2079
- if (!tag) {
2080
- return {
2081
- success: false,
2082
- message: "No se pudo obtener la última versión de Engram desde GitHub."
2083
- };
2173
+ } }).prompt();
2174
+ };
2175
+ var de = (s) => {
2176
+ const n = (t, i) => {
2177
+ const r2 = t.label ?? String(t.value);
2178
+ switch (i) {
2179
+ case "selected":
2180
+ return `${import_picocolors2.default.dim(r2)}`;
2181
+ case "active":
2182
+ return `${import_picocolors2.default.green(j2)} ${r2} ${t.hint ? import_picocolors2.default.dim(`(${t.hint})`) : ""}`;
2183
+ case "cancelled":
2184
+ return `${import_picocolors2.default.strikethrough(import_picocolors2.default.dim(r2))}`;
2185
+ default:
2186
+ return `${import_picocolors2.default.dim(R2)} ${import_picocolors2.default.dim(r2)}`;
2084
2187
  }
2085
- const versionNum = tag.replace(/^v/, "");
2086
- const [os, cpu] = target.split("-");
2087
- const engramCpu = cpu === "x64" ? "amd64" : cpu;
2088
- const ext = process.platform === "win32" ? "zip" : "tar.gz";
2089
- const url = `https://github.com/Gentleman-Programming/engram/releases/download/${tag}/engram_${versionNum}_${os}_${engramCpu}.${ext}`;
2090
- try {
2091
- await downloadAndExtractWithRetry(url, engramToolDir, 0, 120000, 2);
2092
- } catch (e2) {
2093
- return {
2094
- success: false,
2095
- message: `Error descargando Engram ${tag}: ${e2.message}`
2096
- };
2188
+ };
2189
+ return new jD({ options: s.options, initialValue: s.initialValue, render() {
2190
+ const t = `${import_picocolors2.default.gray(a)}
2191
+ ${y2(this.state)} ${s.message}
2192
+ `;
2193
+ switch (this.state) {
2194
+ case "submit":
2195
+ return `${t}${import_picocolors2.default.gray(a)} ${n(this.options[this.cursor], "selected")}`;
2196
+ case "cancel":
2197
+ return `${t}${import_picocolors2.default.gray(a)} ${n(this.options[this.cursor], "cancelled")}
2198
+ ${import_picocolors2.default.gray(a)}`;
2199
+ default:
2200
+ return `${t}${import_picocolors2.default.cyan(a)} ${k2({ cursor: this.cursor, options: this.options, maxItems: s.maxItems, style: (i, r2) => n(i, r2 ? "active" : "inactive") }).join(`
2201
+ ${import_picocolors2.default.cyan(a)} `)}
2202
+ ${import_picocolors2.default.cyan(m2)}
2203
+ `;
2097
2204
  }
2098
- const extractedBin = join7(engramToolDir, "engram" + (process.platform === "win32" ? ".exe" : ""));
2099
- if (existsSync6(extractedBin) && extractedBin !== localBin) {
2100
- try {
2101
- copyFileSync3(extractedBin, localBin);
2102
- unlinkSync3(extractedBin);
2103
- } catch {}
2205
+ } }).prompt();
2206
+ };
2207
+ var he = (s) => {
2208
+ const n = (t, i = "inactive") => {
2209
+ const r2 = t.label ?? String(t.value);
2210
+ return i === "selected" ? `${import_picocolors2.default.dim(r2)}` : i === "cancelled" ? `${import_picocolors2.default.strikethrough(import_picocolors2.default.dim(r2))}` : i === "active" ? `${import_picocolors2.default.bgCyan(import_picocolors2.default.gray(` ${t.value} `))} ${r2} ${t.hint ? import_picocolors2.default.dim(`(${t.hint})`) : ""}` : `${import_picocolors2.default.gray(import_picocolors2.default.bgWhite(import_picocolors2.default.inverse(` ${t.value} `)))} ${r2} ${t.hint ? import_picocolors2.default.dim(`(${t.hint})`) : ""}`;
2211
+ };
2212
+ return new OD({ options: s.options, initialValue: s.initialValue, render() {
2213
+ const t = `${import_picocolors2.default.gray(a)}
2214
+ ${y2(this.state)} ${s.message}
2215
+ `;
2216
+ switch (this.state) {
2217
+ case "submit":
2218
+ return `${t}${import_picocolors2.default.gray(a)} ${n(this.options.find((i) => i.value === this.value) ?? s.options[0], "selected")}`;
2219
+ case "cancel":
2220
+ return `${t}${import_picocolors2.default.gray(a)} ${n(this.options[0], "cancelled")}
2221
+ ${import_picocolors2.default.gray(a)}`;
2222
+ default:
2223
+ return `${t}${import_picocolors2.default.cyan(a)} ${this.options.map((i, r2) => n(i, r2 === this.cursor ? "active" : "inactive")).join(`
2224
+ ${import_picocolors2.default.cyan(a)} `)}
2225
+ ${import_picocolors2.default.cyan(m2)}
2226
+ `;
2104
2227
  }
2105
- if (!existsSync6(localBin)) {
2106
- const found = findBinaryInDir(engramToolDir, "engram");
2107
- if (found && found !== localBin) {
2108
- try {
2109
- copyFileSync3(found, localBin);
2110
- if (process.platform !== "win32")
2111
- execSync3(`chmod +x "${localBin}"`, { stdio: "pipe" });
2112
- } catch {}
2228
+ } }).prompt();
2229
+ };
2230
+ var pe = (s) => {
2231
+ const n = (t, i) => {
2232
+ const r2 = t.label ?? String(t.value);
2233
+ return i === "active" ? `${import_picocolors2.default.cyan(V2)} ${r2} ${t.hint ? import_picocolors2.default.dim(`(${t.hint})`) : ""}` : i === "selected" ? `${import_picocolors2.default.green(M2)} ${import_picocolors2.default.dim(r2)}` : i === "cancelled" ? `${import_picocolors2.default.strikethrough(import_picocolors2.default.dim(r2))}` : i === "active-selected" ? `${import_picocolors2.default.green(M2)} ${r2} ${t.hint ? import_picocolors2.default.dim(`(${t.hint})`) : ""}` : i === "submitted" ? `${import_picocolors2.default.dim(r2)}` : `${import_picocolors2.default.dim(G2)} ${import_picocolors2.default.dim(r2)}`;
2234
+ };
2235
+ return new wD({ options: s.options, initialValues: s.initialValues, required: s.required ?? true, cursorAt: s.cursorAt, validate(t) {
2236
+ if (this.required && t.length === 0)
2237
+ return `Please select at least one option.
2238
+ ${import_picocolors2.default.reset(import_picocolors2.default.dim(`Press ${import_picocolors2.default.gray(import_picocolors2.default.bgWhite(import_picocolors2.default.inverse(" space ")))} to select, ${import_picocolors2.default.gray(import_picocolors2.default.bgWhite(import_picocolors2.default.inverse(" enter ")))} to submit`))}`;
2239
+ }, render() {
2240
+ const t = `${import_picocolors2.default.gray(a)}
2241
+ ${y2(this.state)} ${s.message}
2242
+ `, i = (r2, c2) => {
2243
+ const o = this.value.includes(r2.value);
2244
+ return c2 && o ? n(r2, "active-selected") : o ? n(r2, "selected") : n(r2, c2 ? "active" : "inactive");
2245
+ };
2246
+ switch (this.state) {
2247
+ case "submit":
2248
+ return `${t}${import_picocolors2.default.gray(a)} ${this.options.filter(({ value: r2 }) => this.value.includes(r2)).map((r2) => n(r2, "submitted")).join(import_picocolors2.default.dim(", ")) || import_picocolors2.default.dim("none")}`;
2249
+ case "cancel": {
2250
+ const r2 = this.options.filter(({ value: c2 }) => this.value.includes(c2)).map((c2) => n(c2, "cancelled")).join(import_picocolors2.default.dim(", "));
2251
+ return `${t}${import_picocolors2.default.gray(a)} ${r2.trim() ? `${r2}
2252
+ ${import_picocolors2.default.gray(a)}` : ""}`;
2113
2253
  }
2254
+ case "error": {
2255
+ const r2 = this.error.split(`
2256
+ `).map((c2, o) => o === 0 ? `${import_picocolors2.default.yellow(m2)} ${import_picocolors2.default.yellow(c2)}` : ` ${c2}`).join(`
2257
+ `);
2258
+ return `${t + import_picocolors2.default.yellow(a)} ${k2({ options: this.options, cursor: this.cursor, maxItems: s.maxItems, style: i }).join(`
2259
+ ${import_picocolors2.default.yellow(a)} `)}
2260
+ ${r2}
2261
+ `;
2262
+ }
2263
+ default:
2264
+ return `${t}${import_picocolors2.default.cyan(a)} ${k2({ options: this.options, cursor: this.cursor, maxItems: s.maxItems, style: i }).join(`
2265
+ ${import_picocolors2.default.cyan(a)} `)}
2266
+ ${import_picocolors2.default.cyan(m2)}
2267
+ `;
2114
2268
  }
2115
- if (!existsSync6(localBin)) {
2116
- return {
2117
- success: false,
2118
- message: `Descarga de Engram ${tag} completada pero no se encontró el binario en ${localBin}.`
2119
- };
2120
- }
2121
- if (process.platform !== "win32") {
2122
- try {
2123
- execSync3(`chmod +x "${localBin}"`, { stdio: "pipe" });
2124
- } catch {}
2125
- }
2126
- }
2127
- setMcpEntry("engram", {
2128
- type: "local",
2129
- command: [`.opencode/tools/engram/bin/engram`, "mcp"],
2130
- enabled: true
2131
- });
2132
- const pluginSource = join7(projectRoot, "assets", "plugins", "engram.ts");
2133
- const pluginsDir = join7(projectRoot, ".opencode", "plugins");
2134
- const pluginTarget = join7(pluginsDir, "engram.ts");
2135
- if (existsSync6(pluginSource)) {
2136
- if (!existsSync6(pluginsDir))
2137
- mkdirSync4(pluginsDir, { recursive: true });
2138
- try {
2139
- copyFileSync3(pluginSource, pluginTarget);
2140
- } catch {}
2141
- }
2142
- return { success: true, message: "Engram instalado localmente en .opencode/tools/engram/bin/ y configurado para OpenCode (MCP + plugin)" };
2143
- }
2144
- function setupContext7(toolsDir) {
2145
- const projectRoot = findProjectRoot();
2146
- const ctx7ToolDir = join7(toolsDir ?? join7(projectRoot, ".opencode", "tools"), "context7");
2147
- if (!existsSync6(ctx7ToolDir))
2148
- mkdirSync4(ctx7ToolDir, { recursive: true });
2149
- ensureMcpEntry("context7", {
2150
- type: "remote",
2151
- url: "https://mcp.context7.com/mcp",
2152
- enabled: true
2153
- });
2154
- const npxCmd = isCommandAvailable("bun") ? "bunx" : "npx --yes";
2155
- try {
2156
- execSync3(`${npxCmd} ctx7 setup --opencode`, {
2157
- stdio: "pipe",
2158
- timeout: 60000
2159
- });
2160
- return { success: true, message: "Context7 configurado (MCP + skill instalado)" };
2161
- } catch {
2162
- return {
2163
- success: true,
2164
- message: "Context7 MCP registrado (skill opcional no instalada — corrí `npx ctx7 setup --opencode` manualmente si la querés)"
2165
- };
2166
- }
2167
- }
2168
- async function installStack(toolsDir) {
2169
- return {
2170
- codegraph: await installCodeGraph(toolsDir),
2171
- openspec: setupOpenSpec(),
2172
- engram: await installEngram(toolsDir),
2173
- context7: setupContext7(toolsDir),
2174
- config: patchOpenCodeConfig()
2269
+ } }).prompt();
2270
+ };
2271
+ var ge = (s) => {
2272
+ const n = (t, i, r2 = []) => {
2273
+ const c2 = t.label ?? String(t.value), o = typeof t.group == "string", l2 = o && (r2[r2.indexOf(t) + 1] ?? { group: true }), $2 = o && l2.group === true, d2 = o ? `${$2 ? m2 : a} ` : "";
2274
+ return i === "active" ? `${import_picocolors2.default.dim(d2)}${import_picocolors2.default.cyan(V2)} ${c2} ${t.hint ? import_picocolors2.default.dim(`(${t.hint})`) : ""}` : i === "group-active" ? `${d2}${import_picocolors2.default.cyan(V2)} ${import_picocolors2.default.dim(c2)}` : i === "group-active-selected" ? `${d2}${import_picocolors2.default.green(M2)} ${import_picocolors2.default.dim(c2)}` : i === "selected" ? `${import_picocolors2.default.dim(d2)}${import_picocolors2.default.green(M2)} ${import_picocolors2.default.dim(c2)}` : i === "cancelled" ? `${import_picocolors2.default.strikethrough(import_picocolors2.default.dim(c2))}` : i === "active-selected" ? `${import_picocolors2.default.dim(d2)}${import_picocolors2.default.green(M2)} ${c2} ${t.hint ? import_picocolors2.default.dim(`(${t.hint})`) : ""}` : i === "submitted" ? `${import_picocolors2.default.dim(c2)}` : `${import_picocolors2.default.dim(d2)}${import_picocolors2.default.dim(G2)} ${import_picocolors2.default.dim(c2)}`;
2175
2275
  };
2176
- }
2177
- function uninstallEngramConfig() {
2178
- const projectRoot = findProjectRoot();
2179
- const configPath = findOpenCodeConfig(projectRoot);
2180
- if (!configPath) {
2181
- return { success: false, message: "No se encontró opencode.json ni opencode.jsonc" };
2182
- }
2183
- const config = readOpenCodeConfig(configPath);
2184
- if (!config) {
2185
- return { success: false, message: `Error parseando ${configPath}` };
2186
- }
2187
- const mcp = config.mcp;
2188
- if (mcp && "engram" in mcp) {
2189
- delete mcp.engram;
2190
- if (Object.keys(mcp).length === 0) {
2191
- delete config.mcp;
2192
- }
2193
- writeOpenCodeConfig(configPath, config);
2194
- return { success: true, message: "Config de Engram eliminada de opencode.json" };
2195
- }
2196
- return { success: true, message: "Engram no estaba configurado en este proyecto" };
2197
- }
2198
- function uninstallStackConfig(paths) {
2199
- const projectRoot = findProjectRoot();
2200
- const removed = [];
2201
- const configPath = findOpenCodeConfig(projectRoot);
2202
- if (configPath) {
2203
- const config = readOpenCodeConfig(configPath);
2204
- if (config) {
2205
- const mcp = config.mcp;
2206
- let changed = false;
2207
- if (mcp) {
2208
- for (const name of ["codegraph", "context7", "engram"]) {
2209
- if (name in mcp) {
2210
- delete mcp[name];
2211
- removed.push(`mcp.${name}`);
2212
- changed = true;
2213
- }
2214
- }
2215
- if (Object.keys(mcp).length === 0) {
2216
- delete config.mcp;
2217
- changed = true;
2218
- }
2276
+ return new dD({ options: s.options, initialValues: s.initialValues, required: s.required ?? true, cursorAt: s.cursorAt, validate(t) {
2277
+ if (this.required && t.length === 0)
2278
+ return `Please select at least one option.
2279
+ ${import_picocolors2.default.reset(import_picocolors2.default.dim(`Press ${import_picocolors2.default.gray(import_picocolors2.default.bgWhite(import_picocolors2.default.inverse(" space ")))} to select, ${import_picocolors2.default.gray(import_picocolors2.default.bgWhite(import_picocolors2.default.inverse(" enter ")))} to submit`))}`;
2280
+ }, render() {
2281
+ const t = `${import_picocolors2.default.gray(a)}
2282
+ ${y2(this.state)} ${s.message}
2283
+ `;
2284
+ switch (this.state) {
2285
+ case "submit":
2286
+ return `${t}${import_picocolors2.default.gray(a)} ${this.options.filter(({ value: i }) => this.value.includes(i)).map((i) => n(i, "submitted")).join(import_picocolors2.default.dim(", "))}`;
2287
+ case "cancel": {
2288
+ const i = this.options.filter(({ value: r2 }) => this.value.includes(r2)).map((r2) => n(r2, "cancelled")).join(import_picocolors2.default.dim(", "));
2289
+ return `${t}${import_picocolors2.default.gray(a)} ${i.trim() ? `${i}
2290
+ ${import_picocolors2.default.gray(a)}` : ""}`;
2219
2291
  }
2220
- if (changed) {
2221
- writeOpenCodeConfig(configPath, config);
2292
+ case "error": {
2293
+ const i = this.error.split(`
2294
+ `).map((r2, c2) => c2 === 0 ? `${import_picocolors2.default.yellow(m2)} ${import_picocolors2.default.yellow(r2)}` : ` ${r2}`).join(`
2295
+ `);
2296
+ return `${t}${import_picocolors2.default.yellow(a)} ${this.options.map((r2, c2, o) => {
2297
+ const l2 = this.value.includes(r2.value) || r2.group === true && this.isGroupSelected(`${r2.value}`), $2 = c2 === this.cursor;
2298
+ return !$2 && typeof r2.group == "string" && this.options[this.cursor].value === r2.group ? n(r2, l2 ? "group-active-selected" : "group-active", o) : $2 && l2 ? n(r2, "active-selected", o) : l2 ? n(r2, "selected", o) : n(r2, $2 ? "active" : "inactive", o);
2299
+ }).join(`
2300
+ ${import_picocolors2.default.yellow(a)} `)}
2301
+ ${i}
2302
+ `;
2222
2303
  }
2304
+ default:
2305
+ return `${t}${import_picocolors2.default.cyan(a)} ${this.options.map((i, r2, c2) => {
2306
+ const o = this.value.includes(i.value) || i.group === true && this.isGroupSelected(`${i.value}`), l2 = r2 === this.cursor;
2307
+ return !l2 && typeof i.group == "string" && this.options[this.cursor].value === i.group ? n(i, o ? "group-active-selected" : "group-active", c2) : l2 && o ? n(i, "active-selected", c2) : o ? n(i, "selected", c2) : n(i, l2 ? "active" : "inactive", c2);
2308
+ }).join(`
2309
+ ${import_picocolors2.default.cyan(a)} `)}
2310
+ ${import_picocolors2.default.cyan(m2)}
2311
+ `;
2223
2312
  }
2313
+ } }).prompt();
2314
+ };
2315
+ var ye = (s = "", n = "") => {
2316
+ const t = `
2317
+ ${s}
2318
+ `.split(`
2319
+ `), i = T2(n).length, r2 = Math.max(t.reduce((o, l2) => {
2320
+ const $2 = T2(l2);
2321
+ return $2.length > o ? $2.length : o;
2322
+ }, 0), i) + 2, c2 = t.map((o) => `${import_picocolors2.default.gray(a)} ${import_picocolors2.default.dim(o)}${" ".repeat(r2 - T2(o).length)}${import_picocolors2.default.gray(a)}`).join(`
2323
+ `);
2324
+ process.stdout.write(`${import_picocolors2.default.gray(a)}
2325
+ ${import_picocolors2.default.green(S2)} ${import_picocolors2.default.reset(n)} ${import_picocolors2.default.gray(N2.repeat(Math.max(r2 - i - 1, 1)) + re)}
2326
+ ${c2}
2327
+ ${import_picocolors2.default.gray(ie + N2.repeat(r2 + 2) + ne)}
2328
+ `);
2329
+ };
2330
+ var ve = (s = "") => {
2331
+ process.stdout.write(`${import_picocolors2.default.gray(m2)} ${import_picocolors2.default.red(s)}
2332
+
2333
+ `);
2334
+ };
2335
+ var we = (s = "") => {
2336
+ process.stdout.write(`${import_picocolors2.default.gray(te)} ${s}
2337
+ `);
2338
+ };
2339
+ var fe = (s = "") => {
2340
+ process.stdout.write(`${import_picocolors2.default.gray(a)}
2341
+ ${import_picocolors2.default.gray(m2)} ${s}
2342
+
2343
+ `);
2344
+ };
2345
+ var v2 = { message: (s = "", { symbol: n = import_picocolors2.default.gray(a) } = {}) => {
2346
+ const t = [`${import_picocolors2.default.gray(a)}`];
2347
+ if (s) {
2348
+ const [i, ...r2] = s.split(`
2349
+ `);
2350
+ t.push(`${n} ${i}`, ...r2.map((c2) => `${import_picocolors2.default.gray(a)} ${c2}`));
2224
2351
  }
2225
- const codegraphDir = join7(projectRoot, ".codegraph");
2226
- if (existsSync6(codegraphDir)) {
2227
- try {
2228
- rmSync3(codegraphDir, { recursive: true, force: true });
2229
- removed.push(".codegraph/");
2230
- } catch {}
2231
- }
2232
- if (existsSync6(paths.tools)) {
2233
- try {
2234
- rmSync3(paths.tools, { recursive: true, force: true });
2235
- removed.push(".opencode/tools/");
2236
- } catch {}
2237
- }
2238
- if (removed.length === 0) {
2239
- return { success: true, message: "No había configuración del stack para remover" };
2240
- }
2241
- return {
2242
- success: true,
2243
- message: `Removido: ${removed.join(", ")}. Los binarios globales (codegraph, engram) no se tocaron.`
2352
+ process.stdout.write(`${t.join(`
2353
+ `)}
2354
+ `);
2355
+ }, info: (s) => {
2356
+ v2.message(s, { symbol: import_picocolors2.default.blue(ae) });
2357
+ }, success: (s) => {
2358
+ v2.message(s, { symbol: import_picocolors2.default.green(oe) });
2359
+ }, step: (s) => {
2360
+ v2.message(s, { symbol: import_picocolors2.default.green(S2) });
2361
+ }, warn: (s) => {
2362
+ v2.message(s, { symbol: import_picocolors2.default.yellow(ce) });
2363
+ }, warning: (s) => {
2364
+ v2.warn(s);
2365
+ }, error: (s) => {
2366
+ v2.message(s, { symbol: import_picocolors2.default.red(le) });
2367
+ } };
2368
+ var L2 = () => {
2369
+ const s = E ? ["◒", "◐", "◓", "◑"] : ["•", "o", "O", "0"], n = E ? 80 : 120, t = process.env.CI === "true";
2370
+ let i, r2, c2 = false, o = "", l2;
2371
+ const $2 = (h2) => {
2372
+ const g2 = h2 > 1 ? "Something went wrong" : "Canceled";
2373
+ c2 && P2(g2, h2);
2374
+ }, d2 = () => $2(2), w2 = () => $2(1), b2 = () => {
2375
+ process.on("uncaughtExceptionMonitor", d2), process.on("unhandledRejection", d2), process.on("SIGINT", w2), process.on("SIGTERM", w2), process.on("exit", $2);
2376
+ }, C = () => {
2377
+ process.removeListener("uncaughtExceptionMonitor", d2), process.removeListener("unhandledRejection", d2), process.removeListener("SIGINT", w2), process.removeListener("SIGTERM", w2), process.removeListener("exit", $2);
2378
+ }, I2 = () => {
2379
+ if (l2 === undefined)
2380
+ return;
2381
+ t && process.stdout.write(`
2382
+ `);
2383
+ const h2 = l2.split(`
2384
+ `);
2385
+ process.stdout.write(import_sisteransi2.cursor.move(-999, h2.length - 1)), process.stdout.write(import_sisteransi2.erase.down(h2.length));
2386
+ }, x2 = (h2) => h2.replace(/\.+$/, ""), O2 = (h2 = "") => {
2387
+ c2 = true, i = cD(), o = x2(h2), process.stdout.write(`${import_picocolors2.default.gray(a)}
2388
+ `);
2389
+ let g2 = 0, f2 = 0;
2390
+ b2(), r2 = setInterval(() => {
2391
+ if (t && o === l2)
2392
+ return;
2393
+ I2(), l2 = o;
2394
+ const W2 = import_picocolors2.default.magenta(s[g2]), _2 = t ? "..." : ".".repeat(Math.floor(f2)).slice(0, 3);
2395
+ process.stdout.write(`${W2} ${o}${_2}`), g2 = g2 + 1 < s.length ? g2 + 1 : 0, f2 = f2 < s.length ? f2 + 0.125 : 0;
2396
+ }, n);
2397
+ }, P2 = (h2 = "", g2 = 0) => {
2398
+ c2 = false, clearInterval(r2), I2();
2399
+ const f2 = g2 === 0 ? import_picocolors2.default.green(S2) : g2 === 1 ? import_picocolors2.default.red(A2) : import_picocolors2.default.red(B);
2400
+ o = x2(h2 ?? o), process.stdout.write(`${f2} ${o}
2401
+ `), C(), i();
2244
2402
  };
2245
- }
2246
- function verifyMcpServers(projectRoot) {
2247
- const opencodeDir = findOpenCodeDir(projectRoot);
2248
- const mcpBase = opencodeDir ? join7(opencodeDir, "mcp") : join7(projectRoot, ".opencode", "mcp");
2249
- const controllerPath = join7(mcpBase, "ostacky-controller", "index.js");
2250
- const openspecPath = join7(mcpBase, "openspec", "index.js");
2251
- const result = {
2252
- ostackyController: {
2253
- exists: existsSync6(controllerPath),
2254
- path: controllerPath
2255
- },
2256
- openspec: {
2257
- exists: existsSync6(openspecPath),
2258
- path: openspecPath
2403
+ return { start: O2, stop: P2, message: (h2 = "") => {
2404
+ o = x2(h2 ?? o);
2405
+ } };
2406
+ };
2407
+ var be = async (s, n) => {
2408
+ const t = {}, i = Object.keys(s);
2409
+ for (const r2 of i) {
2410
+ const c2 = s[r2], o = await c2({ results: t })?.catch((l2) => {
2411
+ throw l2;
2412
+ });
2413
+ if (typeof n?.onCancel == "function" && BD(o)) {
2414
+ t[r2] = "canceled", n.onCancel({ results: t });
2415
+ continue;
2259
2416
  }
2260
- };
2261
- if (!result.ostackyController.exists) {
2262
- result.ostackyController.error = "ostacky-controller MCP server not found";
2263
- }
2264
- if (!result.openspec.exists) {
2265
- result.openspec.error = "openspec MCP server not found";
2417
+ t[r2] = o;
2266
2418
  }
2267
- return result;
2268
- }
2269
- var init_stack = __esm(() => {
2270
- init_fs();
2271
- init_config();
2272
- init_github();
2273
- });
2274
- // package.json
2275
- var package_default = {
2276
- name: "ostacky",
2277
- version: "0.6.1",
2278
- description: "Instalador interactivo de agentes y comandos para OpenCode",
2279
- type: "module",
2280
- bin: {
2281
- ostacky: "./dist/cli.js"
2282
- },
2283
- scripts: {
2284
- prebuild: "bun run scripts/sync-version.ts",
2285
- dev: "bun run src/cli.ts",
2286
- build: "bun build src/cli.ts --target=node --format=esm --outfile dist/cli.js && bun scripts/add-shebang.ts",
2287
- start: "node dist/cli.js",
2288
- test: "bun test",
2289
- "check:skills": "bun run scripts/check-skill-sync.ts",
2290
- "check:skills:fix": "bun run scripts/check-skill-sync.ts --fix",
2291
- "hash:check": "bun run scripts/update-manifest-hashes.ts --check",
2292
- "hash:update": "bun run scripts/update-manifest-hashes.ts",
2293
- prepublishOnly: "bun run build"
2294
- },
2295
- files: [
2296
- "dist/",
2297
- "assets/",
2298
- "manifest.json",
2299
- "LICENSE"
2300
- ],
2301
- keywords: [
2302
- "opencode",
2303
- "installer",
2304
- "cli",
2305
- "agent"
2306
- ],
2307
- license: "MIT",
2308
- dependencies: {
2309
- "@clack/prompts": "^0.9.0"
2310
- },
2311
- devDependencies: {
2312
- "@types/bun": "latest",
2313
- typescript: "^5.0.0"
2314
- },
2315
- publishConfig: {
2316
- access: "public"
2317
- },
2318
- engines: {
2319
- node: ">=20.0.0"
2419
+ return t;
2420
+ };
2421
+ var xe = async (s) => {
2422
+ for (const n of s) {
2423
+ if (n.enabled === false)
2424
+ continue;
2425
+ const t = L2();
2426
+ t.start(n.title);
2427
+ const i = await n.task(t.message);
2428
+ t.stop(i || n.title);
2320
2429
  }
2321
2430
  };
2322
2431
 
2323
2432
  // src/prompts/index.ts
2324
- init_dist2();
2325
2433
  init_fs();
2434
+ import { dirname as dirname7 } from "path";
2326
2435
 
2327
2436
  // src/prompts/helpers.ts
2328
- init_dist2();
2329
2437
  init_github();
2330
2438
  init_fs();
2331
2439
  init_lockfile();
@@ -2345,10 +2453,166 @@ import {
2345
2453
  statSync as statSync2,
2346
2454
  copyFileSync as copyFileSync2,
2347
2455
  readFileSync as readFileSync5,
2348
- rmSync as rmSync2
2456
+ rmSync as rmSync3
2349
2457
  } from "fs";
2350
- import { execSync as execSync2 } from "child_process";
2351
- import { join as join6 } from "path";
2458
+ import { execFileSync as execFileSync2, spawn } from "child_process";
2459
+ import { dirname as dirname4, join as join6 } from "path";
2460
+ import { pathToFileURL } from "url";
2461
+ function createMcpConfigEntry(name, nodeExecutable, serverPath, statePath) {
2462
+ const entry = {
2463
+ type: "local",
2464
+ command: [nodeExecutable, serverPath],
2465
+ enabled: true
2466
+ };
2467
+ if (name === "ostacky-controller" && statePath) {
2468
+ entry.environment = { OSTACKY_STATE_PATH: statePath };
2469
+ }
2470
+ return entry;
2471
+ }
2472
+ function getVerifiedNodeExecutable() {
2473
+ const nodeExecutable = findExecutablePath("node");
2474
+ if (!nodeExecutable) {
2475
+ throw new Error("No se encontró Node.js en PATH; no se puede iniciar un MCP local.");
2476
+ }
2477
+ try {
2478
+ execFileSync2(nodeExecutable, ["--version"], { stdio: "pipe", timeout: 1e4 });
2479
+ } catch (error) {
2480
+ throw new Error(`Node.js no se puede ejecutar desde ${nodeExecutable}: ${error.message}`);
2481
+ }
2482
+ return nodeExecutable;
2483
+ }
2484
+ function validateMcpModule(nodeExecutable, serverPath, cwd) {
2485
+ try {
2486
+ execFileSync2(nodeExecutable, ["--input-type=module", "--eval", "await import(process.env.OSTACKY_MCP_PROBE)"], {
2487
+ cwd,
2488
+ env: { ...process.env, OSTACKY_MCP_PROBE: pathToFileURL(serverPath).href },
2489
+ stdio: "pipe",
2490
+ timeout: 15000
2491
+ });
2492
+ } catch (error) {
2493
+ throw new Error(`El MCP no pasó la validación de carga: ${error.message}`);
2494
+ }
2495
+ }
2496
+ async function probeMcpServer(nodeExecutable, serverPath, cwd, statePath) {
2497
+ try {
2498
+ await new Promise((resolve2, reject) => {
2499
+ const child = spawn(nodeExecutable, [serverPath], {
2500
+ cwd,
2501
+ env: {
2502
+ ...process.env,
2503
+ ...statePath ? { OSTACKY_STATE_PATH: statePath } : {}
2504
+ },
2505
+ stdio: ["pipe", "pipe", "pipe"],
2506
+ windowsHide: true
2507
+ });
2508
+ let settled = false;
2509
+ let stderr = "";
2510
+ let stdoutBuffer = "";
2511
+ const requestTimeout = 1e4;
2512
+ const finish = (error) => {
2513
+ if (settled)
2514
+ return;
2515
+ settled = true;
2516
+ clearTimeout(timer);
2517
+ try {
2518
+ child.stdin?.end();
2519
+ } catch {}
2520
+ if (child.exitCode === null)
2521
+ child.kill();
2522
+ error ? reject(error) : resolve2();
2523
+ };
2524
+ const fail = (message) => finish(new Error(`${message}${stderr ? `: ${stderr.trim()}` : ""}`));
2525
+ const send = (message) => {
2526
+ try {
2527
+ child.stdin?.write(JSON.stringify(message) + `
2528
+ `);
2529
+ } catch (error) {
2530
+ finish(error);
2531
+ }
2532
+ };
2533
+ const timer = setTimeout(() => fail("El MCP no completó el health check a tiempo"), requestTimeout);
2534
+ child.once("error", (error) => finish(error));
2535
+ child.stderr?.on("data", (chunk) => {
2536
+ stderr += chunk.toString();
2537
+ });
2538
+ child.once("exit", (code, signal) => {
2539
+ fail(`El MCP terminó durante el health check (código ${code ?? "null"}, señal ${signal ?? "ninguna"})`);
2540
+ });
2541
+ child.stdout?.on("data", (chunk) => {
2542
+ stdoutBuffer += chunk.toString();
2543
+ const lines = stdoutBuffer.split(/\r?\n/);
2544
+ stdoutBuffer = lines.pop() ?? "";
2545
+ for (const line of lines) {
2546
+ if (!line.trim())
2547
+ continue;
2548
+ let message;
2549
+ try {
2550
+ message = JSON.parse(line);
2551
+ } catch {
2552
+ continue;
2553
+ }
2554
+ if (message.error) {
2555
+ fail(`El MCP respondió un error: ${message.error.message ?? "desconocido"}`);
2556
+ return;
2557
+ }
2558
+ if (message.id === 1) {
2559
+ send({ jsonrpc: "2.0", method: "notifications/initialized" });
2560
+ send({ jsonrpc: "2.0", id: 2, method: "tools/list", params: {} });
2561
+ continue;
2562
+ }
2563
+ if (message.id === 2) {
2564
+ const tools = message.result?.tools ?? [];
2565
+ if (!tools.some((tool) => tool.name === "ping") || !tools.some((tool) => tool.name === "start_request")) {
2566
+ fail("El MCP inició pero no expuso las tools requeridas");
2567
+ return;
2568
+ }
2569
+ send({
2570
+ jsonrpc: "2.0",
2571
+ id: 3,
2572
+ method: "tools/call",
2573
+ params: { name: "start_request", arguments: { requestId: "installer-probe" } }
2574
+ });
2575
+ continue;
2576
+ }
2577
+ if (message.id === 3) {
2578
+ const result = message.result;
2579
+ if (result?.isError) {
2580
+ fail("La tool start_request falló durante el health check");
2581
+ return;
2582
+ }
2583
+ finish();
2584
+ }
2585
+ }
2586
+ });
2587
+ send({
2588
+ jsonrpc: "2.0",
2589
+ id: 1,
2590
+ method: "initialize",
2591
+ params: {
2592
+ protocolVersion: "2025-03-26",
2593
+ capabilities: {},
2594
+ clientInfo: { name: "ostacky-installer", version: "0.6.2" }
2595
+ }
2596
+ });
2597
+ });
2598
+ } finally {
2599
+ if (statePath && existsSync5(statePath))
2600
+ rmSync3(statePath, { force: true });
2601
+ if (statePath && existsSync5(statePath + ".backup"))
2602
+ rmSync3(statePath + ".backup", { force: true });
2603
+ }
2604
+ }
2605
+ function takeFileSnapshot(path) {
2606
+ return { path, content: existsSync5(path) ? readFileSync5(path, "utf-8") : null };
2607
+ }
2608
+ function restoreFileSnapshot(snapshot) {
2609
+ if (snapshot.content === null) {
2610
+ if (existsSync5(snapshot.path))
2611
+ rmSync3(snapshot.path, { force: true });
2612
+ return;
2613
+ }
2614
+ writeFileSync5(snapshot.path, snapshot.content, "utf-8");
2615
+ }
2352
2616
  function upsertLockfile(paths, type, item, manifest, contentHash) {
2353
2617
  const existing = readLockfile(paths.root) ?? {
2354
2618
  version: manifest.version,
@@ -2422,7 +2686,7 @@ async function installSkill(item, manifest, paths) {
2422
2686
  }
2423
2687
  const dest = join6(paths.skills, item.name);
2424
2688
  if (existsSync5(dest)) {
2425
- rmSync2(dest, { recursive: true, force: true });
2689
+ rmSync3(dest, { recursive: true, force: true });
2426
2690
  }
2427
2691
  copyDirRecursive(src, dest);
2428
2692
  upsertLockfile(paths, "skills", item, manifest, treeHash);
@@ -2438,36 +2702,67 @@ async function installMcpServer(item, manifest, paths) {
2438
2702
  ` + ` esperado: ${item.sha256}
2439
2703
  ` + ` recibido: ${treeHash}`);
2440
2704
  }
2705
+ const nodeExecutable = getVerifiedNodeExecutable();
2706
+ const projectRoot = dirname4(paths.root);
2441
2707
  const dest = join6(paths.mcp, item.name);
2442
- if (existsSync5(dest)) {
2443
- rmSync2(dest, { recursive: true, force: true });
2444
- }
2445
- mkdirSync3(dest, { recursive: true });
2446
- const bundledPath = join6(PACKAGE_ROOT, "dist", "mcp", item.name, "index.js");
2447
- if (existsSync5(bundledPath)) {
2448
- copyFileSync2(bundledPath, join6(dest, "index.js"));
2449
- } else {
2450
- copyDirRecursive(src, dest, true);
2451
- const installCmd = isCommandAvailable("bun") ? "bun install --no-save" : "npm install --no-audit --no-fund";
2708
+ const staging = `${dest}.staging-${process.pid}-${Date.now()}`;
2709
+ const statePath = item.name === "ostacky-controller" ? join6(paths.root, "ostacky-state.json") : undefined;
2710
+ try {
2711
+ mkdirSync3(staging, { recursive: true });
2712
+ const bundledPath = join6(PACKAGE_ROOT, "dist", "mcp", item.name, "index.js");
2713
+ if (existsSync5(bundledPath)) {
2714
+ copyFileSync2(bundledPath, join6(staging, "index.js"));
2715
+ writeFileSync5(join6(staging, "package.json"), JSON.stringify({ type: "module" }) + `
2716
+ `, "utf-8");
2717
+ } else {
2718
+ copyDirRecursive(src, staging, true);
2719
+ const useBun = isCommandAvailable("bun");
2720
+ const packageManager = useBun ? "bun" : "npm";
2721
+ if (!useBun && !isCommandAvailable("npm")) {
2722
+ throw new Error(`No se encontró Bun ni npm para instalar dependencias de ${item.name}.`);
2723
+ }
2724
+ const args = useBun ? ["install", "--no-save"] : ["install", "--no-audit", "--no-fund"];
2725
+ try {
2726
+ const invocation = getCommandInvocation(packageManager, args);
2727
+ execFileSync2(invocation.command, invocation.args, {
2728
+ cwd: staging,
2729
+ stdio: "pipe",
2730
+ timeout: 60000
2731
+ });
2732
+ } catch (error) {
2733
+ throw new Error(`No se pudieron instalar dependencias de ${item.name} con ${packageManager}: ${error.message}`);
2734
+ }
2735
+ }
2736
+ const stagedServerPath = join6(staging, "index.js");
2737
+ if (!existsSync5(stagedServerPath)) {
2738
+ throw new Error(`El MCP ${item.name} no contiene index.js después de instalarse.`);
2739
+ }
2740
+ validateMcpModule(nodeExecutable, stagedServerPath, staging);
2741
+ await probeMcpServer(nodeExecutable, stagedServerPath, staging, item.name === "ostacky-controller" ? join6(staging, ".probe-state.json") : undefined);
2742
+ const configPath = findOpenCodeConfig(projectRoot) ?? join6(projectRoot, "opencode.json");
2743
+ const configSnapshot = takeFileSnapshot(configPath);
2744
+ const lockfileSnapshot = takeFileSnapshot(getLockfilePath(paths.root));
2745
+ const promotion = promoteStagedDirectory(staging, dest);
2452
2746
  try {
2453
- const output = execSync2(installCmd, {
2454
- cwd: dest,
2455
- encoding: "utf-8",
2456
- timeout: 60000
2457
- });
2458
- if (output)
2459
- console.error(output);
2460
- } catch (e2) {
2461
- console.error(`[WARN] MCP server "${item.name}" copiado pero ${installCmd} falló: ${e2.message}.
2462
- ` + ` Resolvé las dependencias manualmente: cd .opencode/mcp/${item.name} && bun install`);
2747
+ setMcpEntryAtProjectRoot(projectRoot, item.name, createMcpConfigEntry(item.name, nodeExecutable, join6(dest, "index.js"), statePath));
2748
+ upsertLockfile(paths, "mcpServers", item, manifest, treeHash);
2749
+ promotion.commit();
2750
+ } catch (error) {
2751
+ try {
2752
+ restoreFileSnapshot(configSnapshot);
2753
+ } catch {}
2754
+ try {
2755
+ restoreFileSnapshot(lockfileSnapshot);
2756
+ } catch {}
2757
+ try {
2758
+ promotion.rollback();
2759
+ } catch {}
2760
+ throw error;
2463
2761
  }
2762
+ } finally {
2763
+ if (existsSync5(staging))
2764
+ rmSync3(staging, { recursive: true, force: true });
2464
2765
  }
2465
- upsertLockfile(paths, "mcpServers", item, manifest, treeHash);
2466
- ensureMcpEntry(item.name, {
2467
- type: "local",
2468
- command: ["node", `.opencode/mcp/${item.name}/index.js`],
2469
- enabled: true
2470
- });
2471
2766
  }
2472
2767
  function isMcpServerInstalled(name, paths) {
2473
2768
  return existsSync5(join6(paths.mcp, name, "index.js"));
@@ -2509,7 +2804,7 @@ function uninstallSkill(name, paths) {
2509
2804
  const dirPath = join6(paths.skills, name);
2510
2805
  try {
2511
2806
  if (existsSync5(dirPath)) {
2512
- rmSync2(dirPath, { recursive: true, force: true });
2807
+ rmSync3(dirPath, { recursive: true, force: true });
2513
2808
  }
2514
2809
  } catch {
2515
2810
  return false;
@@ -2521,12 +2816,12 @@ function uninstallMcpServer(name, paths) {
2521
2816
  const dirPath = join6(paths.mcp, name);
2522
2817
  try {
2523
2818
  if (existsSync5(dirPath)) {
2524
- rmSync2(dirPath, { recursive: true, force: true });
2819
+ rmSync3(dirPath, { recursive: true, force: true });
2525
2820
  }
2526
2821
  } catch {
2527
2822
  return false;
2528
2823
  }
2529
- const projectRoot = findProjectRoot();
2824
+ const projectRoot = dirname4(paths.root);
2530
2825
  const configPath = findOpenCodeConfig(projectRoot);
2531
2826
  if (configPath) {
2532
2827
  const config = readOpenCodeConfig(configPath);
@@ -2598,7 +2893,7 @@ async function loadLatestManifest() {
2598
2893
  }
2599
2894
  function printPostInstallSteps() {
2600
2895
  ye([
2601
- "Iniciá OpenCode (si no está corriendo):",
2896
+ "Cerrá y reiniciá OpenCode si ya estaba corriendo (los MCP no recargan su config en caliente):",
2602
2897
  " TUI → opencode",
2603
2898
  " Web → opencode web --port 4096",
2604
2899
  "Escribí @Ostacky en el chat (TUI o web) para invocar al agente",
@@ -2701,21 +2996,21 @@ function kindLabel(type) {
2701
2996
  }
2702
2997
 
2703
2998
  // src/prompts/install.ts
2704
- init_dist2();
2705
- import { join as join8 } from "path";
2999
+ import { dirname as dirname6, join as join8 } from "path";
2706
3000
  import { existsSync as existsSync7 } from "fs";
2707
3001
  init_stack();
2708
3002
  init_fs();
2709
- async function doInstallStack(toolsDir) {
3003
+ async function doInstallStack(toolsDir, projectRoot) {
2710
3004
  const spin = L2();
2711
3005
  let allOk = true;
3006
+ const resolvedProjectRoot = projectRoot ?? dirname6(dirname6(toolsDir ?? join8(process.cwd(), ".opencode", "tools")));
2712
3007
  spin.start("Instalando CodeGraph...");
2713
3008
  const cg = await installCodeGraph(toolsDir);
2714
3009
  spin.stop(cg.success ? `✓ ${cg.message}` : `✗ ${cg.message}`);
2715
3010
  if (!cg.success)
2716
3011
  allOk = false;
2717
3012
  spin.start("Configurando OpenSpec...");
2718
- const os = setupOpenSpec();
3013
+ const os = setupOpenSpec(resolvedProjectRoot);
2719
3014
  spin.stop(os.success ? `✓ ${os.message}` : `✗ ${os.message}`);
2720
3015
  if (!os.success)
2721
3016
  allOk = false;
@@ -2731,13 +3026,14 @@ async function doInstallStack(toolsDir) {
2731
3026
  allOk = false;
2732
3027
  spin.start("Verificando configuración...");
2733
3028
  const { patchOpenCodeConfig: patchOpenCodeConfig2 } = await Promise.resolve().then(() => (init_config(), exports_config));
2734
- const cfg = patchOpenCodeConfig2();
3029
+ const cfg = patchOpenCodeConfig2(resolvedProjectRoot);
2735
3030
  spin.stop(cfg.success ? `✓ ${cfg.message}` : `✗ ${cfg.message}`);
2736
3031
  if (!cfg.success)
2737
3032
  allOk = false;
2738
3033
  if (!allOk) {
2739
3034
  v2.warn("Algunos componentes requieren atención. Revisá los mensajes de error arriba.");
2740
3035
  }
3036
+ return allOk;
2741
3037
  }
2742
3038
  async function doInstallAll(manifest, paths) {
2743
3039
  const spin = L2();
@@ -2784,27 +3080,29 @@ async function doInstallAll(manifest, paths) {
2784
3080
  }
2785
3081
  }
2786
3082
  v2.info("Instalando stack de herramientas...");
2787
- await doInstallStack(paths.tools);
3083
+ const stackOk = await doInstallStack(paths.tools, dirname6(paths.root));
3084
+ if (!stackOk)
3085
+ errors++;
2788
3086
  const missingTools = [];
2789
- const codegraphBin = join8(paths.tools, "codegraph", "bin", "codegraph");
2790
- const engramBin = join8(paths.tools, "engram", "bin", "engram");
2791
- if (!existsSync7(codegraphBin))
3087
+ const codegraphDir = join8(paths.tools, "codegraph");
3088
+ const engramDir = join8(paths.tools, "engram");
3089
+ if (!existsSync7(codegraphDir) || !findBinaryInDir(codegraphDir, "codegraph"))
2792
3090
  missingTools.push("CodeGraph");
2793
- if (!existsSync7(engramBin))
3091
+ if (!existsSync7(engramDir) || !findBinaryInDir(engramDir, "engram"))
2794
3092
  missingTools.push("Engram");
2795
3093
  if (missingTools.length > 0) {
2796
3094
  v2.warn(`Faltan herramientas del stack: ${missingTools.join(", ")}.
2797
3095
  ` + "Ejecutá `/install-stack` desde el agente para instalarlas manualmente.");
2798
3096
  }
2799
- if (errors === 0) {
3097
+ if (errors === 0 && stackOk && missingTools.length === 0) {
2800
3098
  v2.success("Todo instalado correctamente.");
2801
3099
  } else {
2802
- v2.warn(`Completado con ${errors} error(es).`);
3100
+ v2.warn(`Instalación parcial: ${errors} componente(s) requieren atención.`);
2803
3101
  }
3102
+ return errors === 0 && stackOk && missingTools.length === 0;
2804
3103
  }
2805
3104
 
2806
3105
  // src/prompts/add.ts
2807
- init_dist2();
2808
3106
  init_lockfile();
2809
3107
  async function doAddAgent(manifest, paths) {
2810
3108
  const lockfile = readLockfile(paths.root);
@@ -2918,7 +3216,6 @@ async function doAddMcp(manifest, paths) {
2918
3216
  }
2919
3217
 
2920
3218
  // src/prompts/update.ts
2921
- init_dist2();
2922
3219
  init_lockfile();
2923
3220
  async function doUpdate(manifest, paths) {
2924
3221
  const candidates = getUpdateCandidates(manifest, paths);
@@ -2988,7 +3285,6 @@ async function doUpdate(manifest, paths) {
2988
3285
  }
2989
3286
 
2990
3287
  // src/prompts/uninstall.ts
2991
- init_dist2();
2992
3288
  import { join as join9 } from "path";
2993
3289
  init_stack();
2994
3290
  init_lockfile();
@@ -3329,9 +3625,10 @@ async function runInteractiveMenu() {
3329
3625
  onCancel(action);
3330
3626
  switch (action) {
3331
3627
  case "all":
3332
- await doInstallAll(manifest, paths);
3628
+ if (!await doInstallAll(manifest, paths))
3629
+ process.exitCode = 1;
3333
3630
  printPostInstallSteps();
3334
- fe("Listo.");
3631
+ fe(process.exitCode ? "Instalación parcial." : "Listo.");
3335
3632
  break;
3336
3633
  case "agent":
3337
3634
  await doAddAgent(manifest, paths);
@@ -3355,8 +3652,10 @@ async function runInteractiveMenu() {
3355
3652
  break;
3356
3653
  case "stack": {
3357
3654
  ensureToolDirs(paths.tools, ["codegraph", "engram", "context7"]);
3358
- await doInstallStack(paths.tools);
3359
- fe("Listo.");
3655
+ const stackOk = await doInstallStack(paths.tools, dirname7(paths.root));
3656
+ if (!stackOk)
3657
+ process.exitCode = 1;
3658
+ fe(stackOk ? "Listo." : "Instalación parcial.");
3360
3659
  break;
3361
3660
  }
3362
3661
  case "update": {
@@ -3382,9 +3681,10 @@ async function runInstallCommand() {
3382
3681
  fe("Cancelado.");
3383
3682
  return;
3384
3683
  }
3385
- await doInstallAll(manifest, paths);
3684
+ if (!await doInstallAll(manifest, paths))
3685
+ process.exitCode = 1;
3386
3686
  printPostInstallSteps();
3387
- fe("Instalación completada.");
3687
+ fe(process.exitCode ? "Instalación parcial." : "Instalación completada.");
3388
3688
  }
3389
3689
  async function runAddAgentCommand() {
3390
3690
  we(" OpenCode Installer ");
@@ -3442,8 +3742,10 @@ async function runInstallStackCommand() {
3442
3742
  return;
3443
3743
  }
3444
3744
  ensureToolDirs(paths.tools, ["codegraph", "engram", "context7"]);
3445
- await doInstallStack(paths.tools);
3446
- fe("Stack instalado.");
3745
+ const stackOk = await doInstallStack(paths.tools, dirname7(paths.root));
3746
+ if (!stackOk)
3747
+ process.exitCode = 1;
3748
+ fe(stackOk ? "Stack instalado." : "Stack instalado parcialmente.");
3447
3749
  }
3448
3750
  async function runUninstallStackCommand() {
3449
3751
  we(" OpenCode Installer — Stack ");
@@ -3503,7 +3805,7 @@ async function runUninstallAgentCommand(name) {
3503
3805
  const { readLockfile: readLockfile2 } = await Promise.resolve().then(() => (init_lockfile(), exports_lockfile));
3504
3806
  const lockfile = readLockfile2(paths.root);
3505
3807
  if (lockfile && Object.keys(lockfile.agents).length > 0) {
3506
- const { default: prompts } = await Promise.resolve().then(() => (init_dist2(), exports_dist));
3808
+ const prompts = exports_dist;
3507
3809
  const installed = Object.keys(lockfile.agents);
3508
3810
  const options = installed.map((n) => ({
3509
3811
  value: n,
@@ -3538,7 +3840,7 @@ async function runUninstallCommandCommand(name) {
3538
3840
  const { readLockfile: readLockfile2 } = await Promise.resolve().then(() => (init_lockfile(), exports_lockfile));
3539
3841
  const lockfile = readLockfile2(paths.root);
3540
3842
  if (lockfile && Object.keys(lockfile.commands).length > 0) {
3541
- const { default: prompts } = await Promise.resolve().then(() => (init_dist2(), exports_dist));
3843
+ const prompts = exports_dist;
3542
3844
  const installed = Object.keys(lockfile.commands);
3543
3845
  const options = installed.map((n) => ({
3544
3846
  value: n,
@@ -3573,7 +3875,7 @@ async function runUninstallSkillCommand(name) {
3573
3875
  const { readLockfile: readLockfile2 } = await Promise.resolve().then(() => (init_lockfile(), exports_lockfile));
3574
3876
  const lockfile = readLockfile2(paths.root);
3575
3877
  if (lockfile && lockfile.skills && Object.keys(lockfile.skills).length > 0) {
3576
- const { default: prompts } = await Promise.resolve().then(() => (init_dist2(), exports_dist));
3878
+ const prompts = exports_dist;
3577
3879
  const installed = Object.keys(lockfile.skills);
3578
3880
  const options = installed.map((n) => ({
3579
3881
  value: n,
@@ -3608,7 +3910,7 @@ async function runUninstallMcpCommand(name) {
3608
3910
  const { readLockfile: readLockfile2 } = await Promise.resolve().then(() => (init_lockfile(), exports_lockfile));
3609
3911
  const lockfile = readLockfile2(paths.root);
3610
3912
  if (lockfile && lockfile.mcpServers && Object.keys(lockfile.mcpServers).length > 0) {
3611
- const { default: prompts } = await Promise.resolve().then(() => (init_dist2(), exports_dist));
3913
+ const prompts = exports_dist;
3612
3914
  const installed = Object.keys(lockfile.mcpServers);
3613
3915
  const options = installed.map((n) => ({
3614
3916
  value: n,