@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.
- package/README.md +19 -6
- package/dashboard-dist/assets/index-D1JhVhPt.css +2 -0
- package/dashboard-dist/assets/index-YMCkRwnG.js +132 -0
- package/dashboard-dist/index.html +2 -2
- package/dist/agents/editor.d.ts +1 -1
- package/dist/agents/editor.js +2 -1
- package/dist/agents/editor.js.map +1 -1
- package/dist/agents/integrator.d.ts +1 -1
- package/dist/agents/integrator.js +2 -1
- package/dist/agents/integrator.js.map +1 -1
- package/dist/agents/lead.d.ts +1 -1
- package/dist/agents/lead.js +5 -8
- package/dist/agents/lead.js.map +1 -1
- package/dist/agents/types.d.ts +6 -0
- package/dist/agents/types.js +51 -1
- package/dist/agents/types.js.map +1 -1
- package/dist/agents/workers.d.ts +1 -1
- package/dist/agents/workers.js +7 -9
- package/dist/agents/workers.js.map +1 -1
- package/dist/cli.js +94 -22
- package/dist/cli.js.map +1 -1
- package/dist/dashboard/server.js +52 -12
- package/dist/dashboard/server.js.map +1 -1
- package/dist/diagnostics/completion.js +9 -1
- package/dist/diagnostics/completion.js.map +1 -1
- package/dist/diagnostics/doctor.js +2 -2
- package/dist/diagnostics/doctor.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +60 -0
- package/dist/index.js.map +1 -1
- package/dist/mcp/commands.d.ts +5 -0
- package/dist/mcp/commands.js +21 -0
- package/dist/mcp/commands.js.map +1 -0
- package/dist/mcp/config-smoke.d.ts +21 -0
- package/dist/mcp/config-smoke.js +95 -0
- package/dist/mcp/config-smoke.js.map +1 -0
- package/dist/mcp/smoke.d.ts +23 -0
- package/dist/mcp/smoke.js +148 -0
- package/dist/mcp/smoke.js.map +1 -0
- package/dist/plugin-status.js +13 -7
- package/dist/plugin-status.js.map +1 -1
- package/dist/telemetry/ledger.d.ts +24 -0
- package/dist/telemetry/ledger.js +48 -0
- package/dist/telemetry/ledger.js.map +1 -1
- package/package.json +4 -2
- package/prompts/editor.md +4 -3
- package/prompts/lead.md +4 -1
- package/prompts/repo.md +1 -1
- package/prompts/tests.md +1 -0
- package/dashboard-dist/assets/index-CbNmtkWh.css +0 -2
- 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-
|
|
9
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
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>
|
package/dist/agents/editor.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { OrchestraConfig } from "../config/schema.js";
|
|
2
|
-
import type
|
|
2
|
+
import { type RuntimeAgentConfig } from "./types.js";
|
|
3
3
|
export declare function createEditorAgent(config: OrchestraConfig, prompt?: string): RuntimeAgentConfig;
|
package/dist/agents/editor.js
CHANGED
|
@@ -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:
|
|
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;
|
|
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
|
|
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:
|
|
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;
|
|
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"}
|
package/dist/agents/lead.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { OrchestraConfig } from "../config/schema.js";
|
|
2
|
-
import type
|
|
2
|
+
import { type RuntimeAgentConfig } from "./types.js";
|
|
3
3
|
export declare function createLeadAgent(config: OrchestraConfig, basePrompt: string): RuntimeAgentConfig;
|
package/dist/agents/lead.js
CHANGED
|
@@ -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
|
|
33
|
-
|
|
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
|
-
|
|
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",
|
package/dist/agents/lead.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lead.js","sourceRoot":"","sources":["../../src/agents/lead.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AACxD,OAAO,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAA;
|
|
1
|
+
{"version":3,"file":"lead.js","sourceRoot":"","sources":["../../src/agents/lead.ts"],"names":[],"mappings":"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"}
|
package/dist/agents/types.d.ts
CHANGED
|
@@ -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";
|
package/dist/agents/types.js
CHANGED
|
@@ -1,2 +1,52 @@
|
|
|
1
|
-
|
|
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
|
package/dist/agents/types.js.map
CHANGED
|
@@ -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"}
|
package/dist/agents/workers.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { OrchestraConfig } from "../config/schema.js";
|
|
2
|
-
import type
|
|
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;
|
package/dist/agents/workers.js
CHANGED
|
@@ -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
|
-
|
|
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:
|
|
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":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAA;
|
|
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 =
|
|
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
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
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 =
|
|
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 =
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
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
|
|
338
|
-
//
|
|
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
|
-
|
|
341
|
-
|
|
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:
|
|
515
|
+
command: Array.isArray(git.command) ? git.command : [git.command],
|
|
516
|
+
cwd: ".",
|
|
486
517
|
enabled: true,
|
|
487
|
-
timeout:
|
|
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:
|
|
524
|
+
command: Array.isArray(astGrep.command) ? astGrep.command : [astGrep.command],
|
|
525
|
+
cwd: ".",
|
|
494
526
|
enabled: true,
|
|
495
|
-
timeout:
|
|
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;
|