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