opencode-orchestrator 0.9.10 โ†’ 0.9.12

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
@@ -55,77 +55,50 @@ Then in OpenCode:
55
55
  ## ๐Ÿ›๏ธ How It Works
56
56
 
57
57
  ```
58
- YOU
59
- โ”‚
60
- โ”‚ /task "Build REST API"
61
- โ–ผ
62
- โ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•—
63
- โ•‘ ๐ŸŽฏ COMMANDER โ•‘
64
- โ•‘ "I orchestrate. I never sleep." โ•‘
65
- โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
66
- โ”‚
67
- โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
68
- โ”‚ โ”‚ โ”‚
69
- โ–ผ โ–ผ โ–ผ
70
- โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
71
- โ”‚๐Ÿ“‹ PLANNERโ”‚ โ”‚๐Ÿ”จ WORKER โ”‚ โ”‚๐Ÿ”จ WORKER โ”‚ x50 PARALLEL
72
- โ”‚ Plan & โ”‚ โ”‚ auth.ts โ”‚ โ”‚ api.ts โ”‚ SESSIONS
73
- โ”‚ Research โ”‚ โ”‚ (TDD) โ”‚ โ”‚ (TDD) โ”‚
74
- โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
75
- โ”‚ โ”‚ โ”‚
76
- โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
77
- โ–ผ
78
- โ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•—
79
- โ•‘ โœ… REVIEWER โ•‘
80
- โ•‘ E2E Tests โ€ข Sync Check โ€ข Validate โ•‘
81
- โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
82
- โ”‚
83
- โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”
84
- โ”‚ Complete? โ”‚
85
- โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”˜
86
- No โ†™ โ†˜ Yes
87
- โ™ป๏ธ ๐ŸŽ–๏ธ
88
- LOOP SEALED
89
- (auto-fix) (mission done)
58
+ /task "Build REST API"
59
+ โ”‚
60
+ โ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•งโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•—
61
+ โ•‘ ๐ŸŽฏ COMMANDER โ•‘
62
+ โ•‘ Delegate โ†’ Loop โ•‘
63
+ โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•คโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
64
+ โ”‚
65
+ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
66
+ โ”‚ โ”‚ โ”‚
67
+ โ–ผ โ–ผ โ–ผ
68
+ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
69
+ โ”‚๐Ÿ“‹PLANNERโ”‚ โ”‚๐Ÿ”จWORKER โ”‚ โ”‚๐Ÿ”จWORKER โ”‚
70
+ โ”‚ plan.md โ”‚ โ”‚ auth.ts โ”‚ โ”‚ api.ts โ”‚
71
+ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
72
+ โ”‚ โ”‚ โ”‚
73
+ โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚
74
+ โ”‚ โ”‚ ๐Ÿ”€ 50 PARALLEL SESSIONS โ”‚ โ”‚
75
+ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚
76
+ โ”‚ โ”‚ โ”‚
77
+ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
78
+ โ–ผ
79
+ โ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•งโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•—
80
+ โ•‘ โœ… REVIEWER โ•‘
81
+ โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•คโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
82
+ โ”‚
83
+ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
84
+ โ”‚ TODO 100%? โ”‚
85
+ โ”‚ Issues = 0? โ”‚
86
+ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
87
+ No โ†™ โ†˜ Yes
88
+ โ™ป๏ธ LOOP ๐ŸŽ–๏ธ SEALED
90
89
  ```
91
90
 
92
- ---
93
-
94
- ## ๐Ÿค– The 4 Agents
95
-
96
- | Agent | Role | Superpower |
97
- |-------|------|------------|
98
- | **๐ŸŽฏ Commander** | Orchestrator | Sees everything, delegates intelligently, never stops |
99
- | **๐Ÿ“‹ Planner** | Strategist | Web search, doc caching, file-level task breakdown |
100
- | **๐Ÿ”จ Worker** | Builder | TDD isolation, 1 file = 1 session, parallel execution |
101
- | **โœ… Reviewer** | Quality Gate | E2E tests, sync checks, integration validation |
102
-
103
- ---
104
-
105
- ## ๐Ÿ“Š System Specs
106
-
107
- | Capability | Value |
108
- |------------|-------|
109
- | **Parallel Sessions** | 50 simultaneous |
110
- | **Concurrency per Agent** | 10 default |
111
- | **Poll Interval** | 1 second |
112
- | **Session TTL** | 60 minutes |
113
- | **Auto-Recovery** | 3 attempts per session |
114
- | **Max Iterations** | 20 per mission |
115
- | **Memory Limit** | 1,000 tasks (auto GC) |
116
-
117
- ---
118
-
119
- ## ๐ŸŽฎ What Happens When You Run `/task`
91
+ ### ๐Ÿ”‘ Key Systems
120
92
 
