ostacky 0.6.0 → 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,2099 +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
+ }
1247
+ }
1248
+ }
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 {}
1208
1287
  }
1209
1288
  }
1289
+ try {
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}`);
1295
+ }
1296
+ archivePromotion?.commit();
1297
+ return { success: true, message: "Engram instalado localmente y configurado para OpenCode (MCP + plugin)" };
1210
1298
  }
1211
- function isCommandAvailable(cmd) {
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 });
1212
1305
  try {
1213
- if (process.platform === "win32") {
1214
- execSync(`where ${cmd} >nul 2>&1`);
1215
- } else {
1216
- execSync(`which ${cmd} >/dev/null 2>&1`);
1217
- }
1218
- return true;
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}` };
1313
+ }
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)" };
1219
1323
  } catch {
1220
- return false;
1324
+ return {
1325
+ success: true,
1326
+ message: "Context7 MCP registrado (skill opcional no instalada — corrí `npx ctx7 setup --opencode` manualmente si la querés)"
1327
+ };
1221
1328
  }
1222
1329
  }
1223
- function detectPlatformTarget() {
1224
- const platform = process.platform;
1225
- const arch = process.arch;
1226
- let os;
1227
- let cpu;
1228
- if (platform === "darwin")
1229
- os = "darwin";
1230
- else if (platform === "linux")
1231
- os = "linux";
1232
- else if (platform === "win32")
1233
- os = "win32";
1234
- else
1235
- return null;
1236
- if (arch === "arm64")
1237
- cpu = "arm64";
1238
- else if (arch === "x64")
1239
- cpu = "x64";
1240
- else
1241
- return null;
1242
- return `${os}-${cpu}`;
1330
+ async function installStack(toolsDir) {
1331
+ const { projectRoot } = resolveToolInstallLocation(toolsDir);
1332
+ return {
1333
+ codegraph: await installCodeGraph(toolsDir),
1334
+ openspec: setupOpenSpec(projectRoot),
1335
+ engram: await installEngram(toolsDir),
1336
+ context7: setupContext7(toolsDir),
1337
+ config: patchOpenCodeConfig(projectRoot)
1338
+ };
1243
1339
  }
1244
- function downloadToFile(url, dest, timeoutMs = 180000) {
1245
- return new Promise((resolve2, reject) => {
1246
- const file = createWriteStream(dest);
1247
- file.on("finish", () => resolve2());
1248
- file.on("error", (err) => reject(err));
1249
- const controller = new AbortController;
1250
- const timer = setTimeout(() => controller.abort(), timeoutMs);
1251
- fetch(url, { signal: controller.signal, headers: { "User-Agent": USER_AGENT } }).then((res) => {
1252
- if (!res.ok || !res.body) {
1253
- reject(new Error(`HTTP ${res.status} ${res.statusText} descargando ${url}`));
1254
- return;
1255
- }
1256
- const writable = new WritableStream({
1257
- write(chunk) {
1258
- return new Promise((ok, fail) => file.write(Buffer.from(chunk), (err) => err ? fail(err) : ok()));
1259
- },
1260
- close() {
1261
- file.end();
1262
- }
1263
- });
1264
- return res.body.pipeTo(writable);
1265
- }).then(() => {
1266
- clearTimeout(timer);
1267
- }).catch((err) => {
1268
- clearTimeout(timer);
1269
- file.destroy();
1270
- try {
1271
- unlinkSync(dest);
1272
- } catch {}
1273
- reject(err);
1274
- });
1275
- });
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" };
1276
1360
  }
1277
- async function downloadAndExtract(url, destDir, stripComponents = 1, timeoutMs = 180000) {
1278
- const tmp = join(destDir, `.download-${Date.now()}`);
1279
- if (!existsSync(tmp))
1280
- mkdirSync(tmp, { recursive: true });
1281
- const archivePath = join(tmp, url.endsWith(".zip") ? "archive.zip" : "archive.tar.gz");
1282
- try {
1283
- await downloadToFile(url, archivePath, timeoutMs);
1284
- if (!existsSync(destDir))
1285
- mkdirSync(destDir, { recursive: true });
1286
- if (process.platform === "win32" && url.endsWith(".zip")) {
1287
- execSync(`powershell -NoProfile -Command "Expand-Archive -Path '${archivePath}' -DestinationPath '${destDir}' -Force"`, { stdio: "pipe", timeout: 60000 });
1288
- } else {
1289
- const stripArg = stripComponents > 0 ? `--strip-components=${stripComponents}` : "";
1290
- execSync(`tar -xzf "${archivePath}" -C "${destDir}" ${stripArg}`, {
1291
- stdio: "pipe",
1292
- timeout: 60000
1293
- });
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
+ }
1377
+ }
1378
+ if (Object.keys(mcp).length === 0) {
1379
+ delete config.mcp;
1380
+ changed = true;
1381
+ }
1382
+ }
1383
+ if (changed) {
1384
+ writeOpenCodeConfig(configPath, config);
1385
+ }
1294
1386
  }
1295
- } finally {
1387
+ }
1388
+ const codegraphDir = join7(projectRoot, ".codegraph");
1389
+ if (existsSync6(codegraphDir)) {
1296
1390
  try {
1297
- rmSync(tmp, { recursive: true, force: true });
1391
+ rmSync4(codegraphDir, { recursive: true, force: true });
1392
+ removed.push(".codegraph/");
1298
1393
  } catch {}
1299
1394
  }
1300
- }
1301
- async function downloadAndExtractWithRetry(url, destDir, stripComponents = 1, timeoutMs = 180000, maxRetries = 2) {
1302
- let lastError = null;
1303
- for (let attempt = 0;attempt <= maxRetries; attempt++) {
1395
+ if (existsSync6(paths.tools)) {
1304
1396
  try {
1305
- await downloadAndExtract(url, destDir, stripComponents, timeoutMs);
1306
- return;
1307
- } catch (err) {
1308
- lastError = err;
1309
- if (attempt < maxRetries) {
1310
- const delay = 1000 * Math.pow(2, attempt);
1311
- console.error(`[download] Intento ${attempt + 1} falló: ${lastError.message}. Reintentando en ${delay}ms...`);
1312
- await new Promise((r2) => setTimeout(r2, delay));
1313
- }
1314
- }
1397
+ rmSync4(paths.tools, { recursive: true, force: true });
1398
+ removed.push(".opencode/tools/");
1399
+ } catch {}
1315
1400
  }
1316
- 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
+ };
1317
1408
  }
1318
- function findBinaryInDir(dir, name) {
1319
- const entries = readdirSync(dir);
1320
- for (const entry of entries) {
1321
- const full = join(dir, entry);
1322
- const stat = statSync(full);
1323
- if (stat.isDirectory()) {
1324
- const found = findBinaryInDir(full, name);
1325
- if (found)
1326
- return found;
1327
- } else if (entry === name || entry === name + ".exe") {
1328
- 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
1329
1422
  }
1423
+ };
1424
+ if (!result.ostackyController.exists) {
1425
+ result.ostackyController.error = "ostacky-controller MCP server not found";
1330
1426
  }
1331
- return null;
1427
+ if (!result.openspec.exists) {
1428
+ result.openspec.error = "openspec MCP server not found";
1429
+ }
1430
+ return result;
1332
1431
  }
