@oeronteros-1/opencode-orchestra 1.0.34 → 2.0.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.
Files changed (51) hide show
  1. package/README.md +19 -6
  2. package/dashboard-dist/assets/index-D1JhVhPt.css +2 -0
  3. package/dashboard-dist/assets/index-YMCkRwnG.js +132 -0
  4. package/dashboard-dist/index.html +2 -2
  5. package/dist/agents/editor.d.ts +1 -1
  6. package/dist/agents/editor.js +2 -1
  7. package/dist/agents/editor.js.map +1 -1
  8. package/dist/agents/integrator.d.ts +1 -1
  9. package/dist/agents/integrator.js +2 -1
  10. package/dist/agents/integrator.js.map +1 -1
  11. package/dist/agents/lead.d.ts +1 -1
  12. package/dist/agents/lead.js +5 -8
  13. package/dist/agents/lead.js.map +1 -1
  14. package/dist/agents/types.d.ts +6 -0
  15. package/dist/agents/types.js +51 -1
  16. package/dist/agents/types.js.map +1 -1
  17. package/dist/agents/workers.d.ts +1 -1
  18. package/dist/agents/workers.js +7 -9
  19. package/dist/agents/workers.js.map +1 -1
  20. package/dist/cli.js +94 -22
  21. package/dist/cli.js.map +1 -1
  22. package/dist/dashboard/server.js +52 -12
  23. package/dist/dashboard/server.js.map +1 -1
  24. package/dist/diagnostics/completion.js +9 -1
  25. package/dist/diagnostics/completion.js.map +1 -1
  26. package/dist/diagnostics/doctor.js +2 -2
  27. package/dist/diagnostics/doctor.js.map +1 -1
  28. package/dist/index.d.ts +1 -0
  29. package/dist/index.js +60 -0
  30. package/dist/index.js.map +1 -1
  31. package/dist/mcp/commands.d.ts +5 -0
  32. package/dist/mcp/commands.js +21 -0
  33. package/dist/mcp/commands.js.map +1 -0
  34. package/dist/mcp/config-smoke.d.ts +21 -0
  35. package/dist/mcp/config-smoke.js +95 -0
  36. package/dist/mcp/config-smoke.js.map +1 -0
  37. package/dist/mcp/smoke.d.ts +23 -0
  38. package/dist/mcp/smoke.js +148 -0
  39. package/dist/mcp/smoke.js.map +1 -0
  40. package/dist/plugin-status.js +13 -7
  41. package/dist/plugin-status.js.map +1 -1
  42. package/dist/telemetry/ledger.d.ts +24 -0
  43. package/dist/telemetry/ledger.js +48 -0
  44. package/dist/telemetry/ledger.js.map +1 -1
  45. package/package.json +4 -2
  46. package/prompts/editor.md +4 -3
  47. package/prompts/lead.md +4 -1
  48. package/prompts/repo.md +1 -1
  49. package/prompts/tests.md +1 -0
  50. package/dashboard-dist/assets/index-CbNmtkWh.css +0 -2
  51. package/dashboard-dist/assets/index-DTImj8fu.js +0 -132
@@ -5,8 +5,8 @@
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-DTImj8fu.js"></script>
9
- <link rel="stylesheet" crossorigin href="/assets/index-CbNmtkWh.css">
8
+ <script type="module" crossorigin src="/assets/index-YMCkRwnG.js"></script>
9
+ <link rel="stylesheet" crossorigin href="/assets/index-D1JhVhPt.css">
10
10
  </head>
11
11
  <body>
12
12
  <div id="root"></div>
@@ -1,3 +1,3 @@
1
1
  import type { OrchestraConfig } from "../config/schema.js";
2
- import type { RuntimeAgentConfig } from "./types.js";
2
+ import { type RuntimeAgentConfig } from "./types.js";
3
3
  export declare function createEditorAgent(config: OrchestraConfig, prompt?: string): RuntimeAgentConfig;
@@ -1,11 +1,12 @@
1
1
  import { resolveModel } from "../routing/model-resolver.js";
