ostacky 0.7.4 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -293,6 +293,36 @@ var init_security = __esm(() => {
293
293
  });
294
294
 
295
295
  // src/fs.ts
296
+ var exports_fs = {};
297
+ __export(exports_fs, {
298
+ USER_AGENT: () => USER_AGENT,
299
+ checkBunAvailability: () => checkBunAvailability,
300
+ computeTreeHash: () => computeTreeHash,
301
+ copyDirRecursive: () => copyDirRecursive,
302
+ createOpenCodeDir: () => createOpenCodeDir,
303
+ detectPlatformTarget: () => detectPlatformTarget,
304
+ downloadAndExtract: () => downloadAndExtract,
305
+ downloadAndExtractWithRetry: () => downloadAndExtractWithRetry,
306
+ downloadToFile: () => downloadToFile,
307
+ downloadWithRetry: () => downloadWithRetry,
308
+ ensureOpenCodePaths: () => ensureOpenCodePaths,
309
+ ensureToolDirs: () => ensureToolDirs,
310
+ findBinaryInDir: () => findBinaryInDir,
311
+ findExecutablePath: () => findExecutablePath,
312
+ findOpenCodeDir: () => findOpenCodeDir,
313
+ findProjectRoot: () => findProjectRoot,
314
+ getBunInstallCommand: () => getBunInstallCommand,
315
+ getCommandInvocation: () => getCommandInvocation,
316
+ getEngramReleaseTarget: () => getEngramReleaseTarget,
317
+ getExecutableName: () => getExecutableName,
318
+ getExecutableNames: () => getExecutableNames,
319
+ getGlobalOpenCodeDir: () => getGlobalOpenCodeDir,
320
+ getOpenCodeDirForScope: () => getOpenCodeDirForScope,
321
+ isCommandAvailable: () => isCommandAvailable,
322
+ parseScopeArg: () => parseScopeArg,
323
+ promoteStagedDirectory: () => promoteStagedDirectory,
324
+ shouldRetryDownload: () => shouldRetryDownload
325
+ });
296
326
  import {
297
327
  existsSync,
298
328
  mkdirSync,
@@ -366,6 +396,22 @@ function getOpenCodeDirForScope(scope, cwd = process.cwd()) {
366
396
  }
367
397
  return getGlobalOpenCodeDir();
368
398
  }
399
+ function parseScopeArg(argv = process.argv) {
400
+ for (let i = 0;i < argv.length; i++) {
401
+ const arg = argv[i];
402
+ if (arg === "--scope" && i + 1 < argv.length) {
403
+ const v3 = argv[i + 1];
404
+ if (v3 === "local" || v3 === "global" || v3 === "auto")
405
+ return v3;
406
+ }
407
+ if (arg.startsWith("--scope=")) {
408
+ const v3 = arg.split("=")[1];
409
+ if (v3 === "local" || v3 === "global" || v3 === "auto")
410
+ return v3;
411
+ }
412
+ }
413
+ return null;
414
+ }
369
415
  function ensureOpenCodePaths(opencodeDir) {
370
416
  const paths = {
371
417
  root: opencodeDir,
@@ -389,6 +435,9 @@ function ensureToolDirs(toolsDir, toolNames) {
389
435
  mkdirSync(dir, { recursive: true });
390
436
  }
391
437
  }
438
+ function createOpenCodeDir(baseDir) {
439
+ return ensureOpenCodePaths(join(baseDir, ".opencode"));
440
+ }
392
441
  function copyDirRecursive(src, dest, skipGenerated = false) {
393
442
  if (!existsSync(dest))
394
443
  mkdirSync(dest, { recursive: true });
@@ -449,6 +498,44 @@ function findExecutablePath(cmd) {
449
498
  return null;
450
499
  }
451
500
  }
501
+ function getBunInstallCommand() {
502
+ const platform = process.platform;
503
+ if (platform === "darwin" || platform === "linux") {
504
+ return {
505
+ command: "curl -fsSL https://bun.com/install | bash",
506
+ note: platform === "linux" ? "Requires 'unzip' package (sudo apt install unzip)" : undefined
507
+ };
508
+ }
509
+ if (platform === "win32") {
510
+ return {
511
+ command: 'powershell -c "irm bun.sh/install.ps1|iex"',
512
+ note: "Requires Windows 10 v1809 or later"
513
+ };
514
+ }
515
+ return {
516
+ command: "npm install -g bun",
517
+ note: "Cross-platform fallback"
518
+ };
519
+ }
520
+ function checkBunAvailability() {
521
+ const bunPath = findExecutablePath("bun");
522
+ if (bunPath) {
523
+ let version;
524
+ try {
525
+ version = execFileSync(bunPath, ["--version"], {
526
+ encoding: "utf-8",
527
+ stdio: ["pipe", "pipe", "pipe"]
528
+ }).trim();
529
+ } catch {}
530
+ return { available: true, path: bunPath, version };
531
+ }
532
+ const { command, note } = getBunInstallCommand();
533
+ return {
534
+ available: false,
535
+ installCommand: command,
536
+ installNote: note
537
+ };
538
+ }
452
539
  function detectPlatformTarget(platform = process.platform, arch = process.arch) {
453
540
  let os;
454
541
  let cpu;
@@ -570,6 +657,23 @@ function downloadToFile(url, dest, timeoutMs = 180000) {
570
657
  });
571
658
  });