1333
- var USER_AGENT = "ostacky-installer";
1334
- var init_fs = __esm(() => {
1335
- init_security();
1336
- });
1337
-
1338
- // manifest.json
1339
- var manifest_default;
1340
- var init_manifest = __esm(() => {
1341
- manifest_default = {
1342
- version: "0.6.0",
1343
- repo: "JaimeHoracio/Ostacky",
1344
- tag: "v0.6.0",
1345
- agents: [
1346
- {
1347
- name: "ostacky",
1348
- file: "assets/agents/ostacky.md",
1349
- 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",
1350
- version: "0.6.0",
1351
- sha256: "206963fd98b0af4580338407d1df11c30ecd0c18b984f73eb4b624555c263f55"
1352
- }
1353
- ],
1354
- commands: [
1355
- {
1356
- name: "install-stack",
1357
- file: "assets/commands/install-stack.md",
1358
- description: "Instala el stack tecnológico del proyecto (CodeGraph, skills, OpenSpec, Engram, Context7, controller MCP con SDK oficial)",
1359
- version: "0.6.0",
1360
- sha256: "9fb5a6ab01506c62c3a844fdac3940773c4aa2c22aa4f1effcf9048dafa28673"
1361
- },
1362
- {
1363
- name: "opsx-sync",
1364
- file: "assets/commands/opsx-sync.md",
1365
- description: "Sincroniza delta specs del change activo sin inicializar CodeGraph si ya existe índice",
1366
- version: "0.6.0",
1367
- sha256: "ed9948f1910743b672e1dfad496bc96972a224a98b063232be39290d43068c50"
1368
- }
1369
- ],
1370
- mcpServers: [
1371
- {
1372
- name: "ostacky-controller",
1373
- file: "assets/mcp/ostacky-controller/",
1374
- 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",
1375
- version: "0.6.0",
1376
- sha256: "b9637c3c78f4da059868e5af4d1e99af8280a9d3e3f1a6eafc6e74362c93a75b"
1377
- },
1378
- {
1379
- name: "openspec",
1380
- file: "assets/mcp/openspec/",
1381
- description: "MCP server local para OpenSpec - proposal, apply, archive, sync de cambios",
1382
- version: "0.6.0",
1383
- sha256: "db49c5ddbf1c2b3a9b65598b9a0ac1409694cd54444d1d1bd74eb12e6b39be01"
1384
- }
1385
- ],
1386
- skills: [
1387
- {
1388
- name: "brainstorming",
1389
- file: "assets/skills/brainstorming/SKILL.md",
1390
- 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)",
1391
- version: "0.6.0",
1392
- sha256: "d1051ded927d57dcf72c33fa0d6116c7d0103ef36f5a7f9e22f7b3da78f9c74e"
1393
- },
1394
- {
1395
- name: "execution-mode-evaluation",
1396
- file: "assets/skills/execution-mode-evaluation/SKILL.md",
1397
- description: "Skill de análisis de modo de ejecución — output reconciliado con controller snapshot contract (recommendation field)",
1398
- version: "0.6.0",
1399
- sha256: "5c37f6f4132378f863c99102bbde8bab478160ced82a2ea1025f958275d8e881"
1400
- },
1401
- {
1402
- name: "writing-plans",
1403
- file: "assets/skills/writing-plans/SKILL.md",
1404
- description: "Skill de planificación de implementación (Superpowers) — execution handoff removido, Ostacky decide modo de ejecución",
1405
- version: "0.6.0",
1406
- sha256: "e681af5e607e7ae4b6a1c0760a4f1d1d292a028d2b6989df3afb9be8dcc81c61"
1407
- },
1408
- {
1409
- name: "tdd",
1410
- file: "assets/skills/tdd/SKILL.md",
1411
- description: "Skill de test-driven development (Superpowers)",
1412
- version: "0.6.0",
1413
- sha256: "9f5a25e61e049d473a854a5401cec947329e830aa902db7c31f91a160ac19890"
1414
- },
1415
- {
1416
- name: "subagent-driven-development",
1417
- file: "assets/skills/subagent-driven-development/SKILL.md",
1418
- description: "Skill de ejecución con subagentes (Superpowers) — ejecuta solo después de confirmación del coordinador Ostacky",
1419
- version: "0.6.0",
1420
- sha256: "65d87f2b3ae1da5d08b6760938ab7009e0e226182ec1d88d322a230754ac9d8e"
1421
- },
1422
- {
1423
- name: "dispatching-parallel-agents",
1424
- file: "assets/skills/dispatching-parallel-agents/SKILL.md",
1425
- description: "Skill de dispatch paralelo de agentes (Superpowers)",
1426
- version: "0.6.0",
1427
- sha256: "2d93480e4b9c0f516861a765977ae08b6e02dc113dc456068ef8026bcb950fcb"
1428
- },
1429
- {
1430
- name: "review",
1431
- file: "assets/skills/review/SKILL.md",
1432
- description: "Skill de revisión de código (Superpowers)",
1433
- version: "0.6.0",
1434
- sha256: "14831d9ef3746ef6e2e6047c868fe7aa296d01f0644227ce776fe99436357b1a"
1435
- },
1436
- {
1437
- name: "receiving-code-review",
1438
- file: "assets/skills/receiving-code-review/SKILL.md",
1439
- description: "Skill de recibir y procesar feedback de code review",
1440
- version: "0.6.0",
1441
- sha256: "0a5780e8a41539d15428114b7c46f36670acc16aba0db3348d36be1175433872"
1442
- },
1443
- {
1444
- name: "openspec-propose",
1445
- file: "assets/skills/openspec-propose/SKILL.md",
1446
- description: "Skill de generación de proposal (OpenSpec)",
1447
- version: "0.6.0",
1448
- sha256: "c50d478fd96ec5a60080012d5d87a09b54787884b4b0fa7d8631e7bee6c8c80d"
1449
- },
1450
- {
1451
- name: "openspec-apply-change",
1452
- file: "assets/skills/openspec-apply-change/SKILL.md",
1453
- description: "Skill de aplicación de change (OpenSpec)",
1454
- version: "0.6.0",
1455
- sha256: "723a492f2ef2df3337e8e841ae84f4f5d0f8621e534c8ea76540ee3a796ff527"
1456
- },
1457
- {
1458
- name: "openspec-archive-change",
1459
- file: "assets/skills/openspec-archive-change/SKILL.md",
1460
- description: "Skill de archivo de change (OpenSpec)",
1461
- version: "0.6.0",
1462
- sha256: "dc2422d0ff9a54e3ed9b016df2bad0dfa6cca9adaee02bb4563ce7525cc56f40"
1463
- },
1464
- {
1465
- name: "openspec-explore",
1466
- file: "assets/skills/openspec-explore/SKILL.md",
1467
- description: "Modo explore para OpenSpec — thinking partner para explorar ideas, investigar problemas y clarificar requisitos antes/durante un cambio",
1468
- version: "0.6.0",
1469
- sha256: "6e162c0b38dedd2ee70d0be9179af1a9716e78ac786511d5b49ebeb0fffc14a0"
1470
- },
1471
- {
1472
- name: "using-git-worktrees",
1473
- file: "assets/skills/using-git-worktrees/SKILL.md",
1474
- description: "Skill de uso de git worktrees para aislamiento de trabajo",
1475
- version: "0.6.0",
1476
- sha256: "3829b79c1d36b1bc9d148153b07f66265599a19494f648731273e3e6d1a0d65c"
1477
- },
1478
- {
1479
- name: "using-superpowers",
1480
- file: "assets/skills/using-superpowers/SKILL.md",
1481
- description: "Skill de orquestación de Superpowers skills",
1482
- version: "0.6.0",
1483
- sha256: "d0153c2bdac88c5a409d439d137b8f04fecda005cc7722f1ca83b2211bfda115"
1484
- },
1485
- {
1486
- name: "writing-skills",
1487
- file: "assets/skills/writing-skills/SKILL.md",
1488
- description: "Skill de creación y edición de skills",
1489
- version: "0.6.0",
1490
- sha256: "371da06aad8a546389785140248698b6401730f34c2ab00b4b9304e5a51e1eb4"
1491
- },
1492
- {
1493
- name: "graceful-degradation",
1494
- file: "assets/skills/graceful-degradation/SKILL.md",
1495
- description: "Skill de degradación graceful cuando múltiples tools están indisponibles",
1496
- version: "0.6.0",
1497
- sha256: "92ea3381b5610d9041797868a5887fb358d185d80ebb753bdae3f9f9abb4d790"
1498
- }
1499
- ]
1500
- };
1432
+ var init_stack = __esm(() => {
1433
+ init_fs();
1434
+ init_config();
1435
+ init_github();
1501
1436
  });
1502
-
1503
- // src/cache.ts
1504
- import { existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
1505
- import { join as join2, dirname as dirname2 } from "path";
1506
- function getCacheRoot(projectRoot) {
1507
- return join2(projectRoot, ".opencode", "cache");
1508
- }
1509
- function cacheKey(projectRoot, repo, tag, filePath) {
1510
- const repoSlug = repo.replace("/", "__");
1511
- return join2(getCacheRoot(projectRoot), repoSlug, tag, filePath);
1512
- }
1513
- function getCached(projectRoot, repo, tag, filePath, expectedHash) {
1514
- const cachePath = cacheKey(projectRoot, repo, tag, filePath);
1515
- if (!existsSync2(cachePath))
1516
- return null;
1517
- try {
1518
- const content = readFileSync2(cachePath, "utf-8");
1519
- if (expectedHash && sha256(content) !== expectedHash)
1520
- return null;
1521
- return content;
1522
- } catch {
1523
- 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"
1524
1483
  }
1525
- }
1526
- function putCache(projectRoot, repo, tag, filePath, content) {
1527
- const cachePath = cacheKey(projectRoot, repo, tag, filePath);
1528
- const dir = dirname2(cachePath);
1529
- if (!existsSync2(dir))
1530
- mkdirSync2(dir, { recursive: true });
1531
- writeFileSync2(cachePath, content, "utf-8");
1532
- }
1533
- var init_cache = __esm(() => {
1534
- 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
1535
1506
  });
1507
+ import { stripVTControlCharacters as T2 } from "node:util";
1536
1508
 
1537
- // src/github.ts
1538
- import { fileURLToPath } from "url";
1539
- import { dirname as dirname3, join as join3 } from "path";
1540
- function getBundledSkillPath(name) {
1541
- validateFilePath(name);
1542
- 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");
1543
1519
  }
1544
- function getBundledMcpPath(name) {
1545
- validateFilePath(name);
1546
- 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, "");
1547
1525
  }
1548
- function getRawUrl(repo, tag, path) {
1549
- return `${GITHUB_RAW}/${repo}/${tag}/${path}`;
1526
+ function O(t) {
1527
+ return t && t.__esModule && Object.prototype.hasOwnProperty.call(t, "default") ? t.default : t;
1550
1528
  }
1551
- async function fetchLatestReleaseTag(repo) {
1552
- try {
1553
- const res = await fetch(`https://api.github.com/repos/${repo}/releases/latest`, {
1554
- signal: AbortSignal.timeout(5000),
1555
- headers: { "User-Agent": USER_AGENT }
1556
- });
1557
- if (res.ok) {
1558
- const data = await res.json();
1559
- 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;
1560
1586
  }
1561
- } catch {}
1562
- try {
1563
- const res = await fetch(`https://github.com/${repo}/releases/latest`, {
1564
- redirect: "manual",
1565
- signal: AbortSignal.timeout(5000),
1566
- headers: { "User-Agent": USER_AGENT }
1567
- });
1568
- const loc = res.headers.get("location") ?? "";
1569
- const m3 = loc.match(/releases\/tag\/(v[^/]+)$/);
1570
- if (m3)
1571
- return m3[1];
1572
- } catch {}
1573
- return null;
1587
+ }
1588
+ return e;
1574
1589
  }
1575
- async function fetchManifest(tag) {
1576
- const resolvedTag = tag ?? manifest_default.tag;
1577
- try {
1578
- const url = getRawUrl(manifest_default.repo, resolvedTag, "manifest.json");
1579
- const response = await fetch(url, {
1580
- signal: AbortSignal.timeout(5000),
1581
- headers: { "User-Agent": USER_AGENT }
1582
- });
1583
- if (response.ok) {
1584
- 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;
1585
1626
  }
1586
- } catch {}
1587
- return manifest_default;
1588
- }
1589
- async function fetchLatestManifest() {
1590
- const latestTag = await fetchLatestReleaseTag(manifest_default.repo);
1591
- const currentTag = manifest_default.tag;
1592
- const isNew = latestTag !== null && latestTag !== currentTag;
1593
- const manifest = await fetchManifest(latestTag ?? currentTag);
1594
- 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;
1595
1633
  }
1596
- async function downloadFile(manifest, filePath) {
1597
- validateFilePath(filePath);
1598
- const item = [
1599
- ...manifest.agents,
1600
- ...manifest.commands,
1601
- ...manifest.skills ?? [],
1602
- ...manifest.mcpServers ?? []
1603
- ].find((i) => i.file === filePath);
1604
- const expectedHash = item?.sha256 ?? null;
1605
- const projectRoot = findProjectRoot();
1606
- const cached = getCached(projectRoot, manifest.repo, manifest.tag, filePath, expectedHash);
1607
- if (cached !== null)
1608
- return cached;
1609
- const url = getRawUrl(manifest.repo, manifest.tag, filePath);
1610
- const response = await fetch(url, {
1611
- headers: { "User-Agent": USER_AGENT },
1612
- signal: AbortSignal.timeout(30000)
1613
- });
1614
- if (!response.ok) {
1615
- 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);
1616
1655
  }
1617
- const content = await response.text();
1618
- verifyChecksum(content, expectedHash, filePath);
1619
- putCache(projectRoot, manifest.repo, manifest.tag, filePath, content);
1620
- return content;
1621
- }
1622
- var GITHUB_RAW = "https://raw.githubusercontent.com", __filename2, __dirname2, PACKAGE_ROOT, BUNDLED_SKILLS_DIR, BUNDLED_MCP_DIR;
1623
- var init_github = __esm(() => {
1624
- init_manifest();
1625
- init_cache();
1626
- init_security();
1627
- init_fs();
1628
- __filename2 = fileURLToPath(import.meta.url);
1629
- __dirname2 = dirname3(__filename2);
1630
- PACKAGE_ROOT = join3(__dirname2, "..");
1631
- BUNDLED_SKILLS_DIR = join3(PACKAGE_ROOT, "assets", "skills");
1632
- BUNDLED_MCP_DIR = join3(PACKAGE_ROOT, "assets", "mcp");
1633
- });
1634
-
1635
- // src/lockfile.ts
1636
- var exports_lockfile = {};
1637
- __export(exports_lockfile, {
1638
- writeLockfile: () => writeLockfile,
1639
- removeFromLockfile: () => removeFromLockfile,
1640
- readLockfile: () => readLockfile,
1641
- getLockfilePath: () => getLockfilePath,
1642
- getInstalledVersion: () => getInstalledVersion,
1643
- clearLockfile: () => clearLockfile
1644
- });
1645
- import { existsSync as existsSync3, readFileSync as readFileSync3, writeFileSync as writeFileSync3 } from "fs";
1646
- import { join as join4 } from "path";
1647
- function getLockfilePath(opencodeRoot) {
1648
- return join4(opencodeRoot, LOCKFILE_NAME);
1649
- }
1650
- function readLockfile(opencodeRoot) {
1651
- const lockPath = getLockfilePath(opencodeRoot);
1652
- if (!existsSync3(lockPath))
1653
- return null;
1654
- try {
1655
- return JSON.parse(readFileSync3(lockPath, "utf-8"));
1656
- } catch {
1657
- 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)));
1658
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
+ `);
1659
1716
  }
1660
- function writeLockfile(opencodeRoot, lockfile) {
1661
- 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
+ }
1662
1733
  }
1663
- function getInstalledVersion(lockfile, type, name) {
1664
- 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;
1665
1741
  }
1666
- function removeFromLockfile(opencodeRoot, type, name) {
1667
- const lockfile = readLockfile(opencodeRoot);
1668
- if (!lockfile)
1669
- return;
1670
- if (!lockfile[type])
1671
- return;
1672
- if (!(name in lockfile[type]))
1742
+ function lD(t, u) {
1743
+ if (t === u)
1673
1744
  return;
1674
- delete lockfile[type][name];
1675
- 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;
1676
1751
  }
1677
- function clearLockfile(opencodeRoot) {
1678
- const lockfile = readLockfile(opencodeRoot);
1679
- if (!lockfile) {
1680
- writeLockfile(opencodeRoot, {
1681
- version: LOCKFILE_VERSION,
1682
- lockedAt: new Date().toISOString(),
1683
- repo: "",
1684
- tag: "",
1685
- agents: {},
1686
- commands: {},
1687
- skills: {},
1688
- 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
+ });
1689
1777
  });
1690
- return;
1691
- }
1692
- lockfile.agents = {};
1693
- lockfile.commands = {};
1694
- lockfile.skills = {};
1695
- lockfile.mcpServers = {};
1696
- lockfile.lockedAt = new Date().toISOString();
1697
- 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
+ };
1698
1782
  }
1699
- var LOCKFILE_NAME = "ostacky-lock.json", LOCKFILE_VERSION;
1700
- var init_lockfile = __esm(() => {
1701
- init_manifest();
1702
- LOCKFILE_VERSION = manifest_default.version;
1703
- });
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);
1704
1786
 
1705
- // src/config.ts
1706
- var exports_config = {};
1707
- __export(exports_config, {
1708
- writeOpenCodeConfig: () => writeOpenCodeConfig,
1709
- stripJsoncComments: () => stripJsoncComments,
1710
- setMcpEntry: () => setMcpEntry,
1711
- readOpenCodeConfig: () => readOpenCodeConfig,
1712
- patchOpenCodeConfig: () => patchOpenCodeConfig,
1713
- findOpenCodeConfig: () => findOpenCodeConfig,
1714
- ensureOpenCodeConfig: () => ensureOpenCodeConfig,
1715
- ensureMcpEntry: () => ensureMcpEntry
1716
- });
1717
- import { existsSync as existsSync4, readFileSync as readFileSync4, writeFileSync as writeFileSync4 } from "fs";
1718
- import { join as join5 } from "path";
1719
- function stripJsoncComments(text) {
1720
- let result = "";
1721
- let i = 0;
1722
- let inString = false;
1723
- while (i < text.length) {
1724
- const char = text[i];
1725
- const next = text[i + 1];
1726
- if (inString) {
1727
- if (char === "\\") {
1728
- result += char + (next ?? "");
1729
- i += 2;
1730
- 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 });
1731
1821
  }
1732
- if (char === '"')
1733
- inString = false;
1734
- result += char;
1735
- i++;
1736
- continue;
1737
- }
1738
- if (char === '"') {
1739
- inString = true;
1740
- result += char;
1741
- i++;
1742
- continue;
1743
- }
1744
- if (char === "/" && next === "/") {
1745
- while (i < text.length && text[i] !== `
1746
- `)
1747
- i++;
1748
- 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");
1749
1839
  }
1750
- if (char === "/" && next === "*") {
1751
- i += 2;
1752
- while (i < text.length && !(text[i] === "*" && text[i + 1] === "/"))
1753
- i++;
1754
- i += 2;
1755
- 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;
1756
1878
  }
1757
- result += char;
1758
- i++;
1759
1879
  }
1760
- return result.replace(/,\s*([}\]])/g, "$1");
1761
1880
  }
1762
- function readOpenCodeConfig(configPath) {
1763
- const raw = readFileSync4(configPath, "utf-8");
1764
- try {
1765
- return JSON.parse(stripJsoncComments(raw));
1766
- } catch {
1767
- 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
+ });
1768
1897
  }
1769
1898
  }
1770
- function writeOpenCodeConfig(configPath, config) {
1771
- writeFileSync4(configPath, JSON.stringify(config, null, 2) + `
1772
- `, "utf-8");
1773
- }
1774
- function ensureOpenCodeConfig(projectRoot) {
1775
- const existing = findOpenCodeConfig(projectRoot);
1776
- if (existing)
1777
- return existing;
1778
- const configPath = join5(projectRoot, "opencode.json");
1779
- writeOpenCodeConfig(configPath, {
1780
- $schema: "https://opencode.ai/config.json",
1781
- mcp: {}
1782
- });
1783
- return configPath;
1784
- }
1785
- function findOpenCodeConfig(projectRoot) {
1786
- const candidates = ["opencode.json", "opencode.jsonc"];
1787
- for (const name of candidates) {
1788
- const full = join5(projectRoot, name);
1789
- if (existsSync4(full))
1790
- 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
+ });
1791
1921
  }
1792
- return null;
1793
- }
1794
- function setMcpEntry(name, entry) {
1795
- const projectRoot = findProjectRoot();
1796
- const configPath = ensureOpenCodeConfig(projectRoot);
1797
- const config = readOpenCodeConfig(configPath);
1798
- if (!config)
1799
- return;
1800
- if (!config.mcp)
1801
- config.mcp = {};
1802
- config.mcp[name] = entry;
1803
- writeOpenCodeConfig(configPath, config);
1804
- }
1805
- function ensureMcpEntry(name, entry) {
1806
- const projectRoot = findProjectRoot();
1807
- const configPath = ensureOpenCodeConfig(projectRoot);
1808
- const config = readOpenCodeConfig(configPath);
1809
- if (!config)
1810
- return;
1811
- if (!config.mcp)
1812
- config.mcp = {};
1813
- const mcp = config.mcp;
1814
- if (!mcp[name]) {
1815
- mcp[name] = entry;
1816
- writeOpenCodeConfig(configPath, config);
1922
+ getGroupItems(u) {
1923
+ return this.options.filter((F) => F.group === u);
1817
1924
  }
1818
- }
1819
- function patchOpenCodeConfig() {
1820
- const projectRoot = findProjectRoot();
1821
- const configPath = findOpenCodeConfig(projectRoot);
1822
- if (!configPath) {
1823
- return {
1824
- success: false,
1825
- message: "No se encontró opencode.json ni opencode.jsonc"
1826
- };
1925
+ isGroupSelected(u) {
1926
+ return this.getGroupItems(u).every((F) => this.value.includes(F.value));
1827
1927
  }
1828
- const config = readOpenCodeConfig(configPath);
1829
- if (!config) {
1830
- return {
1831
- success: false,
1832
- message: `Error parseando ${configPath}`
1833
- };
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
+ }
1834
1937
  }
1835
- let changed = false;
1836
- if ("plugin" in config) {
1837
- delete config.plugin;
1838
- 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
+ });
1839
1961
  }
1840
- if (changed) {
1841
- writeOpenCodeConfig(configPath, config);
1842
- return { success: true, message: "Config actualizada (plugin legacy eliminado)" };
1962
+ get _value() {
1963
+ return this.options[this.cursor].value;
1843
1964
  }
1844
- return { success: true, message: "Config de OpenCode ya está limpia" };
1845
- }
1846
- var init_config = __esm(() => {
1847
- init_fs();
1848
- });
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);
1849
1977
 
1850
- // src/stack.ts
1851
- var exports_stack = {};
1852
- __export(exports_stack, {
1853
- verifyMcpServers: () => verifyMcpServers,
1854
- uninstallStackConfig: () => uninstallStackConfig,
1855
- uninstallEngramConfig: () => uninstallEngramConfig,
1856
- setupOpenSpec: () => setupOpenSpec,
1857
- setupContext7: () => setupContext7,
1858
- installStack: () => installStack,
1859
- installEngram: () => installEngram,
1860
- installCodeGraph: () => installCodeGraph
1861
- });
1862
- import { existsSync as existsSync6, mkdirSync as mkdirSync4, copyFileSync as copyFileSync3, unlinkSync as unlinkSync3, rmSync as rmSync3 } from "fs";
1863
- import { join as join7 } from "path";
1864
- import { execSync as execSync3 } from "child_process";
1865
- async function installCodeGraph(toolsDir) {
1866
- const projectRoot = findProjectRoot();
1867
- const cgToolDir = join7(toolsDir ?? join7(projectRoot, ".opencode", "tools"), "codegraph");
1868
- if (!existsSync6(cgToolDir))
1869
- mkdirSync4(cgToolDir, { recursive: true });
1870
- const target = detectPlatformTarget();
1871
- if (!target) {
1872
- return {
1873
- success: false,
1874
- message: `Plataforma no soportada para descarga local: ${process.platform}/${process.arch}. Instalá CodeGraph manualmente.`
1875
- };
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
+ });
1876
1990
  }
1877
- const localBin = join7(cgToolDir, "bin", "codegraph");
1878
- const localBinExe = localBin + (process.platform === "win32" ? ".exe" : "");
1879
- if (existsSync6(localBinExe)) {
1880
- try {
1881
- execSync3(`"${localBinExe}" --version`, { stdio: "pipe", timeout: 1e4 });
1882
- } catch {
1883
- try {
1884
- rmSync3(join7(cgToolDir, "bin"), { recursive: true, force: true });
1885
- } catch {}
1886
- }
1991
+ get cursor() {
1992
+ return this._cursor;
1887
1993
  }
1888
- if (!existsSync6(localBinExe)) {
1889
- const tag = await fetchLatestReleaseTag("colbymchenry/codegraph");
1890
- if (!tag) {
1891
- return {
1892
- success: false,
1893
- message: "No se pudo obtener la última versión de CodeGraph desde GitHub."
1894
- };
1895
- }
1896
- const ext = process.platform === "win32" ? "zip" : "tar.gz";
1897
- const url = `https://github.com/colbymchenry/codegraph/releases/download/${tag}/codegraph-${target}.${ext}`;
1898
- try {
1899
- await downloadAndExtractWithRetry(url, cgToolDir, 1, 180000, 2);
1900
- } catch (e2) {
1901
- return {
1902
- success: false,
1903
- message: `Error descargando CodeGraph ${tag}: ${e2.message}`
1904
- };
1905
- }
1906
- if (!existsSync6(localBinExe)) {
1907
- return {
1908
- success: false,
1909
- message: `Descarga de CodeGraph ${tag} completada pero no se encontró el binario en ${localBinExe}.`
1910
- };
1911
- }
1912
- if (process.platform !== "win32") {
1913
- try {
1914
- execSync3(`chmod +x "${localBinExe}"`, { stdio: "pipe" });
1915
- } catch {}
1916
- }
1994
+ get masked() {
1995
+ return this.value.replaceAll(/./g, this._mask);
1917
1996
  }
