opencode-orchestrator 0.1.56 → 0.1.59

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 CHANGED
@@ -20,7 +20,7 @@ A 6-agent collaborative system that turns **affordable LLMs into reliable engine
20
20
  - **PDCA Loop** — Plan → Do → Check → Act (self-correcting)
21
21
  - **Parallel DAG** — Independent tasks run concurrently
22
22
  - **Quality Gate** — Reviewer catches all errors before merge
23
-
23
+ - **Structure** — **TypeScript Brain** for logic + **Rust Muscle** for speed
24
24
  ---
25
25
 
26
26
  ## Installation
Binary file
Binary file
@@ -0,0 +1,2 @@
1
+ import { AgentDefinition } from "./types.js";
2
+ export declare const coder: AgentDefinition;
@@ -0,0 +1,2 @@
1
+ import { AgentDefinition } from "./types.js";
2
+ export declare const AGENTS: Record<string, AgentDefinition>;
@@ -0,0 +1,2 @@
1
+ import { AgentDefinition } from "./types.js";
2
+ export declare const fixer: AgentDefinition;
@@ -0,0 +1,2 @@
1
+ import { AgentDefinition } from "./types.js";
2
+ export declare const orchestrator: AgentDefinition;
@@ -0,0 +1,2 @@
1
+ import { AgentDefinition } from "./types.js";
2
+ export declare const planner: AgentDefinition;
@@ -0,0 +1,2 @@
1
+ import { AgentDefinition } from "./types.js";
2
+ export declare const reviewer: AgentDefinition;
@@ -0,0 +1,2 @@
1
+ import { AgentDefinition } from "./types.js";
2
+ export declare const searcher: AgentDefinition;
@@ -0,0 +1,7 @@
1
+ export interface AgentDefinition {
2
+ id: string;
3
+ description: string;
4
+ systemPrompt: string;
5
+ canWrite: boolean;
6
+ canBash: boolean;
7
+ }
package/dist/cli.js CHANGED
@@ -2,13 +2,17 @@
2
2
 
3
3
  // src/cli.ts
4
4
  import { spawn } from "child_process";
5
+ import { existsSync as existsSync2 } from "fs";
6
+ import { platform as platform2, arch as arch2 } from "os";
7
+
8
+ // src/utils/binary.ts
5
9
  import { join, dirname } from "path";
6
10
  import { fileURLToPath } from "url";
7
11
  import { platform, arch } from "os";
8
12
  import { existsSync } from "fs";
9
13
  var __dirname = dirname(fileURLToPath(import.meta.url));
10
14
  function getBinaryPath() {
11
- const binDir = join(__dirname, "..", "bin");
15
+ const binDir = join(__dirname, "..", "..", "bin");
12
16
  const os = platform();
13
17
  const cpu = arch();
14
18
  let binaryName;
@@ -25,10 +29,12 @@ function getBinaryPath() {
25
29
  }
26
30
  return binaryPath;
27
31
  }
32
+
33
+ // src/cli.ts
28
34
  var binary = getBinaryPath();
29
35
  var args = process.argv.slice(2);