572
659
  }
660
+ async function downloadWithRetry(url, dest, maxRetries = 2, timeoutMs = 180000) {
661
+ let lastError = null;
662
+ for (let attempt = 0;attempt <= maxRetries; attempt++) {
663
+ try {
664
+ await downloadToFile(url, dest, timeoutMs);
665
+ return;
666
+ } catch (err) {
667
+ lastError = err;
668
+ if (attempt < maxRetries && shouldRetryDownload(lastError)) {
669
+ const delay = 1000 * Math.pow(2, attempt);
670
+ console.error(`[download] Intento ${attempt + 1} falló: ${lastError.message}. Reintentando en ${delay}ms...`);
671
+ await new Promise((r2) => setTimeout(r2, delay));
672
+ }
673
+ }
674
+ }
675
+ throw lastError;
676
+ }
573
677
  async function downloadAndExtract(url, destDir, stripComponents = 1, timeoutMs = 180000) {
574
678
  const tmp = join(dirname(destDir), `.${basename(destDir)}.download-${Date.now()}-${process.pid}`);
575
679
  if (!existsSync(tmp))
@@ -640,31 +744,31 @@ var init_fs = __esm(() => {
640
744
  var manifest_default;
641
745
  var init_manifest = __esm(() => {
642
746
  manifest_default = {
643
- version: "0.7.4",
747
+ version: "0.8.0",
644
748
  repo: "JaimeHoracio/Ostacky",
645
- tag: "v0.7.4",
749
+ tag: "v0.8.0",
646
750
  agents: [
647
751
  {
648
752
  name: "ostacky",
649
753
  file: "assets/agents/ostacky.md",
650
- 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. v0.7.4: prune de skills obsoletas, lastHandoff, getAvailableTransitions, consecutiveFailures real, mem_session_summary automático al cierre.",
651
- version: "0.7.4",
652
- sha256: "ffda231d1a9df1693f32460bdb6811077f7f53ba7902b2616d82231a3d6d43bb"
754
+ 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. v0.8.0: prune de skills obsoletas, lastHandoff, getAvailableTransitions, consecutiveFailures real, mem_session_summary automático al cierre.",
755
+ version: "0.8.0",
756
+ sha256: "d9f94bb05a33a98d6ff0ea0b56c8eb6c3c8d456d1de1ccaac3f76ee2150b3c7b"
653
757
  }
654
758
  ],
655
759
  commands: [
656
760
  {
657
761
  name: "install-stack",
658
762
  file: "assets/commands/install-stack.md",
659
- description: "Instala el stack tecnológico del proyecto (CodeGraph, skills, OpenSpec, Engram, Context7, controller MCP con SDK oficial). v0.7.4: Paso 1.5 controller expandido con verificación post-instalación y troubleshooting.",
660
- version: "0.7.4",
661
- sha256: "6887499074a82c3b4538e38ca501290cacd3afad676bd127662fed77e268f299"
763
+ description: "Instala el stack tecnológico del proyecto (CodeGraph, skills, OpenSpec, Engram, controller plugin). v0.8.0: controller plugin como alma hard-gate, Context7 removido del stack.",
764
+ version: "0.8.0",
765
+ sha256: "1a8acef8dd59d80aa54fa0febb4bd86a31ed615dea5257ea7fa8ed4fd51836a5"
662
766
  },
663
767
  {
664
768
  name: "opsx-sync",
665
769
  file: "assets/commands/opsx-sync.md",
666
770
  description: "Sincroniza delta specs del change activo sin inicializar CodeGraph si ya existe índice",
667
- version: "0.7.4",
771
+ version: "0.8.0",
668
772
  sha256: "fe0158478f2ca63b315037a85fc1632b77868532e319af6c7384285441767d64"
669
773
  }
670
774
  ],
@@ -672,15 +776,15 @@ var init_manifest = __esm(() => {
672
776
  {
673
777
  name: "ostacky-controller",
674
778
  file: "assets/mcp/ostacky-controller/",
675
- description: "Máquina de estados persistida con @modelcontextprotocol/server SDK. v0.7.4: 22 tools (incluye set_handoff, get_handoff, clear_handoff, get_available_transitions funcional). Bugfixes: consecutiveFailures real, lastHandoff state, defaultChoice persistido. Robustez: degraded mode automático tras 3 fallos, persistence condicional para Nivel 0, prune de skills obsoletas.",
676
- version: "0.7.4",
677
- sha256: "4f86b6829293024caeb3d09c83b61aee158c383a7bb053a49e5a33c7c55862d1"
779
+ description: "Máquina de estados persistida con @modelcontextprotocol/server SDK. v0.8.0: 22 tools (incluye set_handoff, get_handoff, clear_handoff, get_available_transitions funcional). Bugfixes: consecutiveFailures real, lastHandoff state, defaultChoice persistido. Robustez: degraded mode automático tras 3 fallos, persistence condicional para Nivel 0, prune de skills obsoletas.",
780
+ version: "0.8.0",
781
+ sha256: "5c4787001143ad517714e9c44f85b20fac00ba4146631d68486a90b93aa58dcd"
678
782
  },
679
783
  {
680
784
  name: "openspec",
681
785
  file: "assets/mcp/openspec/",
682
786
  description: "MCP server local para OpenSpec - proposal, apply, archive, sync de cambios",
683
- version: "0.7.4",
787
+ version: "0.8.0",
684
788
  sha256: "fa4be28bfc1e75db8f1a037e2580f04a60066c80e8e5934e90e1041020d04609"
685
789
  }
686
790
  ],
@@ -689,105 +793,105 @@ var init_manifest = __esm(() => {
689
793
  name: "brainstorming",
690
794
  file: "assets/skills/brainstorming/SKILL.md",
691
795
  description: "Skill unificado de pensamiento con dos modos: creative-design (producción de diseño → transición a implementación directa o openspec-propose) y open-exploration (exploración libre)",
692
- version: "0.7.4",
693
- sha256: "7b0020f31f346d8f2070219930cfb9341135d40941195f0ea50c3bd7f4a42990"
796
+ version: "0.8.0",
797
+ sha256: "87f8d6ed28205f9272792d3865d8cd3232ab5e511a604d6d63d41e3a02a5f422"
694
798
  },
695
799
  {
696
800
  name: "execution-mode-evaluation",
697
801
  file: "assets/skills/execution-mode-evaluation/SKILL.md",
698
802
  description: "Skill de análisis de modo de ejecución — output reconciliado con controller snapshot contract (recommendation field)",
699
- version: "0.7.4",
700
- sha256: "e17f1e0309572841dc1fa537b1f32c7468eb70b3acf453b9ff5cc4fa8d94fd39"
803
+ version: "0.8.0",
804
+ sha256: "7b89dda29927c88f1eb13ffcea541a12423384c172f66c4f3d9b61efe0c7a163"
701
805
  },
702
806
  {
703
807
  name: "tdd",
704
808
  file: "assets/skills/tdd/SKILL.md",
705
809
  description: "Skill de test-driven development (Superpowers)",
706
- version: "0.7.4",
810
+ version: "0.8.0",
707
811
  sha256: "aa412298980b7826165c211145c1b8e9135f68f36247bb3cb96d0a0eae274486"
708
812
  },
709
813
  {
710
814
  name: "subagent-driven-development",
711
815
  file: "assets/skills/subagent-driven-development/SKILL.md",
712
816
  description: "Skill de ejecución con subagentes (Superpowers) — ejecuta solo después de confirmación del coordinador Ostacky",
713
- version: "0.7.4",
817
+ version: "0.8.0",
714
818
  sha256: "1a42d714a9a13faf05f0bf7b580e8d837c2e77a5633839542ccce603023419e8"
715
819
  },
716
820
  {
717
821
  name: "dispatching-parallel-agents",
718
822
  file: "assets/skills/dispatching-parallel-agents/SKILL.md",
719
823
  description: "Skill de dispatch paralelo de agentes (Superpowers)",
720
- version: "0.7.4",
824
+ version: "0.8.0",
721
825
  sha256: "3c8a66d51ae2e719e877d02c3dac32bd804722c3bb9227c258ecae78252a20ab"
722
826
  },
723
827
  {
724
828
  name: "review",
725
829
  file: "assets/skills/review/SKILL.md",
726
830
  description: "Skill de revisión de código (Superpowers)",
727
- version: "0.7.4",
831
+ version: "0.8.0",
728
832
  sha256: "b19650ed4d1d4d9857a4dd5b7e08e91328a1a1fc9c45bcc2fb600fa9d0213279"
729
833
  },
730
834
  {
731
835
  name: "receiving-code-review",
732
836
  file: "assets/skills/receiving-code-review/SKILL.md",
733
837
  description: "Skill de recibir y procesar feedback de code review",
734
- version: "0.7.4",
838
+ version: "0.8.0",
735
839
  sha256: "d761e884e71d8d3476ac734d287cae403a4024506a7d12e7361a448217c0a831"
736
840
  },
737
841
  {
738
842
  name: "openspec-propose",
739
843
  file: "assets/skills/openspec-propose/SKILL.md",
740
844
  description: "Skill de generación de proposal (OpenSpec)",
741
- version: "0.7.4",
845
+ version: "0.8.0",
742
846
  sha256: "bb59100b9fd3c9f9a1ec6509fa975ec55bf7fc737df4fe73bb3e9bbc217b83f7"
743
847
  },
744
848
  {
745
849
  name: "openspec-apply-change",
746
850
  file: "assets/skills/openspec-apply-change/SKILL.md",
747
851
  description: "Skill de aplicación de change (OpenSpec)",
748
- version: "0.7.4",
852
+ version: "0.8.0",
749
853
  sha256: "dfc823bf89fc7505e91ab6dee9c1f004be38a410bd3d88fb67b211b1b6cbb1d0"
750
854
  },
751
855
  {
752
856
  name: "openspec-archive-change",
753
857
  file: "assets/skills/openspec-archive-change/SKILL.md",
754
858
  description: "Skill de archivo de change (OpenSpec)",
755
- version: "0.7.4",
859
+ version: "0.8.0",
756
860
  sha256: "16e4b561de7747283663fed602e506abf502452c49a8d4b86d7a5539c40f0195"
757
861
  },
758
862
  {
759
863
  name: "openspec-explore",
760
864
  file: "assets/skills/openspec-explore/SKILL.md",
761
865
  description: "Modo explore para OpenSpec — thinking partner para explorar ideas, investigar problemas y clarificar requisitos antes/durante un cambio",
762
- version: "0.7.4",
866
+ version: "0.8.0",
763
867
  sha256: "37ae4aaf17ea71a395bab6dc4d9d61b9a49d7910f6692535ae8553244c46880b"
764
868
  },
765
869
  {
766
870
  name: "using-git-worktrees",
767
871
  file: "assets/skills/using-git-worktrees/SKILL.md",
768
872
  description: "Skill de uso de git worktrees para aislamiento de trabajo",
769
- version: "0.7.4",
873
+ version: "0.8.0",
770
874
  sha256: "93341bc1b7c053618a8b6dc07e3615b77990d7b549a0201f5835d95fef67ce13"
771
875
  },
772
876
  {
773
877
  name: "using-superpowers",
774
878
  file: "assets/skills/using-superpowers/SKILL.md",
775
879
  description: "Skill de orquestación de Superpowers skills",
776
- version: "0.7.4",
880
+ version: "0.8.0",
777
881
  sha256: "7e54536f96d2a379185a10bfc1e970850caa2561b6d8aca7080f0defea0381a4"
778
882
  },
779
883
  {
780
884
  name: "writing-skills",
781
885
  file: "assets/skills/writing-skills/SKILL.md",
782
886
  description: "Skill de creación y edición de skills",
783
- version: "0.7.4",
887
+ version: "0.8.0",
784
888
  sha256: "3d76b906cee518a2b809febb70db95697a35b9f368986bb504b4120c3bfb437a"
785
889
  },
786
890
  {
787
891
  name: "graceful-degradation",
788
892
  file: "assets/skills/graceful-degradation/SKILL.md",
789
893
  description: "Skill de degradación graceful cuando múltiples tools están indisponibles",
790
- version: "0.7.4",
894
+ version: "0.8.0",
791
895
  sha256: "40f929e8032b70d51b3548bddcc383b931d6044fd9d4acce8a5b9f7acd014f59"
792
896
  }
793
897
  ]
@@ -829,6 +933,19 @@ var init_cache = __esm(() => {
829
933
  });
830
934
 
831
935
  // src/github.ts
936
+ var exports_github = {};
937
+ __export(exports_github, {
938
+ BUNDLED_MCP_DIR: () => BUNDLED_MCP_DIR,
939
+ BUNDLED_SKILLS_DIR: () => BUNDLED_SKILLS_DIR,
940
+ PACKAGE_ROOT: () => PACKAGE_ROOT,
941
+ downloadFile: () => downloadFile,
942
+ fetchLatestManifest: () => fetchLatestManifest,
943
+ fetchLatestReleaseTag: () => fetchLatestReleaseTag,
944
+ fetchManifest: () => fetchManifest,
945
+ getBundledMcpPath: () => getBundledMcpPath,
946
+ getBundledSkillPath: () => getBundledSkillPath,
947
+ getRawUrl: () => getRawUrl
948
+ });
832
949
  import { fileURLToPath } from "url";
833
950
  import { dirname as dirname3, join as join3 } from "path";
834
951
  function getBundledSkillPath(name) {
@@ -1143,6 +1260,12 @@ function patchOpenCodeConfig(projectRoot = findProjectRoot()) {
1143
1260
  delete config.plugin;
1144
1261
  changed = true;
1145
1262
  }
1263
+ if (config.mcp && typeof config.mcp === "object" && "context7" in config.mcp) {
1264
+ delete config.mcp.context7;
1265
+ if (Object.keys(config.mcp).length === 0)
1266
+ delete config.mcp;
1267
+ changed = true;
1268
+ }
1146
1269
  if (changed) {
1147
1270
  writeOpenCodeConfig(configPath, config);
1148
1271
  return { success: true, message: "Config actualizada (plugin legacy eliminado)" };
@@ -1162,7 +1285,6 @@ __export(exports_stack, {
1162
1285
  installCodeGraph: () => installCodeGraph,
1163
1286
  installEngram: () => installEngram,
1164
1287
  installStack: () => installStack,
1165
- setupContext7: () => setupContext7,
1166
1288
  setupOpenSpec: () => setupOpenSpec,
1167
1289
  uninstallEngramConfig: () => uninstallEngramConfig,
1168
1290
  uninstallStackConfig: () => uninstallStackConfig,
@@ -1216,6 +1338,15 @@ function copyEngramPlugin(projectRoot) {
1216
1338
  mkdirSync4(pluginsDir, { recursive: true });
1217
1339
  copyFileSync3(pluginSource, join7(pluginsDir, "engram.ts"));
1218
1340
  }
1341
+ function copyOstackyControllerPlugin(projectRoot) {
1342
+ const pluginSource = join7(PACKAGE_ROOT, "assets", "plugins", "ostacky-plugin.ts");
1343
+ const pluginsDir = join7(projectRoot, ".opencode", "plugins");
1344
+ if (!existsSync6(pluginSource)) {
1345
+ throw new Error(`Plugin bundleado de OstackyController no encontrado: ${pluginSource}`);
1346
+ }
1347
+ mkdirSync4(pluginsDir, { recursive: true });
1348
+ copyFileSync3(pluginSource, join7(pluginsDir, "ostacky-plugin.ts"));
1349
+ }
1219
1350
  function buildEngramDownloadUrl(tag, platform = process.platform, arch = process.arch) {
1220
1351
  const target = getEngramReleaseTarget(platform, arch);
1221
1352
  if (!target)
@@ -1439,6 +1570,7 @@ async function installEngram(toolsDir) {
1439
1570
  try {
1440
1571
  runTool(localBin, ["--version"], projectRoot, 1e4);
1441
1572
  copyEngramPlugin(projectRoot);
1573
+ copyOstackyControllerPlugin(projectRoot);
1442
1574
  configureLocalTool(projectRoot, "engram", buildLocalMcpCommand(localBin, ["mcp"]));
1443
1575
  } catch (error) {
1444
1576
  return failAfterExtraction(`Engram fue instalado pero no se pudo verificar o configurar: ${error.message}`);
@@ -1446,44 +1578,15 @@ async function installEngram(toolsDir) {
1446
1578
  archivePromotion?.commit();
1447
1579
  return { success: true, message: "Engram instalado localmente y configurado para OpenCode (MCP + plugin)" };
1448
1580
  }
1449
- function setupContext7(toolsDir) {
1450
- const location = resolveToolInstallLocation(toolsDir);
1451
- const { projectRoot } = location;
1452
- const ctx7ToolDir = join7(location.toolsDir, "context7");
1453
- if (!existsSync6(ctx7ToolDir))
1454
- mkdirSync4(ctx7ToolDir, { recursive: true });
1455
- try {
1456
- ensureMcpEntryAtProjectRoot(projectRoot, "context7", {
1457
- type: "remote",
1458
- url: "https://mcp.context7.com/mcp",
1459
- enabled: true
1460
- });
1461
- } catch (error) {
1462
- return { success: false, message: `No se pudo registrar Context7: ${error.message}` };
1463
- }
1464
- const useBun = isCommandAvailable("bun");
1465
- try {
1466
- const invocation = getCommandInvocation(useBun ? "bunx" : "npx", useBun ? ["ctx7", "setup", "--opencode"] : ["--yes", "ctx7", "setup", "--opencode"]);
1467
- execFileSync3(invocation.command, invocation.args, {
1468
- stdio: "pipe",
1469
- timeout: 60000,
1470
- cwd: projectRoot
1471
- });
1472
- return { success: true, message: "Context7 configurado (MCP + skill instalado)" };
1473
- } catch {
1474
- return {
1475
- success: true,
1476
- message: "Context7 MCP registrado (skill opcional no instalada — corrí `npx ctx7 setup --opencode` manualmente si la querés)"
1477
- };
1478
- }
1479
- }
1480
1581
  async function installStack(toolsDir) {
1481
1582
  const { projectRoot } = resolveToolInstallLocation(toolsDir);
1583
+ try {
1584
+ copyOstackyControllerPlugin(projectRoot);
1585
+ } catch {}
1482
1586
  return {
1483
1587
  codegraph: await installCodeGraph(toolsDir),
1484
1588
  openspec: setupOpenSpec(projectRoot),
1485
1589
  engram: await installEngram(toolsDir),
1486
- context7: setupContext7(toolsDir),
1487
1590
  config: patchOpenCodeConfig(projectRoot)
1488
1591
  };
1489
1592
  }
@@ -1518,7 +1621,7 @@ function uninstallStackConfig(paths) {
1518
1621
  const mcp = config.mcp;
1519
1622
  let changed = false;
1520
1623
  if (mcp) {
1521
- for (const name of ["codegraph", "context7", "engram"]) {
1624
+ for (const name of ["codegraph", "engram", "context7"]) {
1522
1625
  if (name in mcp) {
1523
1626
  delete mcp[name];
1524
1627
  removed.push(`mcp.${name}`);
@@ -1588,7 +1691,7 @@ var init_stack = __esm(() => {
1588
1691
  // package.json
1589
1692
  var package_default = {
1590
1693
  name: "ostacky",
1591
- version: "0.7.4",
1694
+ version: "0.8.0",
1592
1695
  description: "Instalador interactivo de agentes y comandos para OpenCode",
1593
1696
  type: "module",
1594
1697
  bin: {
@@ -2763,7 +2866,7 @@ async function probeMcpServer(nodeExecutable, serverPath, cwd, statePath, option
2763
2866
  params: {
2764
2867
  protocolVersion: "2025-03-26",
2765
2868
  capabilities: {},
2766
- clientInfo: { name: "ostacky-installer", version: "0.7.4" }
2869
+ clientInfo: { name: "ostacky-installer", version: "0.8.0" }
2767
2870
  }
2768
2871
  });
2769
2872
  });
@@ -3277,11 +3380,6 @@ async function doInstallStack(toolsDir, projectRoot) {
3277
3380
  spin.stop(eng.success ? `✓ ${eng.message}` : `✗ ${eng.message}`);
3278
3381
  if (!eng.success)
3279
3382
  allOk = false;
3280
- spin.start("Configurando Context7...");
3281
- const ctx = setupContext7(toolsDir);
3282
- spin.stop(ctx.success ? `✓ ${ctx.message}` : `✗ ${ctx.message}`);
3283
- if (!ctx.success)
3284
- allOk = false;
3285
3383
  spin.start("Verificando configuración...");
3286
3384
  const { patchOpenCodeConfig: patchOpenCodeConfig2 } = await Promise.resolve().then(() => (init_config(), exports_config));
3287
3385
  const cfg = patchOpenCodeConfig2(resolvedProjectRoot);
@@ -3298,9 +3396,9 @@ async function doInstallAll(manifest, paths) {
3298
3396
  let errors = 0;
3299
3397
  const isGlobal = isGlobalScope(paths);
3300
3398
  if (!isGlobal) {
3301
- ensureToolDirs(paths.tools, ["codegraph", "engram", "context7"]);
3399
+ ensureToolDirs(paths.tools, ["codegraph", "engram"]);
3302
3400
  } else {
3303
- v2.info("Scope global detectado: el stack (CodeGraph/Engram) permanece siempre en <proyecto>/.opencode/tools — se omite instalación de stack global.");
3401
+ v2.info("Scope global detectado: el stack (CodeGraph/Engram) y plugins (ostacky-controller, engram) permanecen siempre en <proyecto>/.opencode — se omite instalación de stack global.");
3304
3402
  v2.info("Para instalar el stack, ejecutá 'npx ostacky install-stack --scope local' dentro de cada proyecto.");
3305
3403
  }
3306
3404
  for (const agent of manifest.agents) {
@@ -3347,6 +3445,42 @@ async function doInstallAll(manifest, paths) {
3347
3445
  errors++;
3348
3446
  }
3349
3447
  }
3448
+ try {
3449
+ const { copyFileSync: copyFileSync4, mkdirSync: mkdirSync5, existsSync: existsSync8 } = await import("fs");
3450
+ const { join: join9 } = await import("path");
3451
+ const { PACKAGE_ROOT: PACKAGE_ROOT2 } = await Promise.resolve().then(() => (init_github(), exports_github));
3452
+ const { findProjectRoot: findProjectRoot3 } = await Promise.resolve().then(() => (init_fs(), exports_fs));
3453
+ const src = join9(PACKAGE_ROOT2, "assets", "plugins", "ostacky-plugin.ts");
3454
+ const dest = join9(paths.plugins, "ostacky-plugin.ts");
3455
+ if (existsSync8(src)) {
3456
+ mkdirSync5(paths.plugins, { recursive: true });
3457
+ copyFileSync4(src, dest);
3458
+ }
3459
+ const legacySrc = join9(PACKAGE_ROOT2, "assets", "plugins", "ostacky-controller.ts");
3460
+ if (!existsSync8(src) && existsSync8(legacySrc)) {
3461
+ mkdirSync5(paths.plugins, { recursive: true });
3462
+ copyFileSync4(legacySrc, join9(paths.plugins, "ostacky-controller.ts"));
3463
+ }
3464
+ const srcEng = join9(PACKAGE_ROOT2, "assets", "plugins", "engram.ts");
3465
+ const destEng = join9(paths.plugins, "engram.ts");
3466
+ if (existsSync8(srcEng)) {
3467
+ mkdirSync5(paths.plugins, { recursive: true });
3468
+ copyFileSync4(srcEng, destEng);
3469
+ }
3470
+ if (isGlobal) {
3471
+ try {
3472
+ const projRoot = findProjectRoot3();
3473
+ const localPlugins = join9(projRoot, ".opencode", "plugins");
3474
+ mkdirSync5(localPlugins, { recursive: true });
3475
+ if (existsSync8(src))
3476
+ copyFileSync4(src, join9(localPlugins, "ostacky-plugin.ts"));
3477
+ else if (existsSync8(legacySrc))
3478
+ copyFileSync4(legacySrc, join9(localPlugins, "ostacky-controller.ts"));
3479
+ if (existsSync8(srcEng))
3480
+ copyFileSync4(srcEng, join9(localPlugins, "engram.ts"));
3481
+ } catch {}
3482
+ }
3483
+ } catch {}
3350
3484
  let stackOk = true;
3351
3485
  let missingTools = [];
3352
3486
  if (isGlobal) {
@@ -3893,7 +4027,7 @@ async function runInteractiveMenu(scope) {
3893
4027
  { value: "command", label: "Instalar command" },
3894
4028
  { value: "skill", label: "Instalar skill" },
3895
4029
  { value: "mcp", label: "Instalar MCP server" },
3896
- { value: "stack", label: "Instalar stack de herramientas (CodeGraph, Engram, Context7)" },
4030
+ { value: "stack", label: "Instalar stack de herramientas (CodeGraph, Engram)" },
3897
4031
  { value: "update", label: "Actualizar instalación" },
3898
4032
  { value: "uninstall", label: "Desinstalar" },
3899
4033
  { value: "exit", label: "Salir" }
@@ -3934,7 +4068,7 @@ async function runInteractiveMenu(scope) {
3934
4068
  fe("Cancelado.");
3935
4069
  break;
3936
4070
  }
3937
- ensureToolDirs(paths.tools, ["codegraph", "engram", "context7"]);
4071
+ ensureToolDirs(paths.tools, ["codegraph", "engram"]);
3938
4072
  const stackOk = await doInstallStack(paths.tools, dirname7(paths.root));
3939
4073
  if (!stackOk)
3940
4074
  process.exitCode = 1;
@@ -4037,7 +4171,7 @@ async function runInstallStackCommand(scope) {
4037
4171
  process.exitCode = 1;
4038
4172
  return;
4039
4173
  }
4040
- ensureToolDirs(paths.tools, ["codegraph", "engram", "context7"]);
4174
+ ensureToolDirs(paths.tools, ["codegraph", "engram"]);
4041
4175
  const stackOk = await doInstallStack(paths.tools, dirname7(paths.root));
4042
4176
  if (!stackOk)
4043
4177
  process.exitCode = 1;
@@ -4051,7 +4185,7 @@ async function runUninstallStackCommand(scope) {
4051
4185
  return;
4052
4186
  }
4053
4187
  const confirm = await me({
4054
- message: "¿Remover la configuración del stack (CodeGraph, Engram, Context7) del proyecto? Los binarios globales no se tocan."
4188
+ message: "¿Remover la configuración del stack (CodeGraph, Engram) del proyecto? Los binarios globales no se tocan."
4055
4189
  });
4056
4190
  onCancel(confirm);
4057
4191
  if (!confirm) {
@@ -4238,12 +4372,12 @@ ostacky — Instalador de agentes, comandos, skills y MCPs para OpenCode
4238
4372
 
4239
4373
  Uso:
4240
4374
  npx ostacky [--scope local|global|auto] Menú interactivo (instalación completa, pregunta local vs global, default local)
4241
- npx ostacky install [--scope local|global|auto] Instalar TODO (agente + skills + MCPs + CodeGraph + OpenSpec + Engram + Context7)
4375
+ npx ostacky install [--scope local|global|auto] Instalar TODO (agente + skills + MCPs + CodeGraph + OpenSpec + Engram)
4242
4376
  npx ostacky add agent [--scope local|global|auto] Agregar agente(s)
4243
4377
  npx ostacky add command [--scope ...] Agregar command(s)
4244
4378
  npx ostacky add skill [--scope ...] Agregar skill(s)
4245
4379
  npx ostacky add mcp [--scope ...] Agregar MCP server(s)
4246
- npx ostacky install-stack [--scope local|auto] Instalar solo el stack de herramientas (CodeGraph, OpenSpec, Engram, Context7) — global bloquea con error
4380
+ npx ostacky install-stack [--scope local|auto] Instalar solo el stack de herramientas (CodeGraph, OpenSpec, Engram) — global bloquea con error
4247
4381
  npx ostacky uninstall-stack [--scope local|global|auto] Remover la configuración del stack del proyecto
4248
4382
  npx ostacky doctor Diagnostica locks, tools, state health
4249
4383
  npx ostacky status [--json] Muestra estado del controller sin MCP
@@ -4262,7 +4396,7 @@ Scope:
4262
4396
  --scope auto Elige local si existe .opencode o .git, si no global
4263
4397
  Sin flag Pregunta interactiva local (default) vs global
4264
4398
  `.trim();
4265
- function parseScopeArg(argv = process.argv) {
4399
+ function parseScopeArg2(argv = process.argv) {
4266
4400
  for (let i = 0;i < argv.length; i++) {
4267
4401
  const arg = argv[i];
4268
4402
  if (arg === "--scope" && i + 1 < argv.length) {
@@ -4292,7 +4426,7 @@ function withoutScopeArgs(argv) {
4292
4426
  }
4293
4427
  return out;
4294
4428
  }
4295
- var scope = parseScopeArg();
4429
+ var scope = parseScopeArg2();
4296
4430
  var argvNoScope = withoutScopeArgs(process.argv);
4297
4431
  var [, , cmd, subcmd] = argvNoScope;
4298
4432
  async function runDoctorCommand() {
@@ -4312,14 +4446,30 @@ async function runDoctorCommand() {
4312
4446
  hasError = true;
4313
4447
  }
4314
4448
  };
4449
+ const pluginPaths = [
4450
+ join11(cwd, "assets", "plugins", "ostacky-plugin.ts"),
4451
+ join11(opencodeDir, "plugins", "ostacky-plugin.ts"),
4452
+ join11(cwd, ".opencode", "plugins", "ostacky-plugin.ts"),
4453
+ join11(cwd, "assets", "plugins", "ostacky-controller.ts"),
4454
+ join11(opencodeDir, "plugins", "ostacky-controller.ts"),
4455
+ join11(cwd, ".opencode", "plugins", "ostacky-controller.ts")
4456
+ ];
4457
+ const pluginActive = pluginPaths.some((p2) => existsSync8(p2));
4315
4458
  try {
4316
4459
  if (!existsSync8(statePath)) {
4317
- check("controller: state file missing", false, true);
4460
+ if (pluginActive)
4461
+ console.log(`✅ controller: plugin active (no state yet)`);
4462
+ else
4463
+ check("controller: state file missing", false, true);
4318
4464
  } else {
4319
4465
  const stat = statSync3(statePath);
4320
4466
  const raw = readFileSync6(statePath, "utf-8");
4321
4467
  const parsed = JSON.parse(raw);
4322
- check(`controller: OK (rev ${parsed.revision || 0} state ${parsed.state || "unknown"})`, true);
4468
+ if (pluginActive) {
4469
+ console.log(`✅ controller: plugin active (rev ${parsed.revision || 0} state ${parsed.state || "unknown"})`);
4470
+ } else {
4471
+ check(`controller: OK (rev ${parsed.revision || 0} state ${parsed.state || "unknown"})`, true);
4472
+ }
4323
4473
  if (parsed.degraded) {
4324
4474
  console.log("⚠️ degraded: true (persistido)");
4325
4475
  hasWarn = true;