1918
- try {
1919
- execSync3(`"${localBinExe}" init -i`, { stdio: "pipe", timeout: 120000, cwd: projectRoot });
1920
- } catch {}
1921
- try {
1922
- execSync3(`"${localBinExe}" install --target opencode --location local --yes`, {
1923
- stdio: "pipe",
1924
- timeout: 30000,
1925
- cwd: projectRoot
1997
+ }
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);
2001
+
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();
1926
2016
  });
1927
- } catch {}
1928
- const rootAgentsMd = join7(projectRoot, "AGENTS.md");
1929
- if (existsSync6(rootAgentsMd)) {
1930
- const dest = join7(cgToolDir, "AGENTS.md");
1931
- try {
1932
- copyFileSync3(rootAgentsMd, dest);
1933
- unlinkSync3(rootAgentsMd);
1934
- } catch {}
1935
2017
  }
1936
- setMcpEntry("codegraph", {
1937
- type: "local",
1938
- command: [`.opencode/tools/codegraph/bin/codegraph`, "serve", "--mcp"],
1939
- enabled: true
1940
- });
1941
- return { success: true, message: "CodeGraph instalado localmente en .opencode/tools/codegraph/ y configurado para OpenCode" };
2018
+ get _value() {
2019
+ return this.options[this.cursor];
2020
+ }
2021
+ changeValue() {
2022
+ this.value = this._value.value;
2023
+ }
1942
2024
  }