121
- 1. **๐ŸŽฏ Commander** reads state, creates TODO
122
- 2. **๐Ÿ“‹ Planner** breaks down into file-level tasks
123
- 3. **๐Ÿ”จ Workers** build in parallel (50 simultaneous sessions!)
124
- 4. **โœ… Reviewer** validates, runs E2E tests
125
- 5. **โ™ป๏ธ Loop** until all TODOs checked + zero issues
126
- 6. **๐ŸŽ–๏ธ SEALED** โ€” mission complete
93
+ | System | What It Does |
94
+ |:------:|:-------------|
95
+ | **๐Ÿ”€ Multi-Session** | `delegate_task` โ†’ `client.session.create()` โ†’ new isolated session |
96
+ | **โšก Parallel Agents** | 50 sessions run simultaneously, `ConcurrencyController` manages slots |
97
+ | **๐Ÿ–ฅ๏ธ Background Tasks** | `run_background` โ†’ async shell commands, non-blocking |
98
+ | **๐Ÿ”„ Auto-Continuation** | `session.idle` โ†’ check TODOs โ†’ inject prompt โ†’ keep going |
99
+ | **๐Ÿ›ก๏ธ Self-Healing** | Rate limits, crashes โ†’ 3 auto-retries per session |
127
100
 
128
- > **Tip:** Stop anytime with `/stop`
101
+ > **Stop anytime:** `/stop`
129
102
 
130
103
  <div align="center">
131
104
  <p><strong>TUI</strong></p>
package/dist/index.js CHANGED
@@ -94,6 +94,7 @@ var MEMORY_LIMITS = {
94
94
  };
95
95
 
96
96
  // src/shared/task/constants/parallel-task.ts
