opencode-orchestrator 0.9.6 → 0.9.9

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
@@ -4,7 +4,7 @@
4
4
 
5
5
  # OpenCode Orchestrator
6
6
 
7
- > Autonomous multi-agent plugin for [OpenCode](https://opencode.ai)
7
+ > **🚀 Multi-Agent Orchestration Plugin for [OpenCode](https://opencode.ai)**
8
8
 
9
9
  [![MIT License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
10
10
  [![npm](https://img.shields.io/npm/v/opencode-orchestrator.svg)](https://www.npmjs.com/package/opencode-orchestrator)
@@ -12,112 +12,120 @@
12
12
 
13
13
  ---
14
14
 
15
+ ## 🔥 Why This Plugin?
16
+
17
+ **Budget models have limits. Orchestration breaks them.**
18
+
19
+ ---
20
+
15
21
  ## ⚡ Quick Start
16
22
 
17
23
  ```bash
18
24
  npm install -g opencode-orchestrator
19
25
  ```
20
26
 
21
- Restart OpenCode after installation. Then:
27
+ Then in OpenCode:
22
28
 
23
29
  ```bash
24
30
  /task "Build a REST API with authentication"
25
31
  ```
26
32
 
27
- That's it! The Commander takes over and works until the mission is complete.
33
+ **Done.** You just deployed an army of AI agents. They plan, build, test, fix — and don't stop until it's sealed.
28
34
 
29
35
  ---
30
36
 
31
- ## 💡 Why I Built This
32
-
33
- Budget models have limits. Orchestration breaks them.
34
-
35
- ---
37
+ ## 🎯 What Makes This Different?
36
38
 
37
- ## 🎯 What is This?
39
+ ### 🚀 Core Capabilities
38
40
 
39
- A multi-agent system that **autonomously executes complex tasks** from start to finish. Just describe your mission — the Commander handles everything else.
41
+ | | Feature | What It Means |
42
+ |:---:|:---|:---|
43
+ | ⚡ | **Multi-Session Parallel** | 50 isolated sessions running simultaneously. True multi-threading. |
44
+ | 🔥 | **Parallel Execution** | Workers build different files at once. 10x faster. |
45
+ | � | **Non-Blocking Async** | Fire-and-forget. Commander never waits. Results collected automatically. |
46
+ | 🧩 | **Smart Distribution** | One file = one worker. No conflicts. No stepping on each other. |
47
+ | 🔗 | **Real-Time Sync** | Shared `.opencode/` state. All agents see updates instantly. |
48
+ | 🛡️ | **Auto Verify & Test** | E2E tests, import checks, integration validation. Bugs get caught. |
49
+ | 🩹 | **Self-Healing** | Auto-recovery from crashes, rate limits, context overflow. 3 retries. |
50
+ | � | **Live Monitoring** | Track sessions, progress, queues. Toast notifications in real-time. |
40
51
 
41
52
  ---
42
53
 
43
- ## ✨ v0.9.4 Highlights
44
54
 
45
- > 🚀 **"Relentless execution until absolute success."**
55
+ ## 🏛️ How It Works
46
56
 
47
- | Category | Feature |
48
- |----------|----------|
49
- | 🛡️ **Resilience** | Never stops. Auto-pivots Plan↔Search on any error |
50
- | **Parallelism** | 50 isolated sessions run simultaneously |
51
- | 🔧 **TDD Workers** | Each agent works in complete isolation (1 file = 1 worker) |
52
- | 🔄 **Sync Integration** | Shared `.opencode/` state synchronizes all agents |
53
- | ✅ **Stability Checks** | TODO + Issue verification before mission seal |
54
- | 🧠 **Smart Fixers** | Anti-overengineering: simple errors get simple fixes |
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)
90
+ ```
55
91
 
56
92
  ---
57
93
 
58
- ## 🚀 How It Works
94
+ ## 🤖 The 4 Agents
59
95
 
60
- ```
61
- /task "Build REST API"
62
-
63
-
64
- ┌────────────────────────────────┐
65
- │ 🎯 COMMANDER │
66
- │ Read state → Delegate → Loop │
67
- └────────────────────────────────┘
68
-
69
- ┌───────────────────────┼───────────────────────┐
70
- ▼ ▼ ▼
71
- ┌─────────┐ ┌─────────┐ ┌─────────┐
72
- │ PLANNER │ │ WORKER │ │ WORKER │ ⚡ PARALLEL
73
- │ Plan it │ │ Build A │ │ Build B │ EXECUTION
74
- └─────────┘ └─────────┘ └─────────┘
75
- │ │ │
76
- └───────────────────────┼───────────────────────┘
77
-
78
- ┌────────────────────────────────┐
79
- │ ✅ REVIEWER │
80
- │ Verify → Sync │
81
- └────────────────────────────────┘
82
-
83
- ┌──────────┴──────────┐
84
- │ TODO incomplete? │
85
- │ Sync issues? │
86
- └──────────┬──────────┘
87
- Yes ↓ ↓ No
88
- ♻️ LOOP 🎖️ SEALED
89
- ```
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 |
90
102
 
91
- ### 🔑 Core Principles
103
+ ---
92
104
 
93
- ```
94
- ┌─────────────────────────────────────────────────────────────┐
95
- │ 🔒 ISOLATION │ 🔄 SYNC │ ✅ STABILITY │
96
- ├─────────────────────────────────────────────────────────────┤
97
- │ Each worker │ Shared state │ TODO 100% complete │
98
- │ owns 1 file │ via .opencode │ + Zero sync issues │
99
- │ No conflicts │ Real-time │ = Mission SEALED │
100
- └─────────────────────────────────────────────────────────────┘
101
- ```
105
+ ## 📊 System Specs
102
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) |
103
116
 
104
117
  ---
105
118
 
106
- ## 🎮 Usage
107
-
108
- | Mode | Trigger | What Happens |
109
- |------|---------|--------------|
110
- | **Commander Mode** 🎯 | `/task "mission"` | Full autonomous execution |
111
- | **Chat Mode** 💬 | Just type normally | Simple Q&A, no automation |
119
+ ## 🎮 What Happens When You Run `/task`
112
120
 
113
- **Example Commands:**
114
- ```bash
115
- /task "Fix the login bug in docker-compose"
116
- /task "Add dark mode to the entire app"
117
- /task "Refactor the API to TypeScript"
118
- ```
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
119
127
 
120
- **Stop anytime:** `/stop` or `/cancel`
128
+ > **Tip:** Stop anytime with `/stop`
121
129
 
122
130
  <div align="center">
123
131
  <p><strong>TUI</strong></p>
@@ -130,37 +138,29 @@ A multi-agent system that **autonomously executes complex tasks** from start to
130
138
  <p><strong>Window</strong></p>
131
139
  <img src="assets/window_image.png" alt="Commander Window" width="600" />
132
140
  </div>
133
- ---
134
-
135
- ## 🤖 The 4 Agents
136
-
137
- | Agent | Role | Key Actions |
138
- |-------|------|-------------|
139
- | **Commander** 🎯 | Orchestrator | Delegates tasks, monitors progress, seals mission |
140
- | **Planner** 📋 | Research + Plan | Web search, doc caching, TODO creation |
141
- | **Worker** 🔨 | Implementation | Code writing, file ops, background commands |
142
- | **Reviewer** ✅ | Quality Control | Verification, TODO updates, context management |
143
141
 
144
142
  ---
145
143
 
146
- ## 📊 Resource Limits
144
+ ## 🔧 Self-Healing Features
147
145
 
148
- | Resource | Limit |
149
- |----------|-------|
150
- | Parallel Sessions | 50 |
151
- | Tasks in Memory | 1,000 (auto GC) |
152
- | Session TTL | 60 min |
153
- | Recovery Attempts | 3 per session |
154
- | Max Iterations | 20 per mission |
146
+ ```
147
+ ┌────────────────────────────────────────────────────────────┐
148
+ ERROR TYPE │ AUTO-RECOVERY ACTION │
149
+ ├────────────────────────────────────────────────────────────┤
150
+ Tool crash │ Inject recovery prompt │
151
+ Rate limit │ Exponential backoff + retry │
152
+ Context overflow │ Smart compaction │
153
+ │ Thinking block error │ Auto-restructure │
154
+ │ Session timeout │ Resume from checkpoint │
155
+ │ Build failure │ Loop back, fix, retry │
156
+ └────────────────────────────────────────────────────────────┘
157
+ ```
155
158
 
156
159
  ---
157
160
 
158
161
  ## 📚 Documentation
159
162
 
160
- For detailed architecture, directory structure, and internals:
161
-
162
- - **[System Architecture](docs/SYSTEM_ARCHITECTURE.md)** — Complete technical documentation
163
- - [Release Notes](docs/releases/) — Version history
163
+ - **[System Architecture](docs/SYSTEM_ARCHITECTURE.md)** Full technical deep-dive
164
164
 
165
165
  ---
166
166
 
@@ -179,5 +179,6 @@ MIT License. [LICENSE](LICENSE)
179
179
  ---
180
180
 
181
181
  <div align="center">
182
- <b>🚀 v0.9.4 — "Relentless execution until absolute success."</b>
182
+ <h3>🚀 v0.9.7 — "Relentless execution until absolute success."</h3>
183
+ <p><i>Multi-agent. Parallel. Non-blocking. Self-healing. Enterprise-grade.</i></p>
183
184
  </div>
package/dist/index.js CHANGED
@@ -232,6 +232,9 @@ var SESSION_EVENTS = {
232
232
  CREATED: "session.created",
233
233
  ERROR: "session.error"
234
234
  };
235
+ var MESSAGE_EVENTS = {
236
+ UPDATED: "message.updated"
237
+ };
235
238
 
236
239
  // src/shared/session/constants/event-types.ts
237
240
  var TASK_EVENTS = {
@@ -311,7 +314,11 @@ var PART_TYPES = {
311
314
  TEXT: "text",
312
315
  REASONING: "reasoning",
313
316
  TOOL_CALL: "tool_call",
314
- TOOL_RESULT: "tool_result"
317
+ TOOL_RESULT: "tool_result",
318
+ /** Anthropic-style tool reference */
319
+ TOOL: "tool",
320
+ /** Anthropic-style tool invocation */
321
+ TOOL_USE: "tool_use"
315
322
  };
316
323
 
317
324
  // src/shared/message/constants/prompts.ts
@@ -321,6 +328,20 @@ var PROMPTS = {
321
328
  CONTINUE_DEFAULT: "continue from where we left off"
322
329
  };
323
330
 
331
+ // src/shared/message/constants/message-roles.ts
332
+ var MESSAGE_ROLES = {
333
+ /** AI assistant message */
334
+ ASSISTANT: "assistant",
335
+ /** User message */
336
+ USER: "user",
337
+ /** System message */
338
+ SYSTEM: "system"
339
+ };
340
+ var SESSION_STATUS = {
341
+ IDLE: "idle",
342
+ BUSY: "busy"
343
+ };
344
+
324
345
  // src/shared/errors/patterns.ts
325
346
  var ERROR_PATTERNS = {
326
347
  TOOL_RESULT_MISSING: /tool_result_missing|tool result.*missing/i,
@@ -15957,7 +15978,7 @@ var TaskPoller = class {
15957
15978
  for (const task of running) {
15958
15979
  try {
15959
15980
  const sessionStatus = allStatuses[task.sessionID];
15960
- if (sessionStatus?.type === "idle") {
15981
+ if (sessionStatus?.type === SESSION_STATUS.IDLE) {
15961
15982
  const elapsed2 = Date.now() - task.startedAt.getTime();
15962
15983
  if (elapsed2 < CONFIG.MIN_STABILITY_MS) continue;
15963
15984
  if (!await this.validateSessionHasOutput(task.sessionID)) continue;
@@ -15984,7 +16005,7 @@ var TaskPoller = class {
15984
16005
  try {
15985
16006
  const response = await this.client.session.messages({ path: { id: sessionID } });
15986
16007
  const messages = response.data ?? [];
15987
- return messages.some((m) => m.info?.role === "assistant" && m.parts?.some((p) => p.type === PART_TYPES.TEXT && p.text?.trim() || p.type === "tool"));
16008
+ return messages.some((m) => m.info?.role === MESSAGE_ROLES.ASSISTANT && m.parts?.some((p) => p.type === PART_TYPES.TEXT && p.text?.trim() || p.type === PART_TYPES.TOOL));
15988
16009
  } catch {
15989
16010
  return true;
15990
16011
  }
@@ -16010,13 +16031,13 @@ var TaskPoller = class {
16010
16031
  const result = await this.client.session.messages({ path: { id: task.sessionID } });
16011
16032
  if (result.error) return;
16012
16033
  const messages = result.data ?? [];
16013
- const assistantMsgs = messages.filter((m) => m.info?.role === "assistant");
16034
+ const assistantMsgs = messages.filter((m) => m.info?.role === MESSAGE_ROLES.ASSISTANT);
16014
16035
  let toolCalls = 0;
16015
16036
  let lastTool;
16016
16037
  let lastMessage;
16017
16038
  for (const msg of assistantMsgs) {
16018
16039
  for (const part of msg.parts ?? []) {
16019
- if (part.type === "tool_use" || part.tool) {
16040
+ if (part.type === PART_TYPES.TOOL_USE || part.tool) {
16020
16041
  toolCalls++;
16021
16042
  lastTool = part.tool || part.name;
16022
16043
  }
@@ -16332,7 +16353,7 @@ var ParallelAgentManager = class _ParallelAgentManager {
16332
16353
  const result = await this.client.session.messages({ path: { id: task.sessionID } });
16333
16354
  if (result.error) return `Error: ${result.error}`;
16334
16355
  const messages = result.data ?? [];
16335
- const lastMsg = messages.filter((m) => m.info?.role === "assistant").reverse()[0];
16356
+ const lastMsg = messages.filter((m) => m.info?.role === MESSAGE_ROLES.ASSISTANT).reverse()[0];
16336
16357
  if (!lastMsg) return "(No response)";
16337
16358
  const text = lastMsg.parts?.filter((p) => p.type === PART_TYPES.TEXT || p.type === PART_TYPES.REASONING).map((p) => p.text ?? "").filter(Boolean).join("\n") ?? "";
16338
16359
  task.result = text;
@@ -16370,7 +16391,7 @@ var ParallelAgentManager = class _ParallelAgentManager {
16370
16391
  handleTaskError(taskId, error45) {
16371
16392
  const task = this.store.get(taskId);
16372
16393
  if (!task) return;
16373
- task.status = "error";
16394
+ task.status = TASK_STATUS.ERROR;
16374
16395
  task.error = error45 instanceof Error ? error45.message : String(error45);
16375
16396
  task.completedAt = /* @__PURE__ */ new Date();
16376
16397
  if (task.concurrencyKey) this.concurrency.release(task.concurrencyKey);
@@ -16395,20 +16416,20 @@ async function validateSessionHasOutput(session, sessionID) {
16395
16416
  const response = await session.messages({ path: { id: sessionID } });
16396
16417
  const messages = response.data ?? [];
16397
16418
  const hasAssistantMessage = messages.some(
16398
- (m) => m.info?.role === "assistant"
16419
+ (m) => m.info?.role === MESSAGE_ROLES.ASSISTANT
16399
16420
  );
16400
16421
  if (!hasAssistantMessage) {
16401
16422
  return false;
16402
16423
  }
16403
16424
  const hasContent = messages.some((m) => {
16404
- if (m.info?.role !== "assistant") return false;
16425
+ if (m.info?.role !== MESSAGE_ROLES.ASSISTANT) return false;
16405
16426
  const parts = m.parts ?? [];
16406
16427
  return parts.some(
16407
16428
  (p) => (
16408
16429
  // Text content
16409
16430
  p.type === PART_TYPES.TEXT && p.text && p.text.trim().length > 0 || // Reasoning content
16410
16431
  p.type === PART_TYPES.REASONING && p.text && p.text.trim().length > 0 || // Tool calls (indicates work was done)
16411
- p.type === "tool" || p.type === "tool_use" || p.tool
16432
+ p.type === PART_TYPES.TOOL || p.type === PART_TYPES.TOOL_USE || p.tool
16412
16433
  )
16413
16434
  );
16414
16435
  });
@@ -16448,7 +16469,7 @@ async function pollWithSafetyLimits(session, sessionID, startTime) {
16448
16469
  stablePolls = 0;
16449
16470
  continue;
16450
16471
  }
16451
- if (sessionStatus.type !== "idle") {
16472
+ if (sessionStatus.type !== SESSION_STATUS.IDLE) {
16452
16473
  stablePolls = 0;
16453
16474
  continue;
16454
16475
  }
@@ -16491,7 +16512,7 @@ async function extractSessionResult(session, sessionID) {
16491
16512
  try {
16492
16513
  const msgs = await session.messages({ path: { id: sessionID } });
16493
16514
  const messages = msgs.data ?? [];
16494
- const lastMsg = messages.filter((m) => m.info?.role === "assistant").reverse()[0];
16515
+ const lastMsg = messages.filter((m) => m.info?.role === MESSAGE_ROLES.ASSISTANT).reverse()[0];
16495
16516
  const text = lastMsg?.parts?.filter((p) => p.type === PART_TYPES.TEXT || p.type === PART_TYPES.REASONING).map((p) => p.text ?? "").join("\n") || "";
16496
16517
  return text;
16497
16518
  } catch (error45) {
@@ -18159,7 +18180,7 @@ async function detectSealInSession(client, sessionID) {
18159
18180
  try {
18160
18181
  const response = await client.session.messages({ path: { id: sessionID } });
18161
18182
  const messages = response.data ?? [];
18162
- const assistantMessages = messages.filter((m) => m.info?.role === "assistant");
18183
+ const assistantMessages = messages.filter((m) => m.info?.role === MESSAGE_ROLES.ASSISTANT);
18163
18184
  const recentMessages = assistantMessages.slice(-3);
18164
18185
  for (const msg of recentMessages) {
18165
18186
  if (!msg.parts) continue;
@@ -18450,12 +18471,12 @@ function createEventHandler(ctx) {
18450
18471
  manager.handleEvent(event);
18451
18472
  } catch {
18452
18473
  }
18453
- if (event.type === "session.created") {
18474
+ if (event.type === SESSION_EVENTS.CREATED) {
18454
18475
  const sessionID = event.properties?.id || "";
18455
18476
  log2("[event-handler] session.created", { sessionID });
18456
18477
  presets.missionStarted(`Session ${sessionID.slice(0, 12)}...`);
18457
18478
  }
18458
- if (event.type === "session.deleted") {
18479
+ if (event.type === SESSION_EVENTS.DELETED) {
18459
18480
  const sessionID = event.properties?.id || event.properties?.info?.id || "";
18460
18481
  const session = sessions.get(sessionID);
18461
18482
  if (session) {
@@ -18471,7 +18492,7 @@ function createEventHandler(ctx) {
18471
18492
  presets.sessionCompleted(sessionID, duration3);
18472
18493
  }
18473
18494
  }
18474
- if (event.type === "session.error") {
18495
+ if (event.type === SESSION_EVENTS.ERROR) {
18475
18496
  const sessionID = event.properties?.sessionId || event.properties?.sessionID || "";
18476
18497
  const error45 = event.properties?.error;
18477
18498
  log2("[event-handler] session.error", { sessionID, error: error45 });
@@ -18493,19 +18514,19 @@ function createEventHandler(ctx) {
18493
18514
  }
18494
18515
  presets.taskFailed("session", String(error45).slice(0, 50));
18495
18516
  }
18496
- if (event.type === "message.updated") {
18517
+ if (event.type === MESSAGE_EVENTS.UPDATED) {
18497
18518
  const messageInfo = event.properties?.info;
18498
18519
  const sessionID = messageInfo?.sessionID;
18499
18520
  const role = messageInfo?.role;
18500
- if (sessionID && role === "assistant") {
18521
+ if (sessionID && role === MESSAGE_ROLES.ASSISTANT) {
18501
18522
  markRecoveryComplete(sessionID);
18502
18523
  }
18503
- if (sessionID && role === "user") {
18524
+ if (sessionID && role === MESSAGE_ROLES.USER) {
18504
18525
  handleUserMessage(sessionID);
18505
18526
  handleUserMessage2(sessionID);
18506
18527
  }
18507
18528
  }
18508
- if (event.type === "session.idle") {
18529
+ if (event.type === SESSION_EVENTS.IDLE) {
18509
18530
  const sessionID = event.properties?.sessionID || "";
18510
18531
  if (sessionID) {
18511
18532
  const isMainSession = sessions.has(sessionID);
@@ -4,3 +4,5 @@
4
4
  export { PART_TYPES } from "./part-types.js";
5
5
  export { PROMPTS } from "./prompts.js";
6
6
  export { SLASH_COMMANDS } from "./slash-commands.js";
7
+ export { PLUGIN_HOOKS, type PluginHookName } from "./plugin-hooks.js";
8
+ export { MESSAGE_ROLES, SESSION_STATUS, type MessageRole, type SessionStatus } from "./message-roles.js";
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Message Role Constants
3
+ *
4
+ * OpenCode message roles
5
+ * Use these instead of hardcoded strings
6
+ */
7
+ export declare const MESSAGE_ROLES: {
8
+ /** AI assistant message */
9
+ readonly ASSISTANT: "assistant";
10
+ /** User message */
11
+ readonly USER: "user";
12
+ /** System message */
13
+ readonly SYSTEM: "system";
14
+ };
15
+ export type MessageRole = typeof MESSAGE_ROLES[keyof typeof MESSAGE_ROLES];
16
+ /**
17
+ * Session Status Types
18
+ */
19
+ export declare const SESSION_STATUS: {
20
+ readonly IDLE: "idle";
21
+ readonly BUSY: "busy";
22
+ };
23
+ export type SessionStatus = typeof SESSION_STATUS[keyof typeof SESSION_STATUS];
@@ -6,4 +6,8 @@ export declare const PART_TYPES: {
6
6
  readonly REASONING: "reasoning";
7
7
  readonly TOOL_CALL: "tool_call";
8
8
  readonly TOOL_RESULT: "tool_result";
9
+ /** Anthropic-style tool reference */
10
+ readonly TOOL: "tool";
11
+ /** Anthropic-style tool invocation */
12
+ readonly TOOL_USE: "tool_use";
9
13
  };
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Plugin Hook Constants
3
+ *
4
+ * OpenCode plugin hook names (from @opencode-ai/plugin)
5
+ * Use these instead of hardcoded strings
6
+ */
7
+ export declare const PLUGIN_HOOKS: {
8
+ /** Intercepts user messages before sending to LLM */
9
+ readonly CHAT_MESSAGE: "chat.message";
10
+ /** Runs after LLM finishes responding */
11
+ readonly ASSISTANT_DONE: "assistant.done";
12
+ /** Runs after any tool call completes */
13
+ readonly TOOL_EXECUTE_AFTER: "tool.execute.after";
14
+ };
15
+ export type PluginHookName = typeof PLUGIN_HOOKS[keyof typeof PLUGIN_HOOKS];
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Session constants
3
3
  */
4
- export { SESSION_EVENTS } from "./session-events.js";
5
- export type { SessionEventType } from "./session-events.js";
4
+ export { SESSION_EVENTS, MESSAGE_EVENTS } from "./session-events.js";
5
+ export type { SessionEventType, MessageEventType } from "./session-events.js";
6
6
  export { TASK_EVENTS, TODO_EVENTS, SESSION_EVENTS as SESSION_STATE_EVENTS, DOCUMENT_EVENTS, MISSION_EVENTS, SPECIAL_EVENTS, EVENT_TYPES, } from "./event-types.js";
7
7
  export type { EventTypeValue } from "./event-types.js";
@@ -8,3 +8,10 @@ export declare const SESSION_EVENTS: {
8
8
  readonly ERROR: "session.error";
9
9
  };
10
10
  export type SessionEventType = (typeof SESSION_EVENTS)[keyof typeof SESSION_EVENTS];
11
+ /**
12
+ * Message Event Types
13
+ */
14
+ export declare const MESSAGE_EVENTS: {
15
+ readonly UPDATED: "message.updated";
16
+ };
17
+ export type MessageEventType = (typeof MESSAGE_EVENTS)[keyof typeof MESSAGE_EVENTS];
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.6",
5
+ "version": "0.9.9",
6
6
  "author": "agnusdei1207",
7
7
  "license": "MIT",
8
8
  "repository": {