1943
- function setupOpenSpec() {
1944
- const npxCmd = isCommandAvailable("bun") ? "bunx" : "npx --yes";
1945
- try {
1946
- execSync3(`${npxCmd} openspec init --tools opencode --force`, {
1947
- stdio: "pipe",
1948
- timeout: 120000
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"));
1949
2038
  });
1950
- return { success: true, message: "OpenSpec configurado para OpenCode" };
1951
- } catch (e2) {
1952
- return {
1953
- success: false,
1954
- message: `Error configurando OpenSpec: ${e2.message}`
1955
- };
1956
2039
  }
1957
2040
  }
1958
- async function installEngram(toolsDir) {
1959
- const projectRoot = findProjectRoot();
1960
- const globalBin = Bun.which("engram");
1961
- if (globalBin) {
1962
- const engramToolDir2 = join7(toolsDir ?? join7(projectRoot, ".opencode", "tools"), "engram");
1963
- const engramBinDir2 = join7(engramToolDir2, "bin");
1964
- if (!existsSync6(engramBinDir2))
1965
- mkdirSync4(engramBinDir2, { recursive: true });
1966
- const localBin2 = join7(engramBinDir2, "engram" + (process.platform === "win32" ? ".exe" : ""));
1967
- if (!existsSync6(localBin2)) {
1968
- try {
1969
- unlinkSync3(localBin2);
1970
- } catch {}
1971
- try {
1972
- if (process.platform !== "win32") {
1973
- execSync3(`ln -s "${globalBin}" "${localBin2}"`, { stdio: "pipe" });
1974
- } else {
1975
- copyFileSync3(globalBin, localBin2);
1976
- }
1977
- } catch {}
1978
- }
1979
- setMcpEntry("engram", {
1980
- type: "local",
1981
- command: [`.opencode/tools/engram/bin/engram`, "mcp"],
1982
- enabled: true
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);
1983
2057
  });
1984
- const pluginSource2 = join7(projectRoot, "assets", "plugins", "engram.ts");
1985
- const pluginsDir2 = join7(projectRoot, ".opencode", "plugins");
1986
- const pluginTarget2 = join7(pluginsDir2, "engram.ts");
1987
- if (existsSync6(pluginSource2)) {
1988
- if (!existsSync6(pluginsDir2))
1989
- mkdirSync4(pluginsDir2, { recursive: true });
1990
- try {
1991
- copyFileSync3(pluginSource2, pluginTarget2);
1992
- } catch {}
1993
- }
1994
- return { success: true, message: `Engram global detectado en ${globalBin} — usando binario global. Plugin copiado a .opencode/plugins/` };
1995
2058
  }