97
+ var PARALLEL_LABEL = "parallel";
97
98
  var PARALLEL_TASK = {
98
99
  // Task lifecycle (24 hours for long tasks)
99
100
  TTL_MS: 24 * TIME.HOUR,
@@ -108,7 +109,12 @@ var PARALLEL_TASK = {
108
109
  MIN_IDLE_TIME_MS: 5 * TIME.SECOND,
109
110
  MIN_STABILITY_MS: 3 * TIME.SECOND,
110
111
  STABLE_POLLS_REQUIRED: 3,
111
- MAX_POLL_COUNT: 600
112
+ MAX_POLL_COUNT: 600,
113
+ // Session naming
114
+ SESSION_TITLE_PREFIX: "Parallel",
115
+ // Labels for output
116
+ LABEL: PARALLEL_LABEL,
117
+ GROUP_PREFIX: `${PARALLEL_LABEL}:`
112
118
  };
113
119
 
114
120
  // src/shared/task/constants/background-task.ts
@@ -328,6 +334,15 @@ var PROMPTS = {
328
334
  CONTINUE_DEFAULT: "continue from where we left off"
329
335
  };
330
336
 
337
+ // src/shared/message/constants/slash-commands.ts
338
+ var COMMAND_NAMES = {
339
+ TASK: "task",
340
+ PLAN: "plan",
341
+ STATUS: "status",
342
+ STOP: "stop",
343
+ CANCEL: "cancel"
344
+ };
345
+
331
346
  // src/shared/message/constants/message-roles.ts
332
347
  var MESSAGE_ROLES = {
333
348
  /** AI assistant message */
@@ -15822,7 +15837,7 @@ var TaskLauncher = class {
15822
15837
  log2("[task-launcher.ts] concurrency acquired for", concurrencyKey);
15823
15838
  try {
15824
15839
  const createResult = await this.client.session.create({
15825
- body: { parentID: input.parentSessionID, title: `Parallel: ${input.description}` },
15840
+ body: { parentID: input.parentSessionID, title: `${PARALLEL_TASK.SESSION_TITLE_PREFIX}: ${input.description}` },
15826
15841
  query: { directory: this.directory }
15827
15842
  });
15828
15843
  if (createResult.error) {
@@ -18112,7 +18127,7 @@ function cleanupSession(sessionID) {
18112
18127
  }
18113
18128
 
18114
18129
  // src/core/loop/mission-seal.ts
18115
- import { existsSync as existsSync4, readFileSync, writeFileSync, unlinkSync } from "node:fs";
18130
+ import { existsSync as existsSync4, readFileSync, writeFileSync, unlinkSync, mkdirSync } from "node:fs";
18116
18131
  import { join as join5 } from "node:path";
18117
18132
  var MISSION_SEAL_TAG = MISSION_SEAL.TAG;
18118
18133
  var SEAL_CONFIRMATION = MISSION_SEAL.CONFIRMATION;
@@ -18142,7 +18157,11 @@ function readLoopState(directory) {
18142
18157
  }
18143
18158
  function writeLoopState(directory, state2) {
18144
18159
  const filePath = getStateFilePath(directory);
18160
+ const dirPath = join5(directory, PATHS.OPENCODE);
18145
18161
  try {
18162
+ if (!existsSync4(dirPath)) {
18163
+ mkdirSync(dirPath, { recursive: true });
18164
+ }
18146
18165
  writeFileSync(filePath, JSON.stringify(state2, null, 2), "utf-8");
18147
18166
  return true;
18148
18167
  } catch (error45) {
@@ -18691,8 +18710,8 @@ function createChatMessageHandler(ctx) {
18691
18710
  startSession(sessionID);
18692
18711
  presets.taskStarted(sessionID, AGENT_NAMES.COMMANDER);
18693
18712
  }
18694
- if (!parsed || parsed.command !== "task") {
18695
- const taskTemplate = COMMANDS["task"].template;
18713
+ if (!parsed || parsed.command !== COMMAND_NAMES.TASK) {
18714
+ const taskTemplate = COMMANDS[COMMAND_NAMES.TASK].template;
18696
18715
  const userMessage = parsed?.args || originalText;
18697
18716
  parts[textPartIndex].text = taskTemplate.replace(
18698
18717
  /\$ARGUMENTS/g,
@@ -18710,7 +18729,7 @@ function createChatMessageHandler(ctx) {
18710
18729
  parsed.args || PROMPTS.CONTINUE
18711
18730
  );
18712
18731
  }
18713
- if (command && parsed.command === "task") {
18732
+ if (command && parsed.command === COMMAND_NAMES.TASK) {
18714
18733
  if (!sessions.has(sessionID)) {
18715
18734
  const now = Date.now();
18716
18735
  sessions.set(sessionID, {
@@ -3,6 +3,6 @@
3
3
  */
4
4
  export { PART_TYPES } from "./part-types.js";
5
5
  export { PROMPTS } from "./prompts.js";
6
- export { SLASH_COMMANDS } from "./slash-commands.js";
6
+ export { SLASH_COMMANDS, COMMAND_NAMES, type CommandName } from "./slash-commands.js";
7
7
  export { PLUGIN_HOOKS, type PluginHookName } from "./plugin-hooks.js";
8
8
  export { MESSAGE_ROLES, SESSION_STATUS, type MessageRole, type SessionStatus } from "./message-roles.js";
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Slash Commands
2
+ * Slash Commands (with slash prefix)
3
3
  */
4
4
  export declare const SLASH_COMMANDS: {
5
5
  readonly TASK: "/task";
@@ -8,3 +8,14 @@ export declare const SLASH_COMMANDS: {
8
8
  readonly STOP: "/stop";
9
9
  readonly CANCEL: "/cancel";
10
10
  };
11
+ /**
12
+ * Command Names (without slash prefix, for comparison after parsing)
13
+ */
14
+ export declare const COMMAND_NAMES: {
15
+ readonly TASK: "task";
16
+ readonly PLAN: "plan";
17
+ readonly STATUS: "status";
18
+ readonly STOP: "stop";
19
+ readonly CANCEL: "cancel";
20
+ };
21
+ export type CommandName = typeof COMMAND_NAMES[keyof typeof COMMAND_NAMES];
@@ -13,4 +13,7 @@ export declare const PARALLEL_TASK: {
13
13
  readonly MIN_STABILITY_MS: number;
14
14
  readonly STABLE_POLLS_REQUIRED: 3;
15
15
  readonly MAX_POLL_COUNT: 600;
16
+ readonly SESSION_TITLE_PREFIX: "Parallel";
17
+ readonly LABEL: "parallel";
18
+ readonly GROUP_PREFIX: "parallel:";
16
19
  };
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.9.10",
5
+ "version": "0.9.12",
6
6
  "author": "agnusdei1207",
7
7
  "license": "MIT",
8
8
  "repository": {