@oeronteros-1/opencode-orchestra 1.0.22 → 1.0.24

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.
Files changed (67) hide show
  1. package/README.md +19 -5
  2. package/dashboard-dist/assets/index-Dc5lp8wX.js +124 -0
  3. package/dashboard-dist/index.html +1 -1
  4. package/dist/agents/build.js +4 -0
  5. package/dist/agents/build.js.map +1 -1
  6. package/dist/agents/editor.d.ts +3 -0
  7. package/dist/agents/editor.js +12 -0
  8. package/dist/agents/editor.js.map +1 -0
  9. package/dist/agents/integrator.d.ts +3 -0
  10. package/dist/agents/integrator.js +12 -0
  11. package/dist/agents/integrator.js.map +1 -0
  12. package/dist/agents/lead.js +3 -1
  13. package/dist/agents/lead.js.map +1 -1
  14. package/dist/agents/workers.js +1 -6
  15. package/dist/agents/workers.js.map +1 -1
  16. package/dist/cache-refresh.d.ts +42 -0
  17. package/dist/cache-refresh.js +130 -0
  18. package/dist/cache-refresh.js.map +1 -0
  19. package/dist/cli.d.ts +16 -2
  20. package/dist/cli.js +59 -26
  21. package/dist/cli.js.map +1 -1
  22. package/dist/config/schema.d.ts +11 -1
  23. package/dist/config/schema.js +30 -1
  24. package/dist/config/schema.js.map +1 -1
  25. package/dist/dashboard/server.js +2 -2
  26. package/dist/dashboard/server.js.map +1 -1
  27. package/dist/index.js +35 -12
  28. package/dist/index.js.map +1 -1
  29. package/dist/orchestration/ownership.d.ts +7 -0
  30. package/dist/orchestration/ownership.js +45 -0
  31. package/dist/orchestration/ownership.js.map +1 -0
  32. package/dist/orchestration/worktree-adapter.d.ts +3 -0
  33. package/dist/orchestration/worktree-adapter.js +45 -0
  34. package/dist/orchestration/worktree-adapter.js.map +1 -0
  35. package/dist/orchestration/worktrees.d.ts +22 -0
  36. package/dist/orchestration/worktrees.js +27 -0
  37. package/dist/orchestration/worktrees.js.map +1 -0
  38. package/dist/pricing/cost.d.ts +29 -0
  39. package/dist/pricing/cost.js +47 -0
  40. package/dist/pricing/cost.js.map +1 -0
  41. package/dist/pricing/model-match.d.ts +59 -0
  42. package/dist/pricing/model-match.js +134 -0
  43. package/dist/pricing/model-match.js.map +1 -0
  44. package/dist/pricing/openrouter.d.ts +60 -0
  45. package/dist/pricing/openrouter.js +150 -0
  46. package/dist/pricing/openrouter.js.map +1 -0
  47. package/dist/pricing/resolver.d.ts +50 -0
  48. package/dist/pricing/resolver.js +145 -0
  49. package/dist/pricing/resolver.js.map +1 -0
  50. package/dist/prompts/load.js +1 -1
  51. package/dist/prompts/load.js.map +1 -1
  52. package/dist/routing/planner.d.ts +14 -1
  53. package/dist/routing/planner.js +23 -1
  54. package/dist/routing/planner.js.map +1 -1
  55. package/dist/routing/pricing/estimate.d.ts +14 -1
  56. package/dist/routing/pricing/estimate.js +81 -20
  57. package/dist/routing/pricing/estimate.js.map +1 -1
  58. package/dist/telemetry/ledger.d.ts +6 -1
  59. package/dist/telemetry/ledger.js +15 -3
  60. package/dist/telemetry/ledger.js.map +1 -1
  61. package/dist/tools.d.ts +3 -0
  62. package/dist/tools.js +44 -1
  63. package/dist/tools.js.map +1 -1
  64. package/package.json +16 -2
  65. package/prompts/lead.md +1 -0
  66. package/schema/opencode-orchestra.schema.json +23 -1
  67. package/dashboard-dist/assets/index-BZTn_d2K.js +0 -124
@@ -5,7 +5,7 @@
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
6
  <meta name="theme-color" content="#090b10" />
7
7
  <title>Orchestra Control</title>
8
- <script type="module" crossorigin src="/assets/index-BZTn_d2K.js"></script>
8
+ <script type="module" crossorigin src="/assets/index-Dc5lp8wX.js"></script>
9
9
  <link rel="stylesheet" crossorigin href="/assets/index-1lUDKh9b.css">
10
10
  </head>
11
11
  <body>