1996
- const engramToolDir = join7(toolsDir ?? join7(projectRoot, ".opencode", "tools"), "engram");
1997
- const engramBinDir = join7(engramToolDir, "bin");
1998
- if (!existsSync6(engramBinDir))
1999
- mkdirSync4(engramBinDir, { recursive: true });
2000
- const target = detectPlatformTarget();
2001
- if (!target) {
2002
- return {
2003
- success: false,
2004
- message: `Plataforma no soportada para descarga local: ${process.platform}/${process.arch}. Instalá Engram manualmente.`
2005
- };
2059
+ }
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);
2102
+ }
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
+ `;
2133
+ }
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
+ `;
2006
2154
  }
2007
- const localBin = join7(engramBinDir, "engram" + (process.platform === "win32" ? ".exe" : ""));
2008
- if (existsSync6(localBin)) {
2009
- try {
2010
- execSync3(`"${localBin}" --version`, { stdio: "pipe", timeout: 1e4 });
2011
- } catch {
2012
- try {
2013
- unlinkSync3(localBin);
2014
- } 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
+ `;
2015
2172
  }
2016
- }
2017
- if (!existsSync6(localBin)) {
2018
- const tag = await fetchLatestReleaseTag("Gentleman-Programming/engram");
2019
- if (!tag) {
2020
- return {
2021
- success: false,
2022
- message: "No se pudo obtener la última versión de Engram desde GitHub."
2023
- };
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)}`;
2024
2187
  }
2025
- const versionNum = tag.replace(/^v/, "");
2026
- const [os, cpu] = target.split("-");
2027
- const engramCpu = cpu === "x64" ? "amd64" : cpu;
2028
- const ext = process.platform === "win32" ? "zip" : "tar.gz";
2029
- const url = `https://github.com/Gentleman-Programming/engram/releases/download/${tag}/engram_${versionNum}_${os}_${engramCpu}.${ext}`;
2030
- try {
2031
- await downloadAndExtractWithRetry(url, engramToolDir, 0, 120000, 2);
2032
- } catch (e2) {
2033
- return {
2034
- success: false,
2035
- message: `Error descargando Engram ${tag}: ${e2.message}`
2036
- };
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
+ `;
2037
2204
  }
2038
- const extractedBin = join7(engramToolDir, "engram" + (process.platform === "win32" ? ".exe" : ""));
2039
- if (existsSync6(extractedBin) && extractedBin !== localBin) {
2040
- try {
2041
- copyFileSync3(extractedBin, localBin);
2042
- unlinkSync3(extractedBin);
2043
- } 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
+ `;
2044
2227
  }
2045
- if (!existsSync6(localBin)) {
2046
- const found = findBinaryInDir(engramToolDir, "engram");
2047
- if (found && found !== localBin) {
2048
- try {
2049
- copyFileSync3(found, localBin);
2050
- if (process.platform !== "win32")
2051
- execSync3(`chmod +x "${localBin}"`, { stdio: "pipe" });
2052
- } 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)}` : ""}`;
2053
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
+ `;
2054
2268
  }
2055
- if (!existsSync6(localBin)) {
2056
- return {
2057
- success: false,
2058
- message: `Descarga de Engram ${tag} completada pero no se encontró el binario en ${localBin}.`
2059
- };
2060
- }
2061
- if (process.platform !== "win32") {
2062
- try {
2063
- execSync3(`chmod +x "${localBin}"`, { stdio: "pipe" });
2064
- } catch {}
2065
- }
2066
- }
2067
- setMcpEntry("engram", {
2068
- type: "local",
2069
- command: [`.opencode/tools/engram/bin/engram`, "mcp"],
2070
- enabled: true
2071
- });
2072
- const pluginSource = join7(projectRoot, "assets", "plugins", "engram.ts");
2073
- const pluginsDir = join7(projectRoot, ".opencode", "plugins");
2074
- const pluginTarget = join7(pluginsDir, "engram.ts");
2075
- if (existsSync6(pluginSource)) {
2076
- if (!existsSync6(pluginsDir))
2077
- mkdirSync4(pluginsDir, { recursive: true });
2078
- try {
2079
- copyFileSync3(pluginSource, pluginTarget);
2080
- } catch {}
2081
- }
2082
- return { success: true, message: "Engram instalado localmente en .opencode/tools/engram/bin/ y configurado para OpenCode (MCP + plugin)" };
2083
- }
2084
- function setupContext7(toolsDir) {
2085
- const projectRoot = findProjectRoot();
2086
- const ctx7ToolDir = join7(toolsDir ?? join7(projectRoot, ".opencode", "tools"), "context7");
2087
- if (!existsSync6(ctx7ToolDir))
2088
- mkdirSync4(ctx7ToolDir, { recursive: true });
2089
- ensureMcpEntry("context7", {
2090
- type: "remote",
2091
- url: "https://mcp.context7.com/mcp",
2092
- enabled: true
2093
- });
2094
- const npxCmd = isCommandAvailable("bun") ? "bunx" : "npx --yes";
2095
- try {
2096
- execSync3(`${npxCmd} ctx7 setup --opencode`, {
2097
- stdio: "pipe",
2098
- timeout: 60000
2099
- });
2100
- return { success: true, message: "Context7 configurado (MCP + skill instalado)" };
2101
- } catch {
2102
- return {
2103
- success: true,
2104
- message: "Context7 MCP registrado (skill opcional no instalada — corrí `npx ctx7 setup --opencode` manualmente si la querés)"
2105
- };
2106
- }
2107
- }
2108
- async function installStack(toolsDir) {
2109
- return {
2110
- codegraph: await installCodeGraph(toolsDir),
2111
- openspec: setupOpenSpec(),
2112
- engram: await installEngram(toolsDir),
2113
- context7: setupContext7(toolsDir),
2114
- 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)}`;
2115
2275
  };