30
- if (!existsSync(binary)) {
31
- console.error(`Error: Orchestrator binary not found for your platform (${platform()} ${arch()})`);
36
+ if (!existsSync2(binary)) {
37
+ console.error(`Error: Orchestrator binary not found for your platform (${platform2()} ${arch2()})`);
32
38
  console.error(`Expected at: ${binary}`);
33
39
  process.exit(1);
34
40
  }
@@ -0,0 +1,14 @@
1
+ import { TaskGraph } from "./tasks.js";
2
+ export interface SessionState {
3
+ enabled: boolean;
4
+ iterations: number;
5
+ taskRetries: Map<string, number>;
6
+ currentTask: string;
7
+ graph?: TaskGraph;
8
+ }
9
+ export declare const state: {
10
+ missionActive: boolean;
11
+ maxIterations: number;
12
+ maxRetries: number;
13
+ sessions: Map<string, SessionState>;
14
+ };
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Task management for DAG-based orchestration
3
+ */
4
+ export type TaskStatus = "pending" | "running" | "completed" | "failed";
5
+ export interface Task {
6
+ id: string;
7
+ description: string;
8
+ action: string;
9
+ file: string;
10
+ dependencies: string[];
11
+ status: TaskStatus;
12
+ result?: string;
13
+ retryCount: number;
14
+ complexity: number;
15
+ type: "infrastructure" | "logic" | "integration";
16
+ }
17
+ export declare class TaskGraph {
18
+ private tasks;
19
+ constructor(tasks?: Task[]);
20
+ addTask(task: Task): void;
21
+ getTask(id: string): Task | undefined;
22
+ updateTask(id: string, updates: Partial<Task>): void;
23
+ getReadyTasks(): Task[];
24
+ isCompleted(): boolean;
25
+ hasFailed(): boolean;
26
+ getTaskSummary(): string;
27
+ toJSON(): string;
28
+ static fromJSON(json: string): TaskGraph;
29
+ }
package/dist/index.js CHANGED
@@ -1,86 +1,8 @@
1
- // src/index.ts
2
- import { spawn } from "child_process";
3
- import { join, dirname } from "path";
4
- import { fileURLToPath } from "url";
5
- import { existsSync } from "fs";
6
- import { platform, arch } from "os";
7
- import { tool } from "@opencode-ai/plugin";
8
-
9
- // src/tasks.ts
10
- var TaskGraph = class _TaskGraph {
11
- tasks = /* @__PURE__ */ new Map();
12
- constructor(tasks) {
13
- if (tasks) {
14
- tasks.forEach((t) => this.addTask(t));
15
- }
16
- }
17
- addTask(task) {
18
- this.tasks.set(task.id, { ...task, status: "pending", retryCount: 0 });
19
- }
20
- getTask(id) {
21
- return this.tasks.get(id);
22
- }
23
- updateTask(id, updates) {
24
- const task = this.tasks.get(id);
25
- if (task) {
26
- this.tasks.set(id, { ...task, ...updates });
27
- }
28
- }
29
- getReadyTasks() {
30
- return Array.from(this.tasks.values()).filter((task) => {
31
- if (task.status !== "pending") return false;
32
- return task.dependencies.every((depId) => {
33
- const dep = this.tasks.get(depId);
34
- return dep && dep.status === "completed";
35
- });
36
- });
37
- }
38
- isCompleted() {
39
- return Array.from(this.tasks.values()).every((t) => t.status === "completed");
40
- }
41
- hasFailed() {
42
- return Array.from(this.tasks.values()).some((t) => t.status === "failed" && t.retryCount >= 3);
43
- }
44
- getTaskSummary() {
45
- const tasks = Array.from(this.tasks.values());
46
- const completed = tasks.filter((t) => t.status === "completed");
47
- const notCompleted = tasks.filter((t) => t.status !== "completed");
48
- let summary = "\u{1F4CB} **Mission Status**\n";
49
- if (completed.length > 0) {
50
- summary += `\u2705 Completed: ${completed.length} tasks (Hidden to save tokens)
51
- `;
52
- }
53
- for (const task of notCompleted) {
54
- const icon = task.status === "running" ? "\u23F3" : task.status === "failed" ? "\u274C" : "\u{1F4A4}";
55
- summary += `${icon} [${task.id}] ${task.description}
56
- `;
57
- }
58
- return summary;
59
- }
60
- toJSON() {
61
- return JSON.stringify(Array.from(this.tasks.values()), null, 2);
62
- }
63
- static fromJSON(json) {
64
- try {
65
- const tasks = JSON.parse(json);
66
- return new _TaskGraph(tasks);
67
- } catch (e) {
68
- console.error("Failed to parse TaskGraph JSON:", e);
69
- return new _TaskGraph();
70
- }
71
- }
72
- };
73
-
74
- // src/index.ts
75
- var __dirname = dirname(fileURLToPath(import.meta.url));
76
- var AGENTS = {
77
- // ═══════════════════════════════════════════════════════════════
78
- // ORCHESTRATOR - Team Leader & Decision Maker
79
- // ═══════════════════════════════════════════════════════════════
80
- orchestrator: {
81
- id: "orchestrator",
82
- description: "Team leader - manages the Mission and parallel work streams",
83
- systemPrompt: `You are the Orchestrator - the mission commander.
1
+ // src/agents/orchestrator.ts
2
+ var orchestrator = {
3
+ id: "orchestrator",
4
+ description: "Team leader - manages the Mission and parallel work streams",
5
+ systemPrompt: `You are the Orchestrator - the mission commander.
84
6
 
85
7
  ## Core Philosophy: Micro-Tasking & Quality Gates
86
8
  - Even small models (Phi, Gemma) succeed when tasks are tiny and verified.
@@ -88,68 +10,99 @@ var AGENTS = {
88
10
  - NEVER proceed to a task if its dependencies are not 100% VERIFIED.
89
11
 
90
12
  ## Operational SOP (Standard Operating Procedure)
91
- 1. **PHASE 0: TRADE-OFF ANALYSIS**:
92
- - **Cost vs. Value**: Is the DAG overhead justified?
93
- - **Complexity**: If task is trivial, execute linearly (1-Node DAG).
94
- - Only engage full DAG if complexity > 3 or multiple files involved.
95
- 2. **ANALYSIS PHASE (THINK FIRST)**:
96
- - Call **searcher** to read docs.
97
- ## Operational SOP
98
- 1. PHASE 0: COMPLEXITY AUDIT. Hotfix (Linear) vs System Overhaul (Flow)?
99
- 2. ANALYSIS: MapReduce data. Shard huge context.
100
- 3. CONTRACT: Define Interface Agreement (\`_interface_contract.md\`) if parallel dependencies exist.
101
- 4. PLAN: Decompose & Alloc. Assign Agents/Tools dynamically.
102
- 5. SCHEDULE: Identify ready tasks.
103
- 6. EXECUTE: search -> code -> review.
104
- 7. GLOBAL SYNC GATE: Reviewer must verify cross-task consistency against Contract.
105
- 8. **CLEANUP**: Automatically delete the temporary mission state file (*.mission.md) AND all \`temp_context_*.md\` shards upon completion.
106
-
107
- ## Verification
108
- - Ensure you are not "guessing" libraries.
109
- - If a function signature is needed for a parallel task, READ \`_interface_contract.md\`.
110
- - If no contract exists, CREATE one.
13
+
14
+ 1. **PHASE 0: INTENT GATE & CLASSIFICATION**
15
+ - **Trivial**: Single file, direct answer -> Execute linearly.
16
+ - **Complex**: Multiple modules, "Refactor", "Add feature" -> **Engage Planner**.
17
+ - **GitHub Work**: Mentions of PR/Issue -> Cycle: Investigate -> Implement -> Verify (STOP).
18
+
19
+ ### Intent Classification Table
20
+ | Type | Action |
21
+ |------|--------|
22
+ | **Trivial** | Direct tools only |
23
+ | **Explicit** | Execute directly |
24
+ | **Exploratory** | Fire searcher + tools in parallel |
25
+ | **GitHub Work** | Investigate \u2192 Implement \u2192 Verify \u2192 Report Ready |
26
+ | **Ambiguous** | Ask ONE clarifying question |
27
+
28
+ 2. **PHASE 1: RESEARCH & PLAN**
29
+ - Call **searcher** to read docs, find patterns, and search external references.
30
+ - **Tool Selection**:
31
+ - \`grep\`, \`glob\`, \`lsp_*\`: Standard search.
32
+ - \`searcher\` agent: Contextual search & External Docs.
33
+ - **MapReduce**: Shard huge context into temporary files (\`temp_context_*.md\`).
34
+
35
+ 3. **PHASE 2: EXECUTE (The Loop)**
36
+ - Execute tasks in DAG order.
37
+
38
+ ### Frontend Decision Gate (CRITICAL)
39
+ Before touching .tsx/.css files, ask: **"Is this LOOKS or WORKS?"**
40
+ - **LOOKS** (Visual/UI): **STOP**. Ask user for confirmation or specific design specs before calling Coder.
41
+ - **WORKS** (Logic): Call **coder** for atomic implementation.
42
+
43
+ ### Delegation Prompt Structure (MANDATORY)
44
+ When calling subagents (Coder, Searcher, Planner, Reviewer, Fixer), your prompt MUST include:
45
+ 1. **TASK**: Atomic, specific goal
46
+ 2. **EXPECTED OUTCOME**: Concrete deliverables
47
+ 3. **REQUIRED TOOLS**: Explicit tool whitelist
48
+ 4. **MUST DO**: Exhaustive requirements
49
+ 5. **MUST NOT DO**: Forbidden actions
50
+ 6. **CONTEXT**: File paths, patterns, constraints
51
+
52
+ 4. **PHASE 3: VERIFY & FIX**
53
+ - Call **reviewer** after EVERY implementation step.
54
+ - **5-Point Check**: Syntax, Style, Logic, Integrity, Data Flow.
55
+ - **Evidence Requirements**:
56
+ - File edit: \`lsp_diagnostics\` clean
57
+ - Build/Test: Exit code 0
58
+ - If Fail: Call **fixer** (minimal changes).
59
+
60
+ 5. **PHASE 4: COMPLETION**
61
+ - Confirm all planned tasks are done.
62
+ - **Cleanup**: Delete temporary mission/shard files.
63
+ - **Final Report**: "MISSION COMPLETE"
64
+
65
+ ## GitHub Workflow (If mentioned in PR/Issue)
66
+ 1. **Investigate**: Read issue, search codebase.
67
+ 2. **Implement**: Minimal changes, follow patterns.
68
+ 3. **Verify**: Build, Test, Check Regressions.
69
+ 4. **Report**: State "Ready for human review/PR". **DO NOT push or create PR yourself.**
70
+
71
+ ## Hard Rules (NEVER violate)
72
+ - **NO GIT PUSH**: You are NOT allowed to push code.
73
+ - **NO PR CREATION**: Do not create Pull Requests.
74
+ - **NO GIT COMMITS**: Do not commit unless explicitly asked by user.
75
+ - **NO HALLUCINATED AGENTS**: Only use [Orchestrator, Planner, Coder, Reviewer, Fixer, Searcher].
76
+
77
+ ## Communication Style
78
+ - **Concise**: Start work immediately. No "I'm on it".
79
+ - **Direct**: Answer directly without preamble.
80
+ - **No Flattery**: No "Great question!".
81
+ - **Status Not Updates**: Use "Mission Status" block instead of chatty updates.
82
+
83
+
111
84
 
112
85
  ## Global Consistency Rules (Mandatory)
113
86
  - **State Persistence**: Independent nodes MUST communicate via files, not memory.
114
87
  - **Import Sync**: Any export change MUST trigger an update in all importing files.
115
- - **Signature Sync**: Function signature changes MUST be propagated to all callers in the same DAG layer.
116
- - **Type Sync**: Shared types MUST be modified in isolation before logic implementation.
117
88
  - **Atomic Integrity**: Parallel tasks MUST NOT modify the same line of code in the same file.
118
-
119
- ## Memory Management Strategy (Infinite Context Simulation)
120
- - **Sharding**: Never hold raw code in context. Write it to a file, keep the reference.
121
- - **Garbage Collection**: If a task is done, summarize its outcome ("Task A: Success, Output at /file/path") and FORGET the details.
122
- - **Value Judgment**: Do not summarize "process". Summarize "state changes".
123
-
124
- ## Safety & Boundary SOP
125
- - **Safety Gate**: Verify alignment with project core before any execution.
126
- - **Sync Sentinel**: You are responsible for cross-task logic consistency. If tasks drift, HALT and re-sync.
127
-
128
- ## Failure Recovery SOP
129
- - **Error 1-2**: Call fixer as usual.
130
- - **Error 3**: Pivot. Call searcher for similar fixes or planner to split the task further.
131
- - **Syntax Error**: Fixer MUST only fix syntax, no logic changes.
132
-
133
- ## Reliable Execution with Fixed Models
134
- - This system is optimized for fixed, low-performance models (Phi, Gemma, etc.).
135
- - Performance is achieved through granularity, not model upgrades.
89
+ - **Trust No One**: Subagents can hallucinate. Verify their outputs with tools.
136
90
 
137
91
  ## Progress Status
138
92
  Always show the Mission status at the end of your turns:
139
- \u{1F4CB} Mission Status:
140
- [TASK-001] \u2705 Completed
141
- [TASK-002] \u23F3 Running
142
- [TASK-003] \u{1F4A4} Pending`,
143
- canWrite: false,
144
- canBash: false
145
- },
146
- // ═══════════════════════════════════════════════════════════════
147
- // PLANNER - Atomic Task Decomposition
148
- // ═══════════════════════════════════════════════════════════════
149
- planner: {
150
- id: "planner",
151
- description: "Architect - decomposes work into a JSON Mission",
152
- systemPrompt: `You are the Planner - the master architect.
93
+ Mission Status:
94
+ [TASK-001] Completed
95
+ [TASK-002] Running
96
+ [TASK-003] Pending`,
97
+ canWrite: false,
98
+ canBash: false
99
+ };
100
+
101
+ // src/agents/planner.ts
102
+ var planner = {
103
+ id: "planner",
104
+ description: "Architect - decomposes work into a JSON Mission",
105
+ systemPrompt: `You are the Planner - the master architect.
153
106
 
154
107
  ## Your Mission
155
108
  1. **Understand & Filter**: Read documentation, but **FILTER** out irrelevant parts. determine what is truly important.
@@ -197,16 +150,15 @@ Produce a JSON array of tasks:
197
150
  - Break circular dependencies.
198
151
  - Ensure all files are identified by absolute or relative path from project root.
199
152
  - Keep complexity < 7. If higher, split the task.`,
200
- canWrite: false,
201
- canBash: false
202
- },
203
- // ═══════════════════════════════════════════════════════════════
204
- // CODER - Single Task Implementation
205
- // ═══════════════════════════════════════════════════════════════
206
- coder: {
207
- id: "coder",
208
- description: "Implementation - executes one atomic task with complete, working code",
209
- systemPrompt: `You are the Coder - implementation specialist.
153
+ canWrite: false,
154
+ canBash: false
155
+ };
156
+
157
+ // src/agents/coder.ts
158
+ var coder = {
159
+ id: "coder",
160
+ description: "Implementation - executes one atomic task with complete, working code",
161
+ systemPrompt: `You are the Coder - implementation specialist.
210
162
 
211
163
  ## Your Job
212
164
  Execute the ONE atomic task you're given. Produce complete, working code.
@@ -253,16 +205,15 @@ Provide COMPLETE code that:
253
205
  \`\`\`
254
206
 
255
207
  Brief explanation if needed.`,
256
- canWrite: true,
257
- canBash: true
258
- },
259
- // ═══════════════════════════════════════════════════════════════
260
- // REVIEWER - Quality Gate
261
- // ═══════════════════════════════════════════════════════════════
262
- reviewer: {
263
- id: "reviewer",
264
- description: "Style Guardian & Sync Sentinel - ensures total code consistency",
265
- systemPrompt: `You are the Reviewer - the Style Guardian and Sync Sentinel.
208
+ canWrite: true,
209
+ canBash: true
210
+ };
211
+
212
+ // src/agents/reviewer.ts
213
+ var reviewer = {
214
+ id: "reviewer",
215
+ description: "Style Guardian & Sync Sentinel - ensures total code consistency",
216
+ systemPrompt: `You are the Reviewer - the Style Guardian and Sync Sentinel.
266
217
 
267
218
  ## Your Job
268
219
  1. **Task Review**: Verify individual code changes (Syntax, Style, Logic).
@@ -282,27 +233,26 @@ Brief explanation if needed.`,
282
233
  ## Review Results (MANDATORY Format)
283
234
  ### If PASS:
284
235
  \`\`\`
285
- \u2705 PASS (Confidence: 100%)
236
+ PASS (Confidence: 100%)
286
237
  - All individual checks passed.
287
238
  - Global Sync Check: NO drift detected.
288
239
  \`\`\`
289
240
 
290
241
  ### If FAIL:
291
242
  \`\`\`
292
- \u274C FAIL [SYNC-ERROR | STYLE | LOGIC]
243
+ FAIL [SYNC-ERROR | STYLE | LOGIC]
293
244
  ...
294
245
  \`\`\`
295
246
  `,
296
- canWrite: false,
297
- canBash: true
298
- },
299
- // ═══════════════════════════════════════════════════════════════
300
- // FIXER - Error Resolution
301
- // ═══════════════════════════════════════════════════════════════
302
- fixer: {
303
- id: "fixer",
304
- description: "Error resolution - applies targeted fixes based on reviewer feedback",
305
- systemPrompt: `You are the Fixer - error resolution specialist.
247
+ canWrite: false,
248
+ canBash: true
249
+ };
250
+
251
+ // src/agents/fixer.ts
252
+ var fixer = {
253
+ id: "fixer",
254
+ description: "Error resolution - applies targeted fixes based on reviewer feedback",
255
+ systemPrompt: `You are the Fixer - error resolution specialist.
306
256
 
307
257
  ## Your Job
308
258
  Fix the SPECIFIC errors reported by reviewer.
@@ -349,16 +299,15 @@ You receive error reports like:
349
299
  - Ask for clarification
350
300
  - Show what you understand
351
301
  - Propose alternative fix`,
352
- canWrite: true,
353
- canBash: true
354
- },
355
- // ═══════════════════════════════════════════════════════════════
356
- // SEARCHER - Context Provider
357
- // ═══════════════════════════════════════════════════════════════
358
- searcher: {
359
- id: "searcher",
360
- description: "Context provider - finds documentation and codebase patterns",
361
- systemPrompt: `You are the Searcher - the context oracle.
302
+ canWrite: true,
303
+ canBash: true
304
+ };
305
+
306
+ // src/agents/searcher.ts
307
+ var searcher = {
308
+ id: "searcher",
309
+ description: "Context provider - finds documentation and codebase patterns",
310
+ systemPrompt: `You are the Searcher - the context oracle.
362
311
 
363
312
  ## Mission
364
313
  Your primary job is to find the **Truth** in the codebase.
@@ -384,64 +333,86 @@ OR
384
333
  ### 1. Architectural Boundaries (from docs)
385
334
  ### 2. Relevant Patterns (code snippets)
386
335
  ### 3. Recommendations`,
387
- canWrite: false,
388
- canBash: false
389
- }
336
+ canWrite: false,
337
+ canBash: false
390
338
  };
391
- function getBinaryPath() {
392
- const binDir = join(__dirname, "..", "bin");
393
- const os = platform();
394
- const cpu = arch();
395
- let binaryName;
396
- if (os === "win32") {
397
- binaryName = "orchestrator-windows-x64.exe";
398
- } else if (os === "darwin") {
399
- binaryName = cpu === "arm64" ? "orchestrator-macos-arm64" : "orchestrator-macos-x64";
400
- } else {
401
- binaryName = cpu === "arm64" ? "orchestrator-linux-arm64" : "orchestrator-linux-x64";
339
+
340
+ // src/agents/definitions.ts
341
+ var AGENTS = {
342
+ orchestrator,
343
+ planner,
344
+ coder,
345
+ reviewer,
346
+ fixer,
347
+ searcher
348
+ };
349
+
350
+ // src/core/tasks.ts
351
+ var TaskGraph = class _TaskGraph {
352
+ tasks = /* @__PURE__ */ new Map();
353
+ constructor(tasks) {
354
+ if (tasks) {
355
+ tasks.forEach((t) => this.addTask(t));
356
+ }
402
357
  }
403
- let binaryPath = join(binDir, binaryName);
404
- if (!existsSync(binaryPath)) {
405
- binaryPath = join(binDir, os === "win32" ? "orchestrator.exe" : "orchestrator");
358
+ addTask(task) {
359
+ this.tasks.set(task.id, { ...task, status: "pending", retryCount: 0 });
406
360
  }
407
- return binaryPath;
408
- }
409
- async function callRustTool(name, args) {
410
- const binary = getBinaryPath();
411
- if (!existsSync(binary)) {
412
- return JSON.stringify({ error: `Binary not found: ${binary}` });
361
+ getTask(id) {
362
+ return this.tasks.get(id);
413
363
  }
414
- return new Promise((resolve) => {
415
- const proc = spawn(binary, ["serve"], { stdio: ["pipe", "pipe", "pipe"] });
416
- let stdout = "";
417
- proc.stdout.on("data", (data) => {
418
- stdout += data.toString();
419
- });
420
- const request = JSON.stringify({
421
- jsonrpc: "2.0",
422
- id: 1,
423
- method: "tools/call",
424
- params: { name, arguments: args }
425
- });
426
- proc.stdin.write(request + "\n");
427
- proc.stdin.end();
428
- const timeout = setTimeout(() => {
429
- proc.kill();
430
- resolve(JSON.stringify({ error: "Timeout" }));
431
- }, 6e4);
432
- proc.on("close", () => {
433
- clearTimeout(timeout);
434
- try {
435
- const lines = stdout.trim().split("\n");
436
- const response = JSON.parse(lines[lines.length - 1]);
437
- const text = response?.result?.content?.[0]?.text;
438
- resolve(text || JSON.stringify(response.result));
439
- } catch {
440
- resolve(stdout || "No output");
441
- }
364
+ updateTask(id, updates) {
365
+ const task = this.tasks.get(id);
366
+ if (task) {
367
+ this.tasks.set(id, { ...task, ...updates });
368
+ }
369
+ }
370
+ getReadyTasks() {
371
+ return Array.from(this.tasks.values()).filter((task) => {
372
+ if (task.status !== "pending") return false;
373
+ return task.dependencies.every((depId) => {
374
+ const dep = this.tasks.get(depId);
375
+ return dep && dep.status === "completed";
376
+ });
442
377
  });
443
- });
444
- }
378
+ }
379
+ isCompleted() {
380
+ return Array.from(this.tasks.values()).every((t) => t.status === "completed");
381
+ }
382
+ hasFailed() {
383
+ return Array.from(this.tasks.values()).some((t) => t.status === "failed" && t.retryCount >= 3);
384
+ }
385
+ getTaskSummary() {
386
+ const tasks = Array.from(this.tasks.values());
387
+ const completed = tasks.filter((t) => t.status === "completed");
388
+ const notCompleted = tasks.filter((t) => t.status !== "completed");
389
+ let summary = "\u{1F4CB} **Mission Status**\n";
390
+ if (completed.length > 0) {
391
+ summary += `\u2705 Completed: ${completed.length} tasks (Hidden to save tokens)
392
+ `;
393
+ }
394
+ for (const task of notCompleted) {
395
+ const icon = task.status === "running" ? "\u23F3" : task.status === "failed" ? "\u274C" : "\u{1F4A4}";
396
+ summary += `${icon} [${task.id}] ${task.description}
397
+ `;
398
+ }
399
+ return summary;
400
+ }
401
+ toJSON() {
402
+ return JSON.stringify(Array.from(this.tasks.values()), null, 2);
403
+ }
404
+ static fromJSON(json) {
405
+ try {
406
+ const tasks = JSON.parse(json);
407
+ return new _TaskGraph(tasks);
408
+ } catch (e) {
409
+ console.error("Failed to parse TaskGraph JSON:", e);
410
+ return new _TaskGraph();
411
+ }
412
+ }
413
+ };
414
+
415
+ // src/core/state.ts
445
416
  var state = {
446
417
  missionActive: false,
447
418
  maxIterations: 1e3,
@@ -449,6 +420,9 @@ var state = {
449
420
  maxRetries: 3,
450
421
  sessions: /* @__PURE__ */ new Map()
451
422
  };
423
+
424
+ // src/tools/callAgent.ts
425
+ import { tool } from "@opencode-ai/plugin";
452
426
  var callAgentTool = tool({
453
427
  description: `Call a team member to perform specific work.
454
428
 
@@ -503,6 +477,9 @@ Execute according to your role. Be thorough and precise.
503
477
  return prompt;
504
478
  }
505
479
  });
480
+
481
+ // src/tools/slashCommand.ts
482
+ import { tool as tool2 } from "@opencode-ai/plugin";
506
483
  var COMMANDS = {
507
484
  "task": {
508
485
  description: "Execute a mission using Distributed Cognitive Architecture (PDCA Cycle)",
@@ -611,12 +588,12 @@ function createSlashcommandTool() {
611
588
  const hint = cmd.argumentHint ? ` ${cmd.argumentHint}` : "";
612
589
  return `- /${name}${hint}: ${cmd.description}`;
613
590
  }).join("\n");
614
- return tool({
591
+ return tool2({
615
592
  description: `Commands
616
593
 
617
594
  ${commandList}`,
618
595
  args: {
619
- command: tool.schema.string().describe("Command (without slash)")
596
+ command: tool2.schema.string().describe("Command (without slash)")
620
597
  },
621
598
  async execute(args) {
622
599
  const cmdName = (args.command || "").replace(/^\//, "").split(/\s+/)[0].toLowerCase();
@@ -631,11 +608,83 @@ ${commandList}`;
631
608
  }
632
609
  });
633
610
  }
634
- var grepSearchTool = (directory) => tool({
611
+
612
+ // src/tools/search.ts
613
+ import { tool as tool3 } from "@opencode-ai/plugin";
614
+
615
+ // src/tools/rust.ts
616
+ import { spawn } from "child_process";
617
+ import { existsSync as existsSync2 } from "fs";
618
+
619
+ // src/utils/binary.ts
620
+ import { join, dirname } from "path";
621
+ import { fileURLToPath } from "url";
622
+ import { platform, arch } from "os";
623
+ import { existsSync } from "fs";
624
+ var __dirname = dirname(fileURLToPath(import.meta.url));
625
+ function getBinaryPath() {
626
+ const binDir = join(__dirname, "..", "..", "bin");
627
+ const os = platform();
628
+ const cpu = arch();
629
+ let binaryName;
630
+ if (os === "win32") {
631
+ binaryName = "orchestrator-windows-x64.exe";
632
+ } else if (os === "darwin") {
633
+ binaryName = cpu === "arm64" ? "orchestrator-macos-arm64" : "orchestrator-macos-x64";
634
+ } else {
635
+ binaryName = cpu === "arm64" ? "orchestrator-linux-arm64" : "orchestrator-linux-x64";
636
+ }
637
+ let binaryPath = join(binDir, binaryName);
638
+ if (!existsSync(binaryPath)) {
639
+ binaryPath = join(binDir, os === "win32" ? "orchestrator.exe" : "orchestrator");
640
+ }
641
+ return binaryPath;
642
+ }
643
+
644
+ // src/tools/rust.ts
645
+ async function callRustTool(name, args) {
646
+ const binary = getBinaryPath();
647
+ if (!existsSync2(binary)) {
648
+ return JSON.stringify({ error: `Binary not found: ${binary}` });
649
+ }
650
+ return new Promise((resolve) => {
651
+ const proc = spawn(binary, ["serve"], { stdio: ["pipe", "pipe", "pipe"] });
652
+ let stdout = "";
653
+ proc.stdout.on("data", (data) => {
654
+ stdout += data.toString();
655
+ });
656
+ const request = JSON.stringify({
657
+ jsonrpc: "2.0",
658
+ id: 1,
659
+ method: "tools/call",
660
+ params: { name, arguments: args }
661
+ });
662
+ proc.stdin.write(request + "\n");
663
+ proc.stdin.end();
664
+ const timeout = setTimeout(() => {
665
+ proc.kill();
666
+ resolve(JSON.stringify({ error: "Timeout" }));
667
+ }, 6e4);
668
+ proc.on("close", () => {
669
+ clearTimeout(timeout);
670
+ try {
671
+ const lines = stdout.trim().split("\n");
672
+ const response = JSON.parse(lines[lines.length - 1]);
673
+ const text = response?.result?.content?.[0]?.text;
674
+ resolve(text || JSON.stringify(response.result));
675
+ } catch {
676
+ resolve(stdout || "No output");
677
+ }
678
+ });
679
+ });
680
+ }
681
+
682
+ // src/tools/search.ts
683
+ var grepSearchTool = (directory) => tool3({
635
684
  description: "Search code patterns",
636
685
  args: {
637
- pattern: tool.schema.string().describe("Regex pattern"),
638
- dir: tool.schema.string().optional().describe("Directory")
686
+ pattern: tool3.schema.string().describe("Regex pattern"),
687
+ dir: tool3.schema.string().optional().describe("Directory")
639
688
  },
640
689
  async execute(args) {
641
690
  return callRustTool("grep_search", {
@@ -644,11 +693,11 @@ var grepSearchTool = (directory) => tool({
644
693
  });
645
694
  }
646
695
  });
647
- var globSearchTool = (directory) => tool({
696
+ var globSearchTool = (directory) => tool3({
648
697
  description: "Find files by pattern",
649
698
  args: {
650
- pattern: tool.schema.string().describe("Glob pattern"),
651
- dir: tool.schema.string().optional().describe("Directory")
699
+ pattern: tool3.schema.string().describe("Glob pattern"),
700
+ dir: tool3.schema.string().optional().describe("Directory")
652
701
  },
653
702
  async execute(args) {
654
703
  return callRustTool("glob_search", {
@@ -657,11 +706,15 @@ var globSearchTool = (directory) => tool({
657
706
  });
658
707
  }
659
708
  });
709
+
710
+ // src/utils/common.ts
660
711
  function detectSlashCommand(text) {
661
712
  const match = text.trim().match(/^\/([a-zA-Z0-9_-]+)(?:\s+(.*))?$/);
662
713
  if (!match) return null;
663
714
  return { command: match[1], args: match[2] || "" };
664
715
  }
716
+
717
+ // src/index.ts
665
718
  var OrchestratorPlugin = async (input) => {
666
719
  const { directory } = input;
667
720
  return {
@@ -749,12 +802,8 @@ var OrchestratorPlugin = async (input) => {
749
802
  }
750
803
  }
751
804
  if (session.iterations >= state.maxIterations) {
805
+ state.missionActive = false;
752
806
  session.enabled = false;
753
- output.output += `
754
-
755
- \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501
756
- \u26A0\uFE0F ITERATION LIMIT (${state.maxIterations})
757
- Review progress and continue manually.`;
758
807
  return;
759
808
  }
760
809
  if (output.output.includes("[") && output.output.includes("]") && output.output.includes("{") && input2.tool === "call_agent") {
@@ -0,0 +1,19 @@
1
+ export declare const callAgentTool: {
2
+ description: string;
3
+ args: {
4
+ agent: import("zod").ZodEnum<{
5
+ planner: "planner";
6
+ coder: "coder";
7
+ reviewer: "reviewer";
8
+ fixer: "fixer";
9
+ searcher: "searcher";
10
+ }>;
11
+ task: import("zod").ZodString;
12
+ context: import("zod").ZodOptional<import("zod").ZodString>;
13
+ };
14
+ execute(args: {
15
+ agent: "planner" | "coder" | "reviewer" | "fixer" | "searcher";
16
+ task: string;
17
+ context?: string | undefined;
18
+ }, context: import("@opencode-ai/plugin").ToolContext): Promise<string>;
19
+ };
@@ -0,0 +1 @@
1
+ export declare function callRustTool(name: string, args: Record<string, unknown>): Promise<string>;
@@ -0,0 +1,22 @@
1
+ export declare const grepSearchTool: (directory: string) => {
2
+ description: string;
3
+ args: {
4
+ pattern: import("zod").ZodString;
5
+ dir: import("zod").ZodOptional<import("zod").ZodString>;
6
+ };
7
+ execute(args: {
8
+ pattern: string;
9
+ dir?: string | undefined;
10
+ }, context: import("@opencode-ai/plugin").ToolContext): Promise<string>;
11
+ };
12
+ export declare const globSearchTool: (directory: string) => {
13
+ description: string;
14
+ args: {
15
+ pattern: import("zod").ZodString;
16
+ dir: import("zod").ZodOptional<import("zod").ZodString>;
17
+ };
18
+ execute(args: {
19
+ pattern: string;
20
+ dir?: string | undefined;
21
+ }, context: import("@opencode-ai/plugin").ToolContext): Promise<string>;
22
+ };
@@ -0,0 +1,14 @@
1
+ export declare const COMMANDS: Record<string, {
2
+ description: string;
3
+ template: string;
4
+ argumentHint?: string;
5
+ }>;
6
+ export declare function createSlashcommandTool(): {
7
+ description: string;
8
+ args: {
9
+ command: import("zod").ZodString;
10
+ };
11
+ execute(args: {
12
+ command: string;
13
+ }, context: import("@opencode-ai/plugin").ToolContext): Promise<string>;
14
+ };
@@ -0,0 +1 @@
1
+ export declare function getBinaryPath(): string;
@@ -0,0 +1,4 @@
1
+ export declare function detectSlashCommand(text: string): {
2
+ command: string;
3
+ args: string;
4
+ } | null;
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "opencode-orchestrator",
3
3
  "displayName": "OpenCode Orchestrator",
4
4
  "description": "Distributed Cognitive Architecture for OpenCode. Turns simple prompts into specialized multi-agent workflows (Planner, Coder, Reviewer).",
5
- "version": "0.1.56",
5
+ "version": "0.1.59",
6
6
  "author": "agnusdei1207",
7
7
  "license": "MIT",
8
8
  "repository": {