2
+ import { safeBashPermissions } from "./types.js";
2
3
  export function createEditorAgent(config, prompt) {
3
4
  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
5
  return {
5
6
  description: "Isolated implementation worker that edits only its assigned ownership partition in an OpenCode git workspace.",
6
7
  mode: "subagent", hidden: true, temperature: 0.15,
7
8
  prompt: 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", "ast-grep_*": "allow", "ast_grep_*": "allow", task: "deny", external_directory: "deny" },
9
+ permission: { "*": "deny", read: "allow", edit: "allow", glob: "allow", grep: "allow", list: "allow", lsp: "allow", bash: safeBashPermissions(), "ast-grep_*": "allow", "ast_grep_*": "allow", task: "deny", external_directory: "deny" },
9
10
  ...(resolved ? { model: resolved.id } : {}),
10
11
  };
11
12
  }
@@ -1 +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,EAAE,MAAe;IACxE,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,MAAM,IAAI,uXAAuX;QACzY,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,YAAY,EAAE,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,kBAAkB,EAAE,MAAM,EAAE;QAC3N,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,QAAQ,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC5C,CAAA;AACH,CAAC"}
1
+ {"version":3,"file":"editor.js","sourceRoot":"","sources":["../../src/agents/editor.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAA;AAC3D,OAAO,EAAE,mBAAmB,EAA2B,MAAM,YAAY,CAAA;AAEzE,MAAM,UAAU,iBAAiB,CAAC,MAAuB,EAAE,MAAe;IACxE,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,MAAM,IAAI,uXAAuX;QACzY,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,mBAAmB,EAAE,EAAE,YAAY,EAAE,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,kBAAkB,EAAE,MAAM,EAAE;QACzO,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,QAAQ,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC5C,CAAA;AACH,CAAC"}
@@ -1,3 +1,3 @@
1
1
  import type { OrchestraConfig } from "../config/schema.js";
2
- import type { RuntimeAgentConfig } from "./types.js";
2
+ import { type RuntimeAgentConfig } from "./types.js";
3
3
  export declare function createIntegratorAgent(config: OrchestraConfig, prompt?: string): RuntimeAgentConfig;
@@ -1,11 +1,12 @@
1
1
  import { resolveModel } from "../routing/model-resolver.js";
2
+ import { safeBashPermissions } from "./types.js";
2
3
  export function createIntegratorAgent(config, prompt) {
3
4
  const resolved = resolveModel({ pool: config.models.lead, capability: "reasoning", budget: config.budget, allowPaid: config.budget === "quality" || config.budget === "ebobo", preferredTiers: ["lead", "frontier"] });
4
5
  return {
5
6
  description: "Deterministic integration worker that validates ownership and integrates isolated editor commits.",
6
7
  mode: "subagent", hidden: true, temperature: 0.1,
7
8
  prompt: prompt ?? "Integrate validated editor commits deterministically in sorted editor order. Before cherry-picking, derive actual changed paths from git and build a cross-editor conflict map listing per-editor changed paths, ownership violations, conflicting paths, and the sorted integration order. Fail closed on any ownership overlap, ownership violation, ancestry failure, or Git conflict: if the map is not clean, integrate nothing at all. Cherry-pick the commits only after the entire map is clean, all-or-nothing in deterministic order. On any failure, stop, integrate nothing, and retain all worktrees for diagnosis. Never resolve a semantic or 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
+ permission: { "*": "deny", read: "allow", edit: "deny", glob: "allow", grep: "allow", list: "allow", lsp: "allow", bash: safeBashPermissions(), task: "deny", external_directory: "deny" },
9
10
  ...(resolved ? { model: resolved.id } : {}),
10
11
  };
11
12
  }
@@ -1 +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,EAAE,MAAe;IAC5E,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,MAAM,IAAI,qwBAAqwB;QACvxB,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"}
1
+ {"version":3,"file":"integrator.js","sourceRoot":"","sources":["../../src/agents/integrator.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAA;AAC3D,OAAO,EAAE,mBAAmB,EAA2B,MAAM,YAAY,CAAA;AAEzE,MAAM,UAAU,qBAAqB,CAAC,MAAuB,EAAE,MAAe;IAC5E,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,MAAM,IAAI,qwBAAqwB;QACvxB,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,mBAAmB,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,kBAAkB,EAAE,MAAM,EAAE;QAC1L,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,QAAQ,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC5C,CAAA;AACH,CAAC"}
@@ -1,3 +1,3 @@
1
1
  import type { OrchestraConfig } from "../config/schema.js";
2
- import type { RuntimeAgentConfig } from "./types.js";
2
+ import { type RuntimeAgentConfig } from "./types.js";
3
3
  export declare function createLeadAgent(config: OrchestraConfig, basePrompt: string): RuntimeAgentConfig;
@@ -1,5 +1,6 @@
1
1
  import { PROFILE_CATALOG } from "../profiles/catalog.js";
2
2
  import { leadResolveRequest, resolveModel } from "../routing/model-resolver.js";
3
+ import { leadGitPermissions, safeBashPermissions } from "./types.js";
3
4
  export function createLeadAgent(config, basePrompt) {
4
5
  const enabled = Object.values(PROFILE_CATALOG).filter((profile) => config.orchestration.profiles[profile.name] !== false);
5
6
  const profileGuide = enabled
@@ -29,21 +30,17 @@ export function createLeadAgent(config, basePrompt) {
29
30
  grep: "allow",
30
31
  list: "allow",
31
32
  lsp: "allow",
32
- // Autonomous coordination loop: allow without per-step confirmation.
33
- // Destructive shell patterns (rm -rf, git reset --hard, git push --force,
34
- // git clean -f, mkfs, dd, output truncation bypass) cannot be expressed as
35
- // granular deny rules here — RuntimeAgentConfig allows only
36
- // allow|ask|deny per tool — so they are enforced via system prompts
37
- // (prompts/lead.md §§2–3) instead of an engine-level deny list.
38
- bash: "allow",
33
+ // Autonomous coordination with engine-enforced destructive-command denies.
34
+ bash: safeBashPermissions(),
39
35
  "context7_*": "allow",
40
36
  "codebase-memory_*": "allow",
41
37
  "codebase_memory_*": "allow",
42
38
  "codebase-memory-mcp_*": "allow",
43
39
  "memorygraph_*": "allow",
44
- "git_*": "allow",
40
+ ...leadGitPermissions(),
45
41
  "ast-grep_*": "allow",
46
42
  "ast_grep_*": "allow",
43
+ "playwright_*": "allow",
47
44
  ...(config.superpowers.compatibility ? { skill: "allow" } : {}),
48
45
  task: {
49
46
  "*": "deny",
@@ -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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"}
@@ -1,4 +1,10 @@
1
1
  export type PermissionAction = "allow" | "ask" | "deny";
2
+ /** Engine-enforced shell policy shared by agents that run verification. */
3
+ export declare function safeBashPermissions(defaultAction?: PermissionAction): Record<string, PermissionAction>;
4
+ /** Read-only Git MCP policy for repository scouts. */
5
+ export declare function readOnlyGitPermissions(): Record<string, PermissionAction>;
6
+ /** Git MCP policy for the lead: reads are autonomous, mutations are gated. */
7
+ export declare function leadGitPermissions(): Record<string, PermissionAction>;
2
8
  export interface RuntimeAgentConfig {
3
9
  description: string;
4
10
  mode: "primary" | "subagent";
@@ -1,2 +1,52 @@
1
- export {};
1
+ /** Engine-enforced shell policy shared by agents that run verification. */
2
+ export function safeBashPermissions(defaultAction = "allow") {
3
+ return {
4
+ "*": defaultAction,
5
+ "rm -rf*": "deny",
6
+ "git reset --hard*": "deny",
7
+ "git clean -f*": "deny",
8
+ "git clean -df*": "deny",
9
+ "git push --force*": "deny",
10
+ "git push -f*": "deny",
11
+ "mkfs*": "deny",
12
+ "dd *": "deny",
13
+ "Remove-Item * -Recurse*": "deny",
14
+ "Format-Volume*": "deny",
15
+ "Clear-Disk*": "deny",
16
+ };
17
+ }
18
+ const GIT_READ_TOOL_NAMES = [
19
+ "git_status",
20
+ "git_diff_unstaged",
21
+ "git_diff_staged",
22
+ "git_diff",
23
+ "git_log",
24
+ "git_show",
25
+ "git_branch",
26
+ ];
27
+ /** Read-only Git MCP policy for repository scouts. */
28
+ export function readOnlyGitPermissions() {
29
+ const permissions = { "git_*": "deny" };
30
+ for (const tool of GIT_READ_TOOL_NAMES) {
31
+ permissions[tool] = "allow";
32
+ permissions[`git_${tool}`] = "allow";
33
+ }
34
+ return permissions;
35
+ }
36
+ /** Git MCP policy for the lead: reads are autonomous, mutations are gated. */
37
+ export function leadGitPermissions() {
38
+ return {
39
+ ...readOnlyGitPermissions(),
40
+ "git_git_add": "ask",
41
+ "git_git_commit": "ask",
42
+ "git_git_create_branch": "ask",
43
+ "git_git_checkout": "ask",
44
+ "git_git_reset": "deny",
45
+ git_add: "ask",
46
+ git_commit: "ask",
47
+ git_create_branch: "ask",
48
+ git_checkout: "ask",
49
+ git_reset: "deny",
50
+ };
51
+ }
2
52
  //# sourceMappingURL=types.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/agents/types.ts"],"names":[],"mappings":""}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/agents/types.ts"],"names":[],"mappings":"AAEA,2EAA2E;AAC3E,MAAM,UAAU,mBAAmB,CAAC,gBAAkC,OAAO;IAC3E,OAAO;QACL,GAAG,EAAE,aAAa;QAClB,SAAS,EAAE,MAAM;QACjB,mBAAmB,EAAE,MAAM;QAC3B,eAAe,EAAE,MAAM;QACvB,gBAAgB,EAAE,MAAM;QACxB,mBAAmB,EAAE,MAAM;QAC3B,cAAc,EAAE,MAAM;QACtB,OAAO,EAAE,MAAM;QACf,MAAM,EAAE,MAAM;QACd,yBAAyB,EAAE,MAAM;QACjC,gBAAgB,EAAE,MAAM;QACxB,aAAa,EAAE,MAAM;KACtB,CAAA;AACH,CAAC;AAED,MAAM,mBAAmB,GAAG;IAC1B,YAAY;IACZ,mBAAmB;IACnB,iBAAiB;IACjB,UAAU;IACV,SAAS;IACT,UAAU;IACV,YAAY;CACJ,CAAA;AAEV,sDAAsD;AACtD,MAAM,UAAU,sBAAsB;IACpC,MAAM,WAAW,GAAqC,EAAE,OAAO,EAAE,MAAM,EAAE,CAAA;IACzE,KAAK,MAAM,IAAI,IAAI,mBAAmB,EAAE,CAAC;QACvC,WAAW,CAAC,IAAI,CAAC,GAAG,OAAO,CAAA;QAC3B,WAAW,CAAC,OAAO,IAAI,EAAE,CAAC,GAAG,OAAO,CAAA;IACtC,CAAC;IACD,OAAO,WAAW,CAAA;AACpB,CAAC;AAED,8EAA8E;AAC9E,MAAM,UAAU,kBAAkB;IAChC,OAAO;QACL,GAAG,sBAAsB,EAAE;QAC3B,aAAa,EAAE,KAAK;QACpB,gBAAgB,EAAE,KAAK;QACvB,uBAAuB,EAAE,KAAK;QAC9B,kBAAkB,EAAE,KAAK;QACzB,eAAe,EAAE,MAAM;QACvB,OAAO,EAAE,KAAK;QACd,UAAU,EAAE,KAAK;QACjB,iBAAiB,EAAE,KAAK;QACxB,YAAY,EAAE,KAAK;QACnB,SAAS,EAAE,MAAM;KAClB,CAAA;AACH,CAAC"}
@@ -1,5 +1,5 @@
1
1
  import type { OrchestraConfig } from "../config/schema.js";
2
- import type { AgentSet, RuntimeAgentConfig } from "./types.js";
2
+ import { type AgentSet, type RuntimeAgentConfig } from "./types.js";
3
3
  import type { PromptBundle } from "./build.js";
4
4
  interface WorkerSpec {
5
5
  description: string;
@@ -1,4 +1,5 @@
1
1
  import { resolveModel } from "../routing/model-resolver.js";
2
+ import { readOnlyGitPermissions, safeBashPermissions } from "./types.js";
2
3
  const READ_ONLY = {
3
4
  "*": "deny",
4
5
  read: "allow",
@@ -12,10 +13,6 @@ const READ_ONLY = {
12
13
  task: "deny",
13
14
  external_directory: "ask",
14
15
  };
15
- // Read-only repo scout plus structural/history tools. Git mutations
16
- // (git_commit/git_add/git_reset) and ast-grep rewrites are forbidden by the
17
- // repo system prompt, not by granular permission denies: the permission
18
- // schema supports only allow|ask|deny per tool prefix.
19
16
  const WORKERS = {
20
17
  "orch-repo": {
21
18
  description: "Internal read-only repository scout for focused codebase evidence, ownership, patterns, and change impact.",
@@ -26,7 +23,7 @@ const WORKERS = {
26
23
  ...READ_ONLY,
27
24
  "ast-grep_*": "allow",
28
25
  "ast_grep_*": "allow",
29
- "git_*": "allow",
26
+ ...readOnlyGitPermissions(),
30
27
  },
31
28
  },
32
29
  "orch-docs": {
@@ -43,7 +40,8 @@ const WORKERS = {
43
40
  capability: "code",
44
41
  permission: {
45
42
  ...READ_ONLY,
46
- bash: "allow",
43
+ bash: safeBashPermissions(),
44
+ "playwright_*": "allow",
47
45
  },
48
46
  },
49
47
  "orch-research": {
@@ -65,14 +63,14 @@ const WORKERS = {
65
63
  prompt: "Perform a focused security analysis. Report only evidence-backed attack paths with impact, likelihood, and mitigation. Do not edit or delegate.",
66
64
  pool: "reasoning",
67
65
  capability: "security",
68
- permission: { ...READ_ONLY, webfetch: "allow", websearch: "allow" },
66
+ permission: { ...READ_ONLY, webfetch: "allow", websearch: "allow", "playwright_*": "allow" },
69
67
  },
70
68
  "orch-visual-reference": {
71
69
  description: "Internal visual-reference scout for UI patterns, layout, motion, and interaction examples.",
72
70
  prompt: "Collect relevant visual references and explain which concrete layout, hierarchy, motion, and interaction ideas transfer to this product. Do not edit or delegate.",
73
71
  pool: "vision",
74
72
  capability: "vision",
75
- permission: { ...READ_ONLY, webfetch: "allow", websearch: "allow" },
73
+ permission: { ...READ_ONLY, webfetch: "allow", websearch: "allow", "playwright_*": "allow" },
76
74
  },
77
75
  "orch-visual-generate": {
78
76
  description: "Internal visual generator for exploratory mockups when an image-generation tool is available.",
@@ -86,7 +84,7 @@ const WORKERS = {
86
84
  prompt: "Review the provided visual material against the task. Report observable issues, severity, and precise recommendations. Do not edit or delegate.",
87
85
  pool: "vision",
88
86
  capability: "vision",
89
- permission: READ_ONLY,
87
+ permission: { ...READ_ONLY, "playwright_*": "allow" },
90
88
  },
91
89
  };
92
90
  export function createWorkerAgents(config, prompts) {
@@ -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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"}
package/dist/cli.js CHANGED
@@ -12,6 +12,9 @@ import { startDashboard } from "./dashboard/server.js";
12
12
  import { completionFor, SHELL_NAMES } from "./diagnostics/completion.js";
13
13
  import { formatDoctorReport, runDoctor } from "./diagnostics/doctor.js";
14
14
  import { checkForUpdates, formatUpdateResult } from "./diagnostics/update.js";
15
+ import { astGrepMcpCommand, gitMcpCommand } from "./mcp/commands.js";
16
+ import { formatConfiguredMcpSmokeReport, smokeConfiguredMcps } from "./mcp/config-smoke.js";
17
+ import { smokeMcp } from "./mcp/smoke.js";
15
18
  import { resolvePluginVersion } from "./plugin-status.js";
16
19
  import { homeDirectory, spawnWithCmdFallback } from "./spawn.js";
17
20
  const PACKAGE_NAME = "@oeronteros-1/opencode-orchestra";
@@ -276,42 +279,56 @@ async function provisionMemoryGraph(enabled) {
276
279
  * Best-effort: failures are reported but never block config writes because
277
280
  * `uvx` remains a valid autonomous runtime that retries at launch.
278
281
  */
279
- async function warmGitMcp(enabled, shouldWarm) {
280
- const command = ["uvx", "mcp-server-git"];
282
+ async function warmGitMcp(enabled, shouldWarm, uvx = "uvx") {
283
+ const command = gitMcpCommand(uvx);
281
284
  if (!enabled)
282
285
  return { command, status: "skipped" };
283
286
  if (!shouldWarm)
284
287
  return { command, status: "skipped", reason: "warmup skipped (--no-deps or dry-run)" };
288
+ let smokeRepository;
285
289
  try {
286
- const result = spawnWithCmdFallback("uvx", ["mcp-server-git", "--help"], { stdio: "ignore", timeout: 60_000 });
287
- if (result.error)
288
- throw result.error;
289
- if (result.status !== 0)
290
- throw new Error(`uvx mcp-server-git --help exited with ${result.status ?? "unknown"}`);
290
+ if (!executable(["git"]))
291
+ throw new Error("git is required by Git MCP but was not found in PATH");
292
+ smokeRepository = await mkdtemp(path.join(os.tmpdir(), "opencode-orchestra-git-smoke-"));
293
+ run("git", ["init", "--quiet", smokeRepository]);
294
+ const result = await smokeMcp({
295
+ command,
296
+ cwd: smokeRepository,
297
+ timeoutMs: 120_000,
298
+ call: { tool: "git_status", arguments: { repo_path: smokeRepository } },
299
+ });
300
+ if (!result.ok)
301
+ throw new Error(result.error ?? "Git MCP handshake failed");
291
302
  return { command, status: "installed" };
292
303
  }
293
304
  catch (error) {
294
305
  const reason = failureReason(error);
295
306
  return { command, status: "failed", ...(reason ? { reason } : {}) };
296
307
  }
308
+ finally {
309
+ if (smokeRepository)
310
+ await rm(smokeRepository, { recursive: true, force: true, maxRetries: 5, retryDelay: 200 });
311
+ }
297
312
  }
298
313
  /**
299
314
  * Warm the `uvx` cache for ast-grep MCP (`git+https://…` source).
300
315
  * Cold clone + env build takes 10–25s; without warmup the first MCP
301
316
  * handshake (~10s timeout) almost certainly fails.
302
317
  */
303
- async function warmAstGrepMcp(enabled, shouldWarm) {
304
- const command = ["uvx", "--from", "git+https://github.com/ast-grep/ast-grep-mcp", "ast-grep-server"];
318
+ async function warmAstGrepMcp(enabled, shouldWarm, uvx = "uvx") {
319
+ const command = astGrepMcpCommand(uvx);
305
320
  if (!enabled)
306
321
  return { command, status: "skipped" };
307
322
  if (!shouldWarm)
308
323
  return { command, status: "skipped", reason: "warmup skipped (--no-deps or dry-run)" };
309
324
  try {
310
- const result = spawnWithCmdFallback("uvx", ["--from", "git+https://github.com/ast-grep/ast-grep-mcp", "ast-grep-server", "--help"], { stdio: "ignore", timeout: 60_000 });
311
- if (result.error)
312
- throw result.error;
313
- if (result.status !== 0)
314
- throw new Error(`ast-grep warmup exited with ${result.status ?? "unknown"}`);
325
+ const result = await smokeMcp({
326
+ command,
327
+ timeoutMs: 120_000,
328
+ call: { tool: "dump_syntax_tree", arguments: { code: "const value = 1", language: "typescript", format: "pattern" } },
329
+ });
330
+ if (!result.ok)
331
+ throw new Error(result.error ?? "ast-grep MCP smoke call failed");
315
332
  return { command, status: "installed" };
316
333
  }
317
334
  catch (error) {
@@ -334,11 +351,24 @@ export async function install(options) {
334
351
  return { command: "memorygraph", status: "failed", ...(reason ? { reason } : {}) };
335
352
  })
336
353
  : { command: "memorygraph", status: "skipped" };
337
- // Git + ast-grep warmup is best-effort cache pre-heating (60s timeout each).
338
- // A failed warmup still writes the MCP config: uvx retries at runtime.
354
+ // Git + ast-grep use one managed uv/uvx installation on Windows and Unix.
355
+ // Their real MCP handshakes run concurrently so successful installation is
356
+ // proven without doubling cold-start latency.
339
357
  // Undefined means enabled (backward compatible with callers that predate the flags).
340
- const git = await warmGitMcp(options.git !== false, shouldProvision);
341
- const astGrep = await warmAstGrepMcp(options.astGrep !== false, shouldProvision);
358
+ let mcpUvx = "uvx";
359
+ if (shouldProvision && (options.git !== false || options.astGrep !== false)) {
360
+ try {
361
+ const uv = await ensureUv();
362
+ mcpUvx = executable([...siblingExecutables(path.dirname(uv.command), "uvx"), ...localBinCandidates("uvx"), "uvx"]) ?? "uvx";
363
+ }
364
+ catch {
365
+ // Each smoke result below reports the bounded, server-specific failure.
366
+ }
367
+ }
368
+ const [git, astGrep] = await Promise.all([
369
+ warmGitMcp(options.git !== false, shouldProvision, mcpUvx),
370
+ warmAstGrepMcp(options.astGrep !== false, shouldProvision, mcpUvx),
371
+ ]);
342
372
  const configDirectory = path.resolve(options.configDirectory ?? openCodeConfigDirectory());
343
373
  const openCodeConfig = await existingMainConfig(configDirectory);
344
374
  const orchestraConfig = path.join(configDirectory, "orchestra.jsonc");
@@ -482,17 +512,19 @@ export async function install(options) {
482
512
  if (options.git !== false) {
483
513
  addMcp("git", {
484
514
  type: "local",
485
- command: ["uvx", "mcp-server-git"],
515
+ command: Array.isArray(git.command) ? git.command : [git.command],
516
+ cwd: ".",
486
517
  enabled: true,
487
- timeout: 30_000,
518
+ timeout: 120_000,
488
519
  });
489
520
  }
490
521
  if (options.astGrep !== false) {
491
522
  addMcp("ast-grep", {
492
523
  type: "local",
493
- command: ["uvx", "--from", "git+https://github.com/ast-grep/ast-grep-mcp", "ast-grep-server"],
524
+ command: Array.isArray(astGrep.command) ? astGrep.command : [astGrep.command],
525
+ cwd: ".",
494
526
  enabled: true,
495
- timeout: 30_000,
527
+ timeout: 120_000,
496
528
  });
497
529
  }
498
530
  let backup;
@@ -555,6 +587,7 @@ function usage() {
555
587
  " install Configure OpenCode and provision companion MCPs",
556
588
  " dashboard Start the local telemetry dashboard",
557
589
  " doctor Diagnose config, MCPs, and toolchain paths",
590
+ " mcp-smoke Launch configured local MCPs and test their protocol",
558
591
  " update Check for a newer published version",
559
592
  " completion Print shell completion (zsh | bash | pwsh)",
560
593
  "",
@@ -577,6 +610,11 @@ function usage() {
577
610
  " --host HOST Bind address (default: 127.0.0.1)",
578
611
  " --port PORT Bind port (default: automatic)",
579
612
  " --no-open Do not open the browser automatically",
613
+ "",
614
+ "MCP smoke options:",
615
+ " --directory DIR Project used as cwd and Git repository",
616
+ " --config-dir DIR Override the OpenCode config directory",
617
+ " --json Print a machine-readable report",
580
618
  ].join("\n");
581
619
  }
582
620
  function parseArguments(argv) {
@@ -635,6 +673,30 @@ function parseArguments(argv) {
635
673
  }
636
674
  return { command: "doctor", options };
637
675
  }
676
+ if (argv[0] === "mcp-smoke") {
677
+ const options = {};
678
+ for (let index = 1; index < argv.length; index += 1) {
679
+ const argument = argv[index];
680
+ if (argument === "--config-dir") {
681
+ const directory = argv[++index];
682
+ if (!directory)
683
+ throw new Error("--config-dir requires a directory");
684
+ options.configDirectory = directory;
685
+ }
686
+ else if (argument === "--directory") {
687
+ const directory = argv[++index];
688
+ if (!directory)
689
+ throw new Error("--directory requires a path");
690
+ options.projectDirectory = directory;
691
+ }
692
+ else if (argument === "--json") {
693
+ options.json = true;
694
+ }
695
+ else
696
+ throw new Error(`Unknown mcp-smoke option: ${argument}`);
697
+ }
698
+ return { command: "mcp-smoke", options };
699
+ }
638
700
  if (argv[0] === "update") {
639
701
  for (let index = 1; index < argv.length; index += 1)
640
702
  throw new Error(`Unknown update option: ${argv[index]}`);
@@ -719,6 +781,16 @@ async function main() {
719
781
  }
720
782
  return;
721
783
  }
784
+ if (parsed.command === "mcp-smoke") {
785
+ const report = await smokeConfiguredMcps({
786
+ ...(parsed.options.configDirectory ? { configDirectory: parsed.options.configDirectory } : {}),
787
+ ...(parsed.options.projectDirectory ? { projectDirectory: parsed.options.projectDirectory } : {}),
788
+ });
789
+ console.log(parsed.options.json ? JSON.stringify(report, null, 2) : formatConfiguredMcpSmokeReport(report));
790
+ if (!report.ok)
791
+ process.exitCode = 1;
792
+ return;
793
+ }
722
794
  if (parsed.command === "update") {
723
795
  console.log(formatUpdateResult(await checkForUpdates(await resolvePluginVersion())));
724
796
  return;