2116
- }
2117
- function uninstallEngramConfig() {
2118
- const projectRoot = findProjectRoot();
2119
- const configPath = findOpenCodeConfig(projectRoot);
2120
- if (!configPath) {
2121
- return { success: false, message: "No se encontró opencode.json ni opencode.jsonc" };
2122
- }
2123
- const config = readOpenCodeConfig(configPath);
2124
- if (!config) {
2125
- return { success: false, message: `Error parseando ${configPath}` };
2126
- }
2127
- const mcp = config.mcp;
2128
- if (mcp && "engram" in mcp) {
2129
- delete mcp.engram;
2130
- if (Object.keys(mcp).length === 0) {
2131
- delete config.mcp;
2132
- }
2133
- writeOpenCodeConfig(configPath, config);
2134
- return { success: true, message: "Config de Engram eliminada de opencode.json" };
2135
- }
2136
- return { success: true, message: "Engram no estaba configurado en este proyecto" };
2137
- }
2138
- function uninstallStackConfig(paths) {
2139
- const projectRoot = findProjectRoot();
2140
- const removed = [];
2141
- const configPath = findOpenCodeConfig(projectRoot);
2142
- if (configPath) {
2143
- const config = readOpenCodeConfig(configPath);
2144
- if (config) {
2145
- const mcp = config.mcp;
2146
- let changed = false;
2147
- if (mcp) {
2148
- for (const name of ["codegraph", "context7", "engram"]) {
2149
- if (name in mcp) {
2150
- delete mcp[name];
2151
- removed.push(`mcp.${name}`);
2152
- changed = true;
2153
- }
2154
- }
2155
- if (Object.keys(mcp).length === 0) {
2156
- delete config.mcp;
2157
- changed = true;
2158
- }
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)}` : ""}`;
2159
2291
  }
2160
- if (changed) {
2161
- 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
+ `;
2162
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
+ `;
2163
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}`));
2164
2351
  }
2165
- const codegraphDir = join7(projectRoot, ".codegraph");
2166
- if (existsSync6(codegraphDir)) {
2167
- try {
2168
- rmSync3(codegraphDir, { recursive: true, force: true });
2169
- removed.push(".codegraph/");
2170
- } catch {}
2171
- }
2172
- if (existsSync6(paths.tools)) {
2173
- try {
2174
- rmSync3(paths.tools, { recursive: true, force: true });
2175
- removed.push(".opencode/tools/");
2176
- } catch {}
2177
- }
2178
- if (removed.length === 0) {
2179
- return { success: true, message: "No había configuración del stack para remover" };
2180
- }
2181
- return {
2182
- success: true,
2183
- 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();
2184
2402
  };
2185
- }
2186
- function verifyMcpServers(projectRoot) {
2187
- const opencodeDir = findOpenCodeDir(projectRoot);
2188
- const mcpBase = opencodeDir ? join7(opencodeDir, "mcp") : join7(projectRoot, ".opencode", "mcp");
2189
- const controllerPath = join7(mcpBase, "ostacky-controller", "index.js");
2190
- const openspecPath = join7(mcpBase, "openspec", "index.js");
2191
- const result = {
2192
- ostackyController: {
2193
- exists: existsSync6(controllerPath),
2194
- path: controllerPath
2195
- },
2196
- openspec: {
2197
- exists: existsSync6(openspecPath),
2198
- 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;
2199
2416
  }
2200
- };
2201
- if (!result.ostackyController.exists) {
2202
- result.ostackyController.error = "ostacky-controller MCP server not found";
2203
- }
2204
- if (!result.openspec.exists) {
2205
- result.openspec.error = "openspec MCP server not found";
2417
+ t[r2] = o;
2206
2418
  }
2207
- return result;
2208
- }
2209
- var init_stack = __esm(() => {
2210
- init_fs();
2211
- init_config();
2212
- init_github();
2213
- });
2214
- // package.json
2215
- var package_default = {
2216
- name: "ostacky",
2217
- version: "0.6.0",
2218
- description: "Instalador interactivo de agentes y comandos para OpenCode",
2219
- type: "module",
2220
- bin: {
2221
- ostacky: "./dist/cli.js"
2222
- },
2223
- scripts: {
2224
- prebuild: "bun run scripts/sync-version.ts",
2225
- dev: "bun run src/cli.ts",
2226
- build: "bun build src/cli.ts --target=node --format=esm --outfile dist/cli.js && bun scripts/add-shebang.ts",
2227
- start: "node dist/cli.js",
2228
- test: "bun test",
2229
- "check:skills": "bun run scripts/check-skill-sync.ts",
2230
- "check:skills:fix": "bun run scripts/check-skill-sync.ts --fix",
2231
- "hash:check": "bun run scripts/update-manifest-hashes.ts --check",
2232
- "hash:update": "bun run scripts/update-manifest-hashes.ts",
2233
- prepublishOnly: "bun run build"
2234
- },
2235
- files: [
2236
- "dist/",
2237
- "assets/",
2238
- "manifest.json",
2239
- "LICENSE"
2240
- ],
2241
- keywords: [
2242
- "opencode",
2243
- "installer",
2244
- "cli",
2245
- "agent"
2246
- ],
2247
- license: "MIT",
2248
- dependencies: {
2249
- "@clack/prompts": "^0.9.0"
2250
- },
2251
- devDependencies: {
2252
- "@types/bun": "latest",
2253
- typescript: "^5.0.0"
2254
- },
2255
- publishConfig: {
2256
- access: "public"
2257
- },
2258
- engines: {
2259
- 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);
2260
2429
  }
2261
2430
  };
2262
2431
 
2263
2432
  // src/prompts/index.ts
2264
- init_dist2();
2265
2433
  init_fs();
2434
+ import { dirname as dirname7 } from "path";
2266
2435
 
2267
2436
  // src/prompts/helpers.ts
2268
- init_dist2();
2269
2437
  init_github();
2270
2438
  init_fs();
2271
2439
  init_lockfile();
@@ -2285,10 +2453,166 @@ import {
2285
2453
  statSync as statSync2,
2286
2454
  copyFileSync as copyFileSync2,
2287
2455
  readFileSync as readFileSync5,
2288
- rmSync as rmSync2
2456
+ rmSync as rmSync3
2289
2457
  } from "fs";
2290
- import { execSync as execSync2 } from "child_process";
2291
- 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
+ }
2292
2616
  function upsertLockfile(paths, type, item, manifest, contentHash) {
2293
2617
  const existing = readLockfile(paths.root) ?? {
2294
2618
  version: manifest.version,
@@ -2362,7 +2686,7 @@ async function installSkill(item, manifest, paths) {
2362
2686
  }
2363
2687
  const dest = join6(paths.skills, item.name);
2364
2688
  if (existsSync5(dest)) {
2365
- rmSync2(dest, { recursive: true, force: true });
2689
+ rmSync3(dest, { recursive: true, force: true });
2366
2690
  }
2367
2691
  copyDirRecursive(src, dest);
2368
2692
  upsertLockfile(paths, "skills", item, manifest, treeHash);
@@ -2378,36 +2702,67 @@ async function installMcpServer(item, manifest, paths) {
2378
2702
  ` + ` esperado: ${item.sha256}
2379
2703
  ` + ` recibido: ${treeHash}`);