@@ -2,10 +2,14 @@ import { createJudgeAgent } from "./judge.js";
2
2
  import { createMergeAgent } from "./merge.js";
3
3
  import { createLeadAgent } from "./lead.js";
4
4
  import { createWorkerAgents } from "./workers.js";
5
+ import { createEditorAgent } from "./editor.js";
6
+ import { createIntegratorAgent } from "./integrator.js";
5
7
  export function createAgentSet(config, prompts) {
6
8
  const agents = {
7
9
  "orch-lead": createLeadAgent(config, prompts.lead),
8
10
  ...createWorkerAgents(config),
11
+ "orch-editor": createEditorAgent(config),
12
+ "orch-integrator": createIntegratorAgent(config),
9
13
  "orch-merge": createMergeAgent(config),
10
14
  "orch-judge": createJudgeAgent(config, prompts.judge),
11
15
  };
@@ -1 +1 @@
1
- {"version":3,"file":"build.js","sourceRoot":"","sources":["../../src/agents/build.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAC7C,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAC7C,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAA;AAE3C,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAA;AAOjD,MAAM,UAAU,cAAc,CAAC,MAAuB,EAAE,OAAqB;IAC3E,MAAM,MAAM,GAAa;QACvB,WAAW,EAAE,eAAe,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC;QAClD,GAAG,kBAAkB,CAAC,MAAM,CAAC;QAC7B,YAAY,EAAE,gBAAgB,CAAC,MAAM,CAAC;QACtC,YAAY,EAAE,gBAAgB,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,CAAC;KACtD,CAAA;IACD,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;QACjE,IAAI,MAAM,CAAC,IAAI,CAAC;YAAE,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,GAAG,KAAK,CAAA;IAC9C,CAAC;IACD,OAAO,MAAM,CAAA;AACf,CAAC"}
1
+ {"version":3,"file":"build.js","sourceRoot":"","sources":["../../src/agents/build.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAC7C,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAC7C,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAA;AAE3C,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAA;AACjD,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAC/C,OAAO,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAA;AAOvD,MAAM,UAAU,cAAc,CAAC,MAAuB,EAAE,OAAqB;IAC3E,MAAM,MAAM,GAAa;QACvB,WAAW,EAAE,eAAe,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC;QAClD,GAAG,kBAAkB,CAAC,MAAM,CAAC;QAC7B,aAAa,EAAE,iBAAiB,CAAC,MAAM,CAAC;QACxC,iBAAiB,EAAE,qBAAqB,CAAC,MAAM,CAAC;QAChD,YAAY,EAAE,gBAAgB,CAAC,MAAM,CAAC;QACtC,YAAY,EAAE,gBAAgB,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,CAAC;KACtD,CAAA;IACD,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;QACjE,IAAI,MAAM,CAAC,IAAI,CAAC;YAAE,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,GAAG,KAAK,CAAA;IAC9C,CAAC;IACD,OAAO,MAAM,CAAA;AACf,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { OrchestraConfig } from "../config/schema.js";
2
+ import type { RuntimeAgentConfig } from "./types.js";
3
+ export declare function createEditorAgent(config: OrchestraConfig): RuntimeAgentConfig;
@@ -0,0 +1,12 @@
1
+ import { resolveModel } from "../routing/model-resolver.js";
2
+ export function createEditorAgent(config) {
3
+ const resolved = resolveModel({ pool: config.models.worker.code, capability: "code", budget: config.budget, allowPaid: config.budget === "quality" || config.budget === "ebobo", preferredCosts: config.budget === "eco" || config.budget === "balanced" ? ["free"] : [], preferredTiers: ["worker", "lead", "frontier"] });
4
+ return {
5
+ description: "Isolated implementation worker that edits only its assigned ownership partition in an OpenCode git workspace.",
6
+ mode: "subagent", hidden: true, temperature: 0.15,
7
+ prompt: "Work only inside the isolated worktree assigned by OpenCode. Edit only repository-relative paths in the explicit ownership list. Never touch the parent checkout, shared configuration, lockfiles, or files outside ownership. Run scoped verification, commit all changes, and return base revision, commit, changed files, and tests. Do not delegate. Stop on ownership ambiguity.",
8
+ permission: { "*": "deny", read: "allow", edit: "allow", glob: "allow", grep: "allow", list: "allow", lsp: "allow", bash: "allow", task: "deny", external_directory: "deny" },
9
+ ...(resolved ? { model: resolved.id } : {}),
10
+ };
11
+ }
12
+ //# sourceMappingURL=editor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"editor.js","sourceRoot":"","sources":["../../src/agents/editor.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAA;AAG3D,MAAM,UAAU,iBAAiB,CAAC,MAAuB;IACvD,MAAM,QAAQ,GAAG,YAAY,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,CAAC,MAAM,KAAK,SAAS,IAAI,MAAM,CAAC,MAAM,KAAK,OAAO,EAAE,cAAc,EAAE,MAAM,CAAC,MAAM,KAAK,KAAK,IAAI,MAAM,CAAC,MAAM,KAAK,UAAU,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,cAAc,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,CAAC,CAAA;IAC3T,OAAO;QACL,WAAW,EAAE,+GAA+G;QAC5H,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI;QACjD,MAAM,EAAE,uXAAuX;QAC/X,UAAU,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,kBAAkB,EAAE,MAAM,EAAE;QAC7K,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,QAAQ,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC5C,CAAA;AACH,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { OrchestraConfig } from "../config/schema.js";
2
+ import type { RuntimeAgentConfig } from "./types.js";
3
+ export declare function createIntegratorAgent(config: OrchestraConfig): RuntimeAgentConfig;
@@ -0,0 +1,12 @@
1
+ import { resolveModel } from "../routing/model-resolver.js";
2
+ export function createIntegratorAgent(config) {
3
+ const resolved = resolveModel({ pool: config.models.lead, capability: "reasoning", budget: config.budget, allowPaid: config.budget === "quality" || config.budget === "ebobo", preferredTiers: ["lead", "frontier"] });
4
+ return {
5
+ description: "Deterministic integration worker that validates ownership and integrates isolated editor commits.",
6
+ mode: "subagent", hidden: true, temperature: 0.1,
7
+ prompt: "Integrate validated editor commits in plan-node order. Before cherry-picking, derive changed paths from git and fail closed if any path is unowned, multiply owned, or outside its editor partition. Stop on conflicts; never resolve an ownership conflict autonomously. Run aggregate verification and report commits, files, tests, and retained worktrees. Do not delegate.",
8
+ permission: { "*": "deny", read: "allow", edit: "deny", glob: "allow", grep: "allow", list: "allow", lsp: "allow", bash: "allow", task: "deny", external_directory: "deny" },
9
+ ...(resolved ? { model: resolved.id } : {}),
10
+ };
11
+ }
12
+ //# sourceMappingURL=integrator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"integrator.js","sourceRoot":"","sources":["../../src/agents/integrator.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAA;AAG3D,MAAM,UAAU,qBAAqB,CAAC,MAAuB;IAC3D,MAAM,QAAQ,GAAG,YAAY,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,CAAC,MAAM,KAAK,SAAS,IAAI,MAAM,CAAC,MAAM,KAAK,OAAO,EAAE,cAAc,EAAE,CAAC,MAAM,EAAE,UAAU,CAAC,EAAE,CAAC,CAAA;IACtN,OAAO;QACL,WAAW,EAAE,mGAAmG;QAChH,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,GAAG;QAChD,MAAM,EAAE,iXAAiX;QACzX,UAAU,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,kBAAkB,EAAE,MAAM,EAAE;QAC5K,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,QAAQ,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC5C,CAAA;AACH,CAAC"}
@@ -25,7 +25,7 @@ export function createLeadAgent(config, basePrompt) {
25
25
  return {
26
26
  description: "Primary implementation lead that classifies complex work, dispatches a small specialist team, synthesizes evidence, edits files, and verifies the result.",
27
27
  mode: "primary",
28
- prompt: `${basePrompt.trim()}\n\nExecution protocol: build a dependency DAG; dispatch every currently-ready node concurrently up to the runtime limit; wait for dependencies before releasing downstream nodes; after all evidence nodes finish, call orch-merge exactly once with every result labeled by node id and worker.\n\nEnabled profiles:\n${profileGuide}\n\nRuntime limits: dispatch at most ${config.orchestration.maxWorkers} workers total and at most ${config.orchestration.parallelWorkers} concurrently. Budget mode: ${config.budget}.${config.budget === "ebobo" ? " EBOBO MODE: dispatch the full available specialist roster in parallel, require independent evidence, and always use orch-judge for frontier arbitration." : ""}`,
28
+ prompt: `${basePrompt.trim()}\n\nExecution protocol: build a dependency DAG; dispatch every currently-ready node concurrently up to the runtime limit; wait for dependencies before releasing downstream nodes; after all evidence nodes finish, call orch-merge exactly once with every result labeled by node id and worker. If implementation needs parallel editors, call orchestration_prepare_edit_plan with explicit non-overlapping partitions, then call orchestration_validate_commit for every editor commit before orch-integrator. For editor partitions, resolve one base HEAD SHA, reject overlapping ownership, create one experimental git worktree per editor, dispatch orch-editor nodes only in those worktrees, validate actual git diff and ancestry before calling orch-integrator exactly once, and retain worktrees on failure. Never let parallel editors share a checkout.\n\nEnabled profiles:\n${profileGuide}\n\nRuntime limits: dispatch at most ${config.orchestration.maxWorkers} workers total and at most ${config.orchestration.parallelWorkers} concurrently. Budget mode: ${config.budget}.${config.budget === "ebobo" ? " EBOBO MODE: dispatch the full available specialist roster in parallel, require independent evidence, and always use orch-judge for frontier arbitration." : ""}`,
29
29
  hidden: false,
30
30
  temperature: 0.2,
31
31
  color: "accent",
@@ -46,6 +46,8 @@ export function createLeadAgent(config, basePrompt) {
46
46
  task: {
47
47
  "*": "deny",
48
48
  ...workerPermissions,
49
+ "orch-editor": "allow",
50
+ "orch-integrator": "allow",
49
51
  "orch-merge": "allow",
50
52
  "orch-judge": "allow",
51
53
  },
@@ -1 +1 @@
1
- {"version":3,"file":"lead.js","sourceRoot":"","sources":["../../src/agents/lead.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"lead.js","sourceRoot":"","sources":["../../src/agents/lead.ts"],"names":[],"mappings":"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"}
@@ -34,12 +34,7 @@ const WORKERS = {
34
34
  capability: "code",
35
35
  permission: {
36
36
  ...READ_ONLY,
37
- bash: {
38
- "*": "ask",
39
- "git status*": "allow",
40
- "git diff*": "allow",
41
- "*test*": "allow",
42
- },
37
+ bash: "allow",
43
38
  },
44
39
  },
45
40
  "orch-research": {
@@ -1 +1 @@
1
- {"version":3,"file":"workers.js","sourceRoot":"","sources":["../../src/agents/workers.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"workers.js","sourceRoot":"","sources":["../../src/agents/workers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,42 @@
1
+ declare const PACKAGE_NAME = "@oeronteros-1/opencode-orchestra";
2
+ /**
3
+ * OpenCode resolves each plugin spec into `<cache>/opencode/packages/<spec>/`
4
+ * and only ever installs there once: an existing `package.json` short-circuits
5
+ * re-resolution. A spec like `@latest` therefore keeps loading the version it
6
+ * first resolved to (e.g. 1.0.8) even after newer versions are published.
7
+ * Exact semver pins (`@1.0.15`) can never drift, so they are not refreshed.
8
+ */
9
+ export interface PluginCacheReport {
10
+ /** Mutable entries whose cached version already matches the target. */
11
+ upToDate: string[];
12
+ /** Mutable entries updated in place to the running plugin version. */
13
+ reinstalled: string[];
14
+ /** Mutable entries removed after a failed refresh; OpenCode reinstalls them on its next start. */
15
+ invalidated: string[];
16
+ }
17
+ /**
18
+ * Installs the rewritten pin inside a cache entry directory. Returns false
19
+ * when no package manager succeeded so the caller can fall back to removal.
20
+ */
21
+ export type RefreshInstaller = (directory: string) => Promise<boolean>;
22
+ export interface RefreshPluginCacheOptions {
23
+ /** The `packages` directory of OpenCode's cache (see openCodePackagesRoot). */
24
+ packagesRoot: string;
25
+ /** Version the cache should resolve to; normally the running CLI version. */
26
+ targetVersion: string;
27
+ /** Classify stale entries without writing or removing anything. */
28
+ dryRun?: boolean;
29
+ /** Test seam replacing the bun/npm installation step. */
30
+ runInstaller?: RefreshInstaller;
31
+ }
32
+ /** Root where OpenCode caches installed plugin packages across platforms. */
33
+ export declare function openCodePackagesRoot(): string;
34
+ /**
35
+ * Bring every mutable Orchestra entry in OpenCode's package cache up to
36
+ * `targetVersion`. Entries that cannot be updated are removed so OpenCode
37
+ * performs a clean install on its next start instead of loading a stale copy.
38
+ */
39
+ export declare function refreshPluginCache(options: RefreshPluginCacheOptions): Promise<PluginCacheReport>;
40
+ /** Format a cache report as a single human-readable line, or undefined when there is nothing to report. */
41
+ export declare function formatPluginCacheReport(report: PluginCacheReport, dryRun: boolean): string | undefined;
42
+ export { PACKAGE_NAME };
@@ -0,0 +1,130 @@
1
+ import { spawnSync } from "node:child_process";
2
+ import { readFile, readdir, rm, writeFile } from "node:fs/promises";
3
+ import os from "node:os";
4
+ import path from "node:path";
5
+ import { compareVersions } from "./diagnostics/update.js";
6
+ const PACKAGE_NAME = "@oeronteros-1/opencode-orchestra";
7
+ /** Root where OpenCode caches installed plugin packages across platforms. */
8
+ export function openCodePackagesRoot() {
9
+ const cacheRoot = process.env.XDG_CACHE_HOME
10
+ ?? (process.platform === "win32" ? process.env.LOCALAPPDATA : undefined)
11
+ ?? path.join(os.homedir(), ".cache");
12
+ return path.join(cacheRoot, "opencode", "packages");
13
+ }
14
+ function isExactPin(spec) {
15
+ return /^v?\d+\.\d+\.\d+(?:[-+][\w.]+)*$/.test(spec);
16
+ }
17
+ async function readInstalledVersion(directory) {
18
+ try {
19
+ const manifest = JSON.parse(await readFile(path.join(directory, "node_modules", ...PACKAGE_NAME.split("/"), "package.json"), "utf8"));
20
+ return typeof manifest.version === "string" ? manifest.version : undefined;
21
+ }
22
+ catch {
23
+ return undefined;
24
+ }
25
+ }
26
+ async function discoverEntries(packagesRoot) {
27
+ const entries = [];
28
+ // Scoped specs install under `packages/<@scope>/`, so an entry's full name
29
+ // joins the optional scope with the directory name ("opencode-orchestra",
30
+ // "opencode-orchestra@latest"). The remainder after the package name is
31
+ // either empty (bare spec resolves like @latest) or "@spec".
32
+ const consider = (scope, name, directory) => {
33
+ const fullName = scope ? `${scope}/${name}` : name;
34
+ if (!fullName.startsWith(PACKAGE_NAME))
35
+ return;
36
+ const rest = fullName.slice(PACKAGE_NAME.length);
37
+ if (rest !== "" && !rest.startsWith("@"))
38
+ return;
39
+ entries.push({ label: fullName, directory, spec: rest === "" ? "" : rest.slice(1) });
40
+ };
41
+ let scopes = [];
42
+ try {
43
+ scopes = await readdir(packagesRoot, { withFileTypes: true });
44
+ }
45
+ catch {
46
+ return entries;
47
+ }
48
+ for (const scope of scopes) {
49
+ if (scope.name.startsWith("@") && scope.isDirectory()) {
50
+ const scopeDirectory = path.join(packagesRoot, scope.name);
51
+ for (const child of await readdir(scopeDirectory, { withFileTypes: true })) {
52
+ if (child.isDirectory())
53
+ consider(scope.name, child.name, path.join(scopeDirectory, child.name));
54
+ }
55
+ }
56
+ else if (scope.isDirectory()) {
57
+ consider(undefined, scope.name, path.join(packagesRoot, scope.name));
58
+ }
59
+ }
60
+ return entries.sort((a, b) => a.label.localeCompare(b.label));
61
+ }
62
+ async function reinstallInPlace(entry, version, runInstaller) {
63
+ await writeFile(path.join(entry.directory, "package.json"), `${JSON.stringify({ dependencies: { [PACKAGE_NAME]: version } }, null, 2)}\n`);
64
+ if (runInstaller)
65
+ return runInstaller(entry.directory);
66
+ // OpenCode itself installs plugins with bun; npm covers environments without it.
67
+ const attempts = [
68
+ ["bun", ["install"]],
69
+ ["npm", ["install", "--no-audit", "--no-fund"]],
70
+ ];
71
+ for (const [command, args] of attempts) {
72
+ try {
73
+ const result = spawnSync(command, args, { cwd: entry.directory, stdio: "ignore", shell: process.platform === "win32" });
74
+ if (result.status === 0 && compareVersions((await readInstalledVersion(entry.directory)) ?? "", version) === 0) {
75
+ return true;
76
+ }
77
+ }
78
+ catch {
79
+ // Try the next package manager.
80
+ }
81
+ }
82
+ return false;
83
+ }
84
+ /**
85
+ * Bring every mutable Orchestra entry in OpenCode's package cache up to
86
+ * `targetVersion`. Entries that cannot be updated are removed so OpenCode
87
+ * performs a clean install on its next start instead of loading a stale copy.
88
+ */
89
+ export async function refreshPluginCache(options) {
90
+ const report = { upToDate: [], reinstalled: [], invalidated: [] };
91
+ // A source checkout without a resolvable version cannot state a target;
92
+ // refreshing against "unknown" would churn healthy entries.
93
+ if (!/^\d/.test(options.targetVersion))
94
+ return report;
95
+ const entries = await discoverEntries(options.packagesRoot);
96
+ for (const entry of entries) {
97
+ if (isExactPin(entry.spec))
98
+ continue;
99
+ const installed = await readInstalledVersion(entry.directory);
100
+ if (installed !== undefined && compareVersions(installed, options.targetVersion) === 0) {
101
+ report.upToDate.push(entry.label);
102
+ continue;
103
+ }
104
+ if (options.dryRun) {
105
+ report.reinstalled.push(entry.label);
106
+ continue;
107
+ }
108
+ const updated = await reinstallInPlace(entry, options.targetVersion, options.runInstaller).catch(() => false);
109
+ if (updated)
110
+ report.reinstalled.push(entry.label);
111
+ else {
112
+ await rm(entry.directory, { recursive: true, force: true }).catch(() => undefined);
113
+ report.invalidated.push(entry.label);
114
+ }
115
+ }
116
+ return report;
117
+ }
118
+ /** Format a cache report as a single human-readable line, or undefined when there is nothing to report. */
119
+ export function formatPluginCacheReport(report, dryRun) {
120
+ const parts = [];
121
+ if (report.upToDate.length > 0)
122
+ parts.push(`up-to-date: ${report.upToDate.join(", ")}`);
123
+ if (report.reinstalled.length > 0)
124
+ parts.push(`${dryRun ? "stale (would reinstall)" : "reinstalled"}: ${report.reinstalled.join(", ")}`);
125
+ if (report.invalidated.length > 0)
126
+ parts.push(`invalidated: ${report.invalidated.join(", ")}`);
127
+ return parts.length > 0 ? parts.join("; ") : undefined;
128
+ }
129
+ export { PACKAGE_NAME };
130
+ //# sourceMappingURL=cache-refresh.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache-refresh.js","sourceRoot":"","sources":["../src/cache-refresh.ts"],"names":[],"mappings":"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"}
package/dist/cli.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env node
2
+ import { type PluginCacheReport } from "./cache-refresh.js";
2
3
  export interface InstallOptions {
3
4
  configDirectory?: string;
4
5
  context7: boolean;
@@ -11,6 +12,12 @@ export interface InstallOptions {
11
12
  provisionDependencies: boolean;
12
13
  force: boolean;
13
14
  dryRun: boolean;
15
+ /**
16
+ * Override for OpenCode's plugin package cache (`packages` directory).
17
+ * Tests point this at a temporary directory so runs never touch the
18
+ * real per-user cache.
19
+ */
20
+ pluginCacheDirectory?: string;
14
21
  }
15
22
  type DependencyStatus = "installed" | "existing" | "skipped" | "failed";
16
23
  export interface InstallResult {
@@ -19,10 +26,17 @@ export interface InstallResult {
19
26
  changed: string[];
20
27
  preserved: string[];
21
28
  backup?: string;
29
+ pluginCache: PluginCacheReport;
22
30
  dependencies: {
23
- codebaseMemory: DependencyStatus;
24
- memoryGraph: DependencyStatus;
31
+ codebaseMemory: ProvisionedDependency;
32
+ memoryGraph: ProvisionedDependency;
25
33
  };
26
34
  }
35
+ interface ProvisionedDependency {
36
+ command: string | string[];
37
+ status: DependencyStatus;
38
+ reason?: string;
39
+ }
40
+ export declare function failureReason(error: unknown): string | undefined;
27
41
  export declare function install(options: InstallOptions): Promise<InstallResult>;
28
42
  export {};
package/dist/cli.js CHANGED
@@ -1,10 +1,11 @@
1
1
  #!/usr/bin/env node
2
2
  import { spawnSync } from "node:child_process";
3
- import { copyFile, mkdir, mkdtemp, readFile, realpath, rename, rm, writeFile } from "node:fs/promises";
3
+ import { copyFile, mkdir, mkdtemp, readdir, readFile, realpath, rename, rm, writeFile } from "node:fs/promises";
4
4
  import os from "node:os";
5
5
  import path from "node:path";
6
6
  import { pathToFileURL } from "node:url";
7
7
  import { applyEdits, modify, parse, printParseErrorCode } from "jsonc-parser";
8
+ import { formatPluginCacheReport, openCodePackagesRoot, refreshPluginCache } from "./cache-refresh.js";
8
9
  import { openCodeConfigDirectory } from "./config/paths.js";
9
10
  import { startDashboard } from "./dashboard/server.js";
10
11
  import { completionFor, SHELL_NAMES } from "./diagnostics/completion.js";
@@ -76,10 +77,7 @@ function superPowersName(entry) {
76
77
  return (hash === -1 ? name : name.slice(0, hash)).toLowerCase();
77
78
  }
78
79
  function superPowersSkillsPath() {
79
- const cacheRoot = process.env.XDG_CACHE_HOME
80
- ?? (process.platform === "win32" ? process.env.LOCALAPPDATA : undefined)
81
- ?? path.join(os.homedir(), ".cache");
82
- return path.join(cacheRoot, "opencode", "packages", SUPER_POWERS_ENTRY, "node_modules", "superpowers", "skills");
80
+ return path.join(openCodePackagesRoot(), SUPER_POWERS_ENTRY, "node_modules", "superpowers", "skills");
83
81
  }
84
82
  async function existingMainConfig(configDirectory) {
85
83
  // OpenCode loads JSONC after JSON when both files exist, so update the
@@ -131,8 +129,15 @@ function run(command, args, env) {
131
129
  if (result.status !== 0)
132
130
  throw new Error(`Command failed (${result.status ?? "unknown"}): ${command} ${args.join(" ")}`);
133
131
  }
132
+ // Exported for unit tests: installer output must stay single-line and bounded.
133
+ export function failureReason(error) {
134
+ const raw = error instanceof Error ? error.message : String(error);
135
+ const reason = raw.replace(/[\r\n]+/g, " ").replace(/\s+/g, " ").trim().slice(0, 200);
136
+ return reason || undefined;
137
+ }
134
138
  async function downloadScript(url, filename) {
135
- const response = await fetch(url, { redirect: "follow" });
139
+ // Bounded fetch: a hung registry mirror must not stall the whole install.
140
+ const response = await fetch(url, { redirect: "follow", signal: AbortSignal.timeout(30_000) });
136
141
  if (!response.ok)
137
142
  throw new Error(`Failed to download ${url}: HTTP ${response.status}`);
138
143
  const directory = await mkdtemp(path.join(os.tmpdir(), "opencode-orchestra-"));
@@ -204,26 +209,42 @@ async function provisionMemoryGraph(enabled) {
204
209
  const current = executable(["memorygraph", localBin("memorygraph")]);
205
210
  if (current)
206
211
  return { command: current, status: "existing" };
212
+ // uv provisioning failures abort before the try so they surface verbatim.
207
213
  const uv = await ensureUv();
208
- run(uv.command, ["tool", "install", "memorygraphMCP"]);
209
- const toolBin = capture(uv.command, ["tool", "dir", "--bin"]);
210
- const installed = executable([
211
- ...(toolBin ? [path.join(toolBin, executableName("memorygraph"))] : []),
212
- localBin("memorygraph"),
213
- "memorygraph",
214
- ]);
215
- if (!installed)
216
- throw new Error("memorygraphMCP installed, but its executable was not found.");
217
- return { command: installed, status: "installed" };
214
+ try {
215
+ run(uv.command, ["tool", "install", "memorygraphMCP>=0.12"]);
216
+ const toolBin = capture(uv.command, ["tool", "dir", "--bin"]);
217
+ const installed = executable([
218
+ ...(toolBin ? [path.join(toolBin, executableName("memorygraph"))] : []),
219
+ localBin("memorygraph"),
220
+ "memorygraph",
221
+ ]);
222
+ if (!installed)
223
+ throw new Error("memorygraphMCP installed, but its executable was not found.");
224
+ return { command: installed, status: "installed" };
225
+ }
226
+ catch (error) {
227
+ // PyPI ships a `memorygraph` launcher; fall back to an ephemeral uvx run.
228
+ const uvx = executable([path.join(path.dirname(uv.command), executableName("uvx")), localBin("uvx"), "uvx"]);
229
+ if (!uvx)
230
+ throw error;
231
+ return { command: [uvx, "memorygraph"], status: "installed" };
232
+ }
218
233
  }
219
234
  export async function install(options) {
220
235
  const shouldProvision = options.provisionDependencies && !options.dryRun;
221
236
  // Companion MCPs are optional: failed provisioning must not prevent plugin setup.
222
237
  const codebase = options.codebaseMemory
223
- ? await provisionCodebaseMemory(shouldProvision).catch(() => ({ command: "codebase-memory-mcp", status: "failed" }))
238
+ ? await provisionCodebaseMemory(shouldProvision).catch((error) => {
239
+ const reason = failureReason(error);
240
+ return { command: "codebase-memory-mcp", status: "failed", ...(reason ? { reason } : {}) };
241
+ })
224
242
  : { command: "codebase-memory-mcp", status: "skipped" };
225
243
  const memoryGraph = options.memoryGraph
226
- ? await provisionMemoryGraph(shouldProvision).catch(() => ({ command: "memorygraph", status: "failed" }))
244
+ ? await provisionMemoryGraph(shouldProvision).catch((error) => {
245
+ const reason = failureReason(error);
246
+ return { command: "memorygraph", status: "failed", ...(reason ? { reason } : {}) };
247
+ })
227
248
  : { command: "memorygraph", status: "skipped" };
228
249
  const configDirectory = path.resolve(options.configDirectory ?? openCodeConfigDirectory());
229
250
  const openCodeConfig = await existingMainConfig(configDirectory);
@@ -345,18 +366,19 @@ export async function install(options) {
345
366
  if (options.playwright !== false) {
346
367
  addMcp("playwright", { type: "local", command: PLAYWRIGHT_COMMAND, enabled: true, timeout: 30_000 });
347
368
  }
348
- if (options.codebaseMemory) {
369
+ // A failed provisioning never persists an MCP entry pointing at a dead command.
370
+ if (options.codebaseMemory && codebase.status !== "failed") {
349
371
  addMcp("codebase-memory", {
350
372
  type: "local",
351
- command: [codebase.command],
373
+ command: Array.isArray(codebase.command) ? codebase.command : [codebase.command],
352
374
  enabled: true,
353
375
  timeout: 30_000,
354
376
  });
355
377
  }
356
- if (options.memoryGraph) {
378
+ if (options.memoryGraph && memoryGraph.status !== "failed") {
357
379
  addMcp("memorygraph", {
358
380
  type: "local",
359
- command: [memoryGraph.command],
381
+ command: Array.isArray(memoryGraph.command) ? memoryGraph.command : [memoryGraph.command],
360
382
  enabled: true,
361
383
  timeout: 30_000,
362
384
  });
@@ -370,6 +392,13 @@ export async function install(options) {
370
392
  }
371
393
  await atomicWrite(openCodeConfig, updated.endsWith("\n") ? updated : `${updated}\n`);
372
394
  }
395
+ // Reinstalling the plugin must also refresh OpenCode's package cache:
396
+ // an entry like `@latest` keeps its first-resolved version until removed.
397
+ const pluginCache = await refreshPluginCache({
398
+ packagesRoot: path.resolve(options.pluginCacheDirectory ?? openCodePackagesRoot()),
399
+ targetVersion: await resolvePluginVersion(),
400
+ ...(options.dryRun ? { dryRun: true } : {}),
401
+ });
373
402
  try {
374
403
  const orchestraOriginal = await readFile(orchestraConfig, "utf8");
375
404
  parseObject(orchestraOriginal, orchestraConfig);
@@ -394,9 +423,10 @@ export async function install(options) {
394
423
  changed,
395
424
  preserved,
396
425
  ...(backup ? { backup } : {}),
426
+ pluginCache,
397
427
  dependencies: {
398
- codebaseMemory: codebase.status,
399
- memoryGraph: memoryGraph.status,
428
+ codebaseMemory: codebase,
429
+ memoryGraph: memoryGraph,
400
430
  },
401
431
  };
402
432
  }
@@ -578,8 +608,11 @@ async function main() {
578
608
  const result = await install(parsed.options);
579
609
  console.log(`OpenCode Orchestra configured: ${result.openCodeConfig}`);
580
610
  console.log(`Agent settings: ${result.orchestraConfig}`);
581
- console.log(`Codebase Memory: ${result.dependencies.codebaseMemory}`);
582
- console.log(`MemoryGraph: ${result.dependencies.memoryGraph}`);
611
+ const cacheSummary = formatPluginCacheReport(result.pluginCache, parsed.options.dryRun);
612
+ console.log(`OpenCode plugin cache: ${cacheSummary ?? "no cached Orchestra entries"}`);
613
+ const dependencyLine = ({ status, reason }) => `${status}${reason ? ` (${reason})` : ""}`;
614
+ console.log(`Codebase Memory: ${dependencyLine(result.dependencies.codebaseMemory)}`);
615
+ console.log(`MemoryGraph: ${dependencyLine(result.dependencies.memoryGraph)}`);
583
616
  if (result.changed.length > 0)
584
617
  console.log(`Changed: ${result.changed.join(", ")}`);
585
618
  if (result.preserved.length > 0)