2380
2704
  }
2705
+ const nodeExecutable = getVerifiedNodeExecutable();
2706
+ const projectRoot = dirname4(paths.root);
2381
2707
  const dest = join6(paths.mcp, item.name);
2382
- if (existsSync5(dest)) {
2383
- rmSync2(dest, { recursive: true, force: true });
2384
- }
2385
- mkdirSync3(dest, { recursive: true });
2386
- const bundledPath = join6(PACKAGE_ROOT, "dist", "mcp", item.name, "index.js");
2387
- if (existsSync5(bundledPath)) {
2388
- copyFileSync2(bundledPath, join6(dest, "index.js"));
2389
- } else {
2390
- copyDirRecursive(src, dest, true);
2391
- 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);
2392
2746
  try {
2393
- const output = execSync2(installCmd, {
2394
- cwd: dest,
2395
- encoding: "utf-8",
2396
- timeout: 60000
2397
- });
2398
- if (output)
2399
- console.error(output);
2400
- } catch (e2) {
2401
- console.error(`[WARN] MCP server "${item.name}" copiado pero ${installCmd} falló: ${e2.message}.
2402
- ` + ` 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;
2403
2761
  }
2762
+ } finally {
2763
+ if (existsSync5(staging))
2764
+ rmSync3(staging, { recursive: true, force: true });
2404
2765
  }
2405
- upsertLockfile(paths, "mcpServers", item, manifest, treeHash);
2406
- ensureMcpEntry(item.name, {
2407
- type: "local",
2408
- command: ["node", `.opencode/mcp/${item.name}/index.js`],
2409
- enabled: true
2410
- });
2411
2766
  }
2412
2767
  function isMcpServerInstalled(name, paths) {
2413
2768
  return existsSync5(join6(paths.mcp, name, "index.js"));
@@ -2449,7 +2804,7 @@ function uninstallSkill(name, paths) {
2449
2804
  const dirPath = join6(paths.skills, name);
2450
2805
  try {
2451
2806
  if (existsSync5(dirPath)) {
2452
- rmSync2(dirPath, { recursive: true, force: true });
2807
+ rmSync3(dirPath, { recursive: true, force: true });
2453
2808
  }
2454
2809
  } catch {
2455
2810
  return false;
@@ -2461,12 +2816,12 @@ function uninstallMcpServer(name, paths) {
2461
2816
  const dirPath = join6(paths.mcp, name);
2462
2817
  try {
2463
2818
  if (existsSync5(dirPath)) {
2464
- rmSync2(dirPath, { recursive: true, force: true });
2819
+ rmSync3(dirPath, { recursive: true, force: true });
2465
2820
  }
2466
2821
  } catch {
2467
2822
  return false;
2468
2823
  }
2469
- const projectRoot = findProjectRoot();
2824
+ const projectRoot = dirname4(paths.root);
2470
2825
  const configPath = findOpenCodeConfig(projectRoot);
2471
2826
  if (configPath) {
2472
2827
  const config = readOpenCodeConfig(configPath);
@@ -2538,7 +2893,7 @@ async function loadLatestManifest() {
2538
2893
  }
2539
2894
  function printPostInstallSteps() {
2540
2895
  ye([
2541
- "Iniciá OpenCode (si no está corriendo):",
2896
+ "Cerrá y reiniciá OpenCode si ya estaba corriendo (los MCP no recargan su config en caliente):",
2542
2897
  " TUI → opencode",
2543
2898
  " Web → opencode web --port 4096",
2544
2899
  "Escribí @Ostacky en el chat (TUI o web) para invocar al agente",
@@ -2641,21 +2996,21 @@ function kindLabel(type) {
2641
2996
  }
2642
2997
 
2643
2998
  // src/prompts/install.ts
2644
- init_dist2();
2645
- import { join as join8 } from "path";
2999
+ import { dirname as dirname6, join as join8 } from "path";
2646
3000
  import { existsSync as existsSync7 } from "fs";
2647
3001
  init_stack();
2648
3002
  init_fs();
2649
- async function doInstallStack(toolsDir) {
3003
+ async function doInstallStack(toolsDir, projectRoot) {
2650
3004
  const spin = L2();
2651
3005
  let allOk = true;
3006
+ const resolvedProjectRoot = projectRoot ?? dirname6(dirname6(toolsDir ?? join8(process.cwd(), ".opencode", "tools")));
2652
3007
  spin.start("Instalando CodeGraph...");
2653
3008
  const cg = await installCodeGraph(toolsDir);
2654
3009
  spin.stop(cg.success ? `✓ ${cg.message}` : `✗ ${cg.message}`);
2655
3010
  if (!cg.success)
2656
3011
  allOk = false;
2657
3012
  spin.start("Configurando OpenSpec...");
2658
- const os = setupOpenSpec();
3013
+ const os = setupOpenSpec(resolvedProjectRoot);
2659
3014
  spin.stop(os.success ? `✓ ${os.message}` : `✗ ${os.message}`);
2660
3015
  if (!os.success)
2661
3016
  allOk = false;
@@ -2671,13 +3026,14 @@ async function doInstallStack(toolsDir) {
2671
3026
  allOk = false;
2672
3027
  spin.start("Verificando configuración...");
2673
3028
  const { patchOpenCodeConfig: patchOpenCodeConfig2 } = await Promise.resolve().then(() => (init_config(), exports_config));
2674
- const cfg = patchOpenCodeConfig2();
3029
+ const cfg = patchOpenCodeConfig2(resolvedProjectRoot);
2675
3030
  spin.stop(cfg.success ? `✓ ${cfg.message}` : `✗ ${cfg.message}`);
2676
3031
  if (!cfg.success)
2677
3032
  allOk = false;
2678
3033
  if (!allOk) {
2679
3034
  v2.warn("Algunos componentes requieren atención. Revisá los mensajes de error arriba.");
2680
3035
  }
3036
+ return allOk;
2681
3037
  }
2682
3038
  async function doInstallAll(manifest, paths) {
2683
3039
  const spin = L2();
@@ -2724,27 +3080,29 @@ async function doInstallAll(manifest, paths) {
2724
3080
  }
2725
3081
  }
2726
3082
  v2.info("Instalando stack de herramientas...");
2727
- await doInstallStack(paths.tools);
3083
+ const stackOk = await doInstallStack(paths.tools, dirname6(paths.root));
3084
+ if (!stackOk)
3085
+ errors++;
2728
3086
  const missingTools = [];
2729
- const codegraphBin = join8(paths.tools, "codegraph", "bin", "codegraph");
2730
- const engramBin = join8(paths.tools, "engram", "bin", "engram");
2731
- if (!existsSync7(codegraphBin))
3087
+ const codegraphDir = join8(paths.tools, "codegraph");
3088
+ const engramDir = join8(paths.tools, "engram");
3089
+ if (!existsSync7(codegraphDir) || !findBinaryInDir(codegraphDir, "codegraph"))
2732
3090
  missingTools.push("CodeGraph");
2733
- if (!existsSync7(engramBin))
3091
+ if (!existsSync7(engramDir) || !findBinaryInDir(engramDir, "engram"))
2734
3092
  missingTools.push("Engram");
2735
3093
  if (missingTools.length > 0) {
2736
3094
  v2.warn(`Faltan herramientas del stack: ${missingTools.join(", ")}.
2737
3095
  ` + "Ejecutá `/install-stack` desde el agente para instalarlas manualmente.");
2738
3096
  }
2739
- if (errors === 0) {
3097
+ if (errors === 0 && stackOk && missingTools.length === 0) {
2740
3098
  v2.success("Todo instalado correctamente.");
2741
3099
  } else {
2742
- v2.warn(`Completado con ${errors} error(es).`);
3100
+ v2.warn(`Instalación parcial: ${errors} componente(s) requieren atención.`);
2743
3101
  }
3102
+ return errors === 0 && stackOk && missingTools.length === 0;
2744
3103
  }
2745
3104
 
2746
3105
  // src/prompts/add.ts
2747
- init_dist2();
2748
3106
  init_lockfile();
2749
3107
  async function doAddAgent(manifest, paths) {
2750
3108
  const lockfile = readLockfile(paths.root);
@@ -2858,7 +3216,6 @@ async function doAddMcp(manifest, paths) {
2858
3216
  }
2859
3217
 
2860
3218
  // src/prompts/update.ts
2861
- init_dist2();
2862
3219
  init_lockfile();
2863
3220
  async function doUpdate(manifest, paths) {
2864
3221
  const candidates = getUpdateCandidates(manifest, paths);
@@ -2928,7 +3285,6 @@ async function doUpdate(manifest, paths) {
2928
3285
  }
2929
3286
 
2930
3287
  // src/prompts/uninstall.ts
2931
- init_dist2();
2932
3288
  import { join as join9 } from "path";
2933
3289
  init_stack();
2934
3290
  init_lockfile();
@@ -3269,9 +3625,10 @@ async function runInteractiveMenu() {
3269
3625
  onCancel(action);
3270
3626
  switch (action) {
3271
3627
  case "all":
3272
- await doInstallAll(manifest, paths);
3628
+ if (!await doInstallAll(manifest, paths))
3629
+ process.exitCode = 1;
3273
3630
  printPostInstallSteps();
3274
- fe("Listo.");
3631
+ fe(process.exitCode ? "Instalación parcial." : "Listo.");
3275
3632
  break;
3276
3633
  case "agent":
3277
3634
  await doAddAgent(manifest, paths);
@@ -3295,8 +3652,10 @@ async function runInteractiveMenu() {
3295
3652
  break;
3296
3653
  case "stack": {
3297
3654
  ensureToolDirs(paths.tools, ["codegraph", "engram", "context7"]);
3298
- await doInstallStack(paths.tools);
3299
- 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.");
3300
3659
  break;
3301
3660
  }
3302
3661
  case "update": {
@@ -3322,9 +3681,10 @@ async function runInstallCommand() {
3322
3681
  fe("Cancelado.");
3323
3682
  return;
3324
3683
  }
3325
- await doInstallAll(manifest, paths);
3684
+ if (!await doInstallAll(manifest, paths))
3685
+ process.exitCode = 1;
3326
3686
  printPostInstallSteps();
3327
- fe("Instalación completada.");
3687
+ fe(process.exitCode ? "Instalación parcial." : "Instalación completada.");
3328
3688
  }
3329
3689
  async function runAddAgentCommand() {
3330
3690
  we(" OpenCode Installer ");
@@ -3382,8 +3742,10 @@ async function runInstallStackCommand() {
3382
3742
  return;
3383
3743
  }
3384
3744
  ensureToolDirs(paths.tools, ["codegraph", "engram", "context7"]);
3385
- await doInstallStack(paths.tools);
3386
- 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.");
3387
3749
  }
3388
3750
  async function runUninstallStackCommand() {
3389
3751
  we(" OpenCode Installer — Stack ");
@@ -3443,7 +3805,7 @@ async function runUninstallAgentCommand(name) {
3443
3805
  const { readLockfile: readLockfile2 } = await Promise.resolve().then(() => (init_lockfile(), exports_lockfile));
3444
3806
  const lockfile = readLockfile2(paths.root);
3445
3807
  if (lockfile && Object.keys(lockfile.agents).length > 0) {
3446
- const { default: prompts } = await Promise.resolve().then(() => (init_dist2(), exports_dist));
3808
+ const prompts = exports_dist;
3447
3809
  const installed = Object.keys(lockfile.agents);
3448
3810
  const options = installed.map((n) => ({
3449
3811
  value: n,
@@ -3478,7 +3840,7 @@ async function runUninstallCommandCommand(name) {
3478
3840
  const { readLockfile: readLockfile2 } = await Promise.resolve().then(() => (init_lockfile(), exports_lockfile));
3479
3841
  const lockfile = readLockfile2(paths.root);
3480
3842
  if (lockfile && Object.keys(lockfile.commands).length > 0) {
3481
- const { default: prompts } = await Promise.resolve().then(() => (init_dist2(), exports_dist));
3843
+ const prompts = exports_dist;
3482
3844
  const installed = Object.keys(lockfile.commands);
3483
3845
  const options = installed.map((n) => ({
3484
3846
  value: n,
@@ -3513,7 +3875,7 @@ async function runUninstallSkillCommand(name) {
3513
3875
  const { readLockfile: readLockfile2 } = await Promise.resolve().then(() => (init_lockfile(), exports_lockfile));
3514
3876
  const lockfile = readLockfile2(paths.root);
3515
3877
  if (lockfile && lockfile.skills && Object.keys(lockfile.skills).length > 0) {
3516
- const { default: prompts } = await Promise.resolve().then(() => (init_dist2(), exports_dist));
3878
+ const prompts = exports_dist;
3517
3879
  const installed = Object.keys(lockfile.skills);
3518
3880
  const options = installed.map((n) => ({
3519
3881
  value: n,
@@ -3548,7 +3910,7 @@ async function runUninstallMcpCommand(name) {
3548
3910
  const { readLockfile: readLockfile2 } = await Promise.resolve().then(() => (init_lockfile(), exports_lockfile));
3549
3911
  const lockfile = readLockfile2(paths.root);
3550
3912
  if (lockfile && lockfile.mcpServers && Object.keys(lockfile.mcpServers).length > 0) {
3551
- const { default: prompts } = await Promise.resolve().then(() => (init_dist2(), exports_dist));
3913
+ const prompts = exports_dist;
3552
3914
  const installed = Object.keys(lockfile.mcpServers);
3553
3915
  const options = installed.map((n) => ({
3554
3916
  value: n,