opencode-orchestrator 1.0.5 → 1.0.10
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 +94 -43
- package/dist/agents/prompts/common/hyper-parallel.d.ts +4 -0
- package/dist/agents/prompts/common/index.d.ts +2 -0
- package/dist/agents/prompts/common/modularity.d.ts +6 -0
- package/dist/core/agents/config.d.ts +1 -1
- package/dist/core/agents/interfaces/launch-input.interface.d.ts +2 -0
- package/dist/core/agents/interfaces/parallel-task.interface.d.ts +2 -0
- package/dist/core/agents/manager/event-handler.d.ts +2 -1
- package/dist/core/agents/manager/task-launcher.d.ts +14 -1
- package/dist/core/agents/manager/task-poller.d.ts +2 -1
- package/dist/core/agents/manager.d.ts +2 -1
- package/dist/index.js +332 -105
- package/dist/shared/task/constants/parallel-task.d.ts +11 -6
- package/dist/tools/parallel/delegate-task.d.ts +8 -0
- package/dist/utils/compatibility/claude.d.ts +9 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,13 +2,21 @@
|
|
|
2
2
|
<img src="assets/logo.png" alt="logo" width="280" />
|
|
3
3
|
<h1>OpenCode Orchestrator</h1>
|
|
4
4
|
|
|
5
|
+
<p><b>Next-Gen Autonomous Mastery: Powered by HPFA™ & MSVP™</b></p>
|
|
6
|
+
<p><i>Redefining Scalability with Fractal Swarm Intelligence and Multi-Stage Integrity</i></p>
|
|
7
|
+
|
|
5
8
|
[](LICENSE)
|
|
6
9
|
[](https://www.npmjs.com/package/opencode-orchestrator)
|
|
7
10
|
[]()
|
|
8
11
|
</div>
|
|
9
12
|
|
|
10
|
-
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
### 🌌 **The End of Sequential Limits. The Era of Fractal Mastery.**
|
|
16
|
+
|
|
17
|
+
Where traditional agents hit a sequential wall, we deploy a fractal swarm. OpenCode Orchestrator is the world's most advanced autonomous engineering platform—a **Titan-Class Execution Engine** designed to conquer missions that break conventional AI.
|
|
11
18
|
|
|
19
|
+
By fusing **Fractal Swarm Intelligence (HPFA™)** with **Continuous Multi-Stage Verification Pipeline (MSVP™)**, it delivers a level of scale, velocity, and architectural absolute previously considered impossible. Welcome to the final form of autonomous development. No bottlenecks. No limits. Only pure execution.
|
|
12
20
|
|
|
13
21
|
## ⚡ Quick Start
|
|
14
22
|
|
|
@@ -16,20 +24,21 @@
|
|
|
16
24
|
npm install -g opencode-orchestrator
|
|
17
25
|
```
|
|
18
26
|
|
|
19
|
-
Then in OpenCode:
|
|
27
|
+
Then in OpenCode, launch your mission:
|
|
20
28
|
```bash
|
|
21
|
-
/extreme-mission "
|
|
29
|
+
/extreme-mission "Architect and Build a Diablo-like Web Engine"
|
|
22
30
|
```
|
|
23
31
|
|
|
24
|
-
##
|
|
32
|
+
## 💎 The Four Pillars of Excellence
|
|
25
33
|
|
|
26
|
-
|
|
34
|
+
We’ve combined industrial-grade reliability with cutting-edge parallel intelligence to redefine what’s possible in AI coding.
|
|
27
35
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
36
|
+
* **⚡ Velocity**: Parallelize up to 50 concurrent sessions. What takes hours for others is finished in minutes through **Cognitive Elasticity**.
|
|
37
|
+
* **🧬 Scale**: **Fractal Delegation** allows workers to recursively spawn their own sub-agents. No task is too big for a system that can replicate its own intelligence.
|
|
38
|
+
* **🛡️ Safety**: Our **MSVP (Multi-Stage Verification Pipeline)** reviews every line of code in parallel "Shadow Sessions" before it ever touches your build.
|
|
39
|
+
* **♾️ Trust**: **Iron-Clad Reliability** via Write-Ahead Logging (WAL). Even after a crash, the system replays its history to resume exactly where it was.
|
|
32
40
|
|
|
41
|
+
---
|
|
33
42
|
|
|
34
43
|
## ⭐ Core Philosophy
|
|
35
44
|
|
|
@@ -63,47 +72,90 @@ Built for "Infinite Missions," the OpenCode Orchestrator is engineered to handle
|
|
|
63
72
|
| 🤝 **Specialized Roles** | Each agent has a clear, focused responsibility |
|
|
64
73
|
|
|
65
74
|
|
|
66
|
-
## 🏛️
|
|
75
|
+
## 🏛️ Hyper-Parallel Architecture: HPFA & MSVP
|
|
76
|
+
|
|
77
|
+
The orchestrator eliminates the linear bottleneck of AI development through two breakthrough technologies:
|
|
78
|
+
|
|
79
|
+
### 🧬 **HPFA (Hyper-Parallel Fractal Architecture)**
|
|
80
|
+
Imagine an agent that doesn't just work, but **thinks like a Hive Mind**.
|
|
81
|
+
* **Fractal Delegation**: Workers are no longer just "doers." They are mini-planners that can recursively spawn their own sub-agents to handle complexity at every level.
|
|
82
|
+
* **Speculative Racing**: Ambiguous tasks are solved using multiple strategies in parallel. The fastest, most accurate path wins, while others are pruned—minimizing latency and maximizing quality.
|
|
83
|
+
|
|
84
|
+
### 🛡️ **MSVP (Multi-Stage Verification Pipeline)**
|
|
85
|
+
Speed is nothing without accuracy. MSVP ensures your code is production-ready at every second.
|
|
86
|
+
* **Shadow Parallel Review**: As soon as a file is written, a parallel reviewer session is already validating it before the main task even finishes.
|
|
87
|
+
* **Barrier-Sync Integration**: A 4-stage verification gate that prevents "architectural drift" by forcing a global synchronization barrier before final sealing.
|
|
67
88
|
|
|
68
89
|
```
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
│
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
90
|
+
/extreme-mission "Build Complex System"
|
|
91
|
+
│
|
|
92
|
+
╔═══════════════════════════════════════╗
|
|
93
|
+
║ 🎯 COMMANDER — Orchestrator ║
|
|
94
|
+
║ (Main Session - Single) ║
|
|
95
|
+
╚═══════════════════╤═══════════════════╝
|
|
96
|
+
│
|
|
97
|
+
┌───────────────────▼───────────────────┐
|
|
98
|
+
│ 📋 PLANNER — Create Plan │
|
|
99
|
+
│ → Outputs: Architectural Grid │
|
|
100
|
+
└───────────────────┬───────────────────┘
|
|
101
|
+
│
|
|
102
|
+
══════════════════════════╧══════════════════════════
|
|
103
|
+
║ 🔥 HPFA PARALLEL GRID (MSVP) ║
|
|
104
|
+
══════════════════════════════════════════════════════
|
|
105
|
+
│ │ │ │
|
|
106
|
+
▼ ▼ ▼ ▼
|
|
107
|
+
┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
|
|
108
|
+
│🔨 WORKER │ │🔨 WORKER │ │🔨 WORKER │ │🔨 WORKER │ <-- Fractal Spawning
|
|
109
|
+
│ Module A │ │ Module B │ │ Module C │ │ Module D │
|
|
110
|
+
└────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬─────┘
|
|
111
|
+
│ ⚡ Instant │ ⚡ Instant │ ⚡ Instant │ ⚡ Instant
|
|
112
|
+
▼ Review ▼ Review ▼ Review ▼ Review
|
|
113
|
+
┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
|
|
114
|
+
│✅ REVIEWR│ │✅ REVIEWR│ │✅ REVIEWR│ │✅ REVIEWR│ <-- Stage 1: Unit
|
|
115
|
+
│ (Unit-A) │ │ (Unit-B) │ │ (Unit-C) │ │ (Unit-D) │ Verification
|
|
116
|
+
└────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬─────┘
|
|
117
|
+
│ │ │ │
|
|
118
|
+
═▼═══════════════▼═══════════════▼═══════════════▼════
|
|
119
|
+
║ ⏳ SYNC BARRIER ║
|
|
120
|
+
══════════════════════════════════════════════════════
|
|
121
|
+
│
|
|
122
|
+
┌───────────────────▼───────────────────┐
|
|
123
|
+
│ ✅ MASTER REVIEWER — Final Pass │
|
|
124
|
+
│ (Cross-module Integration) │
|
|
125
|
+
│ → Stage 2: E2E & System Integrity │
|
|
126
|
+
└───────────────────┬───────────────────┘
|
|
127
|
+
│
|
|
128
|
+
┌─────────┴─────────┐
|
|
129
|
+
│ Seal Conditions │
|
|
130
|
+
│ Verified? │
|
|
131
|
+
└─────────┬─────────┘
|
|
132
|
+
No ↙ ↘ Yes
|
|
133
|
+
♻️ LOOP 🎖️ MISSION
|
|
134
|
+
(Adaptive) SEALED
|
|
94
135
|
```
|
|
95
136
|
|
|
137
|
+
### Execution Model (MSVP)
|
|
138
|
+
|
|
139
|
+
| Phase | Agent | Parallelism | Verification Level |
|
|
140
|
+
|:------|:------|:------------|:-------------------|
|
|
141
|
+
| 1️⃣ Plan | Planner | **Single** | Static Analysis |
|
|
142
|
+
| 2️⃣ Implement | Workers | **HPFA Parallel** | Direct Coding |
|
|
143
|
+
| 3️⃣ Unit Pass | Reviewers | **Shadow Parallel** | **1차 리뷰**: Unit Tests (Async) |
|
|
144
|
+
| 4️⃣ Final Sync | Barrier | **Blocking** | All Units Verified |
|
|
145
|
+
| 5️⃣ Integration | Master Reviewer | **Single** | **2차 리뷰**: Full E2E & Sync |
|
|
146
|
+
|
|
96
147
|
## Features
|
|
97
148
|
|
|
98
149
|
| Feature | What It Does |
|
|
99
150
|
|:---------|:-------------|
|
|
100
|
-
| 🚀 **
|
|
101
|
-
|
|
|
151
|
+
| 🚀 **MSVP Pipeline** | Parallel unit reviews triggered immediately after worker tasks |
|
|
152
|
+
| 🧬 **Fractal Spawning** | Workers can recursively spawn sub-missions for complex tasks |
|
|
153
|
+
| ⚡ **20+ Parallel Tasks** | High-intensity execution with safety concurrency limits |
|
|
102
154
|
| 🔄 **Non-Stop Recovery** | WAL-based persistence (resumes tasks after crashes) |
|
|
103
155
|
| 🔥 **Multi-File Ops** | Work on different files at the same time |
|
|
104
156
|
| 🛡️ **Self-Scaling** | Dynamic concurrency limits based on success/failure |
|
|
105
157
|
| 🩹 **Memory Integrity** | Strict resource cleanup prevents leaks in long sessions |
|
|
106
|
-
|
|
|
158
|
+
| 🏗️ **Architectural Modularity**| Enforces language-agnostic clean code principles |
|
|
107
159
|
|
|
108
160
|
---
|
|
109
161
|
|
|
@@ -119,14 +171,13 @@ Built for "Infinite Missions," the OpenCode Orchestrator is engineered to handle
|
|
|
119
171
|
| 🔨 Build failure | Fix the issue and retry |
|
|
120
172
|
|
|
121
173
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
- **[System Architecture](docs/SYSTEM_ARCHITECTURE.md)** — Full technical deep-dive
|
|
125
|
-
|
|
174
|
+
---
|
|
126
175
|
|
|
127
176
|
## 🎹 Developer's Words
|
|
128
177
|
|
|
129
|
-
>
|
|
178
|
+
> "We are not just building a tool; we are building an autonomous engineer that can evolve with the project. HPFA and MSVP are the heart of this evolution—turning AI from a chatbot into a high-performance execution engine."
|
|
179
|
+
>
|
|
180
|
+
> [Read the full Developer's Note →](docs/DEVELOPERS_NOTE.md)
|
|
130
181
|
|
|
131
182
|
|
|
132
183
|
## 📄 License
|
|
@@ -12,3 +12,5 @@ export { VERIFICATION_REQUIREMENTS } from "./verification.js";
|
|
|
12
12
|
export { CORE_PHILOSOPHY } from "./core-philosophy.js";
|
|
13
13
|
export { SHARED_LSP_TOOLS } from "./lsp.js";
|
|
14
14
|
export { SHARED_AST_TOOLS } from "./ast.js";
|
|
15
|
+
export { MODULARITY_ENFORCEMENT } from "./modularity.js";
|
|
16
|
+
export { HYPER_PARALLEL_ENFORCEMENT } from "./hyper-parallel.js";
|
|
@@ -14,7 +14,8 @@ export declare class EventHandler {
|
|
|
14
14
|
private notifyParentIfAllComplete;
|
|
15
15
|
private scheduleCleanup;
|
|
16
16
|
private validateSessionHasOutput;
|
|
17
|
-
|
|
17
|
+
private onTaskComplete?;
|
|
18
|
+
constructor(client: OpencodeClient, store: TaskStore, concurrency: ConcurrencyController, findBySession: (sessionID: string) => ParallelTask | undefined, notifyParentIfAllComplete: (parentSessionID: string) => Promise<void>, scheduleCleanup: (taskId: string) => void, validateSessionHasOutput: (sessionID: string) => Promise<boolean>, onTaskComplete?: ((task: ParallelTask) => void | Promise<void>) | undefined);
|
|
18
19
|
/**
|
|
19
20
|
* Handle OpenCode session events for proper resource cleanup.
|
|
20
21
|
* Call this from your plugin's event hook.
|
|
@@ -15,6 +15,19 @@ export declare class TaskLauncher {
|
|
|
15
15
|
private onTaskError;
|
|
16
16
|
private startPolling;
|
|
17
17
|
constructor(client: OpencodeClient, directory: string, store: TaskStore, concurrency: ConcurrencyController, onTaskError: (taskId: string, error: unknown) => void, startPolling: () => void);
|
|
18
|
-
|
|
18
|
+
/**
|
|
19
|
+
* Unified launch method - handles both single and multiple tasks efficiently.
|
|
20
|
+
* All session creations happen in parallel immediately.
|
|
21
|
+
* Concurrency acquisition and prompt firing happen in the background.
|
|
22
|
+
*/
|
|
23
|
+
launch(inputs: LaunchInput | LaunchInput[]): Promise<ParallelTask | ParallelTask[]>;
|
|
24
|
+
/**
|
|
25
|
+
* Prepare task: Create session and registration without blocking on concurrency
|
|
26
|
+
*/
|
|
27
|
+
private prepareTask;
|
|
28
|
+
/**
|
|
29
|
+
* Background execution: Acquire slot and fire prompt
|
|
30
|
+
*/
|
|
31
|
+
private executeBackground;
|
|
19
32
|
}
|
|
20
33
|
export {};
|
|
@@ -13,8 +13,9 @@ export declare class TaskPoller {
|
|
|
13
13
|
private notifyParentIfAllComplete;
|
|
14
14
|
private scheduleCleanup;
|
|
15
15
|
private pruneExpiredTasks;
|
|
16
|
+
private onTaskComplete?;
|
|
16
17
|
private pollingInterval?;
|
|
17
|
-
constructor(client: OpencodeClient, store: TaskStore, concurrency: ConcurrencyController, notifyParentIfAllComplete: (parentSessionID: string) => Promise<void>, scheduleCleanup: (taskId: string) => void, pruneExpiredTasks: () => void);
|
|
18
|
+
constructor(client: OpencodeClient, store: TaskStore, concurrency: ConcurrencyController, notifyParentIfAllComplete: (parentSessionID: string) => Promise<void>, scheduleCleanup: (taskId: string) => void, pruneExpiredTasks: () => void, onTaskComplete?: ((task: ParallelTask) => void | Promise<void>) | undefined);
|
|
18
19
|
start(): void;
|
|
19
20
|
stop(): void;
|
|
20
21
|
isRunning(): boolean;
|
|
@@ -30,7 +30,7 @@ export declare class ParallelAgentManager {
|
|
|
30
30
|
private eventHandler;
|
|
31
31
|
private constructor();
|
|
32
32
|
static getInstance(client?: OpencodeClient, directory?: string): ParallelAgentManager;
|
|
33
|
-
launch(
|
|
33
|
+
launch(inputs: LaunchInput | LaunchInput[]): Promise<ParallelTask | ParallelTask[]>;
|
|
34
34
|
resume(input: ResumeInput): Promise<ParallelTask>;
|
|
35
35
|
getTask(id: string): ParallelTask | undefined;
|
|
36
36
|
getRunningTasks(): ParallelTask[];
|
|
@@ -54,6 +54,7 @@ export declare class ParallelAgentManager {
|
|
|
54
54
|
}): void;
|
|
55
55
|
private findBySession;
|
|
56
56
|
private handleTaskError;
|
|
57
|
+
private handleTaskComplete;
|
|
57
58
|
private recoverActiveTasks;
|
|
58
59
|
}
|
|
59
60
|
export declare const parallelAgentManager: {
|
package/dist/index.js
CHANGED
|
@@ -288,17 +288,24 @@ var PARALLEL_TASK = {
|
|
|
288
288
|
// Task lifecycle (24 hours for long tasks)
|
|
289
289
|
TTL_MS: 24 * TIME.HOUR,
|
|
290
290
|
CLEANUP_DELAY_MS: 10 * TIME.MINUTE,
|
|
291
|
-
MAX_DEPTH:
|
|
292
|
-
//
|
|
293
|
-
|
|
294
|
-
|
|
291
|
+
MAX_DEPTH: 5,
|
|
292
|
+
// Increased for fractal recursion
|
|
293
|
+
// Concurrency limits (Aggressive for intense processing)
|
|
294
|
+
DEFAULT_CONCURRENCY: 5,
|
|
295
|
+
MAX_CONCURRENCY: 20,
|
|
295
296
|
// Sync polling (for delegate_task sync mode)
|
|
297
|
+
// Optimized: Reduced polling frequency while relying more on events
|
|
296
298
|
SYNC_TIMEOUT_MS: 5 * TIME.MINUTE,
|
|
297
|
-
POLL_INTERVAL_MS:
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
299
|
+
POLL_INTERVAL_MS: 2e3,
|
|
300
|
+
// 500 → 2000ms (75% less API calls)
|
|
301
|
+
MIN_IDLE_TIME_MS: 3 * TIME.SECOND,
|
|
302
|
+
// 5s → 3s (faster detection)
|
|
303
|
+
MIN_STABILITY_MS: 2 * TIME.SECOND,
|
|
304
|
+
// 3s → 2s (faster stability)
|
|
305
|
+
STABLE_POLLS_REQUIRED: 2,
|
|
306
|
+
// 3 → 2 (faster completion)
|
|
307
|
+
MAX_POLL_COUNT: 150,
|
|
308
|
+
// 600 → 150 (adjusted for 2s interval)
|
|
302
309
|
// Session naming
|
|
303
310
|
SESSION_TITLE_PREFIX: "Parallel",
|
|
304
311
|
// Labels for output
|
|
@@ -1610,10 +1617,10 @@ function mergeDefs(...defs) {
|
|
|
1610
1617
|
function cloneDef(schema) {
|
|
1611
1618
|
return mergeDefs(schema._zod.def);
|
|
1612
1619
|
}
|
|
1613
|
-
function getElementAtPath(obj,
|
|
1614
|
-
if (!
|
|
1620
|
+
function getElementAtPath(obj, path6) {
|
|
1621
|
+
if (!path6)
|
|
1615
1622
|
return obj;
|
|
1616
|
-
return
|
|
1623
|
+
return path6.reduce((acc, key) => acc?.[key], obj);
|
|
1617
1624
|
}
|
|
1618
1625
|
function promiseAllObject(promisesObj) {
|
|
1619
1626
|
const keys = Object.keys(promisesObj);
|
|
@@ -1974,11 +1981,11 @@ function aborted(x, startIndex = 0) {
|
|
|
1974
1981
|
}
|
|
1975
1982
|
return false;
|
|
1976
1983
|
}
|
|
1977
|
-
function prefixIssues(
|
|
1984
|
+
function prefixIssues(path6, issues) {
|
|
1978
1985
|
return issues.map((iss) => {
|
|
1979
1986
|
var _a;
|
|
1980
1987
|
(_a = iss).path ?? (_a.path = []);
|
|
1981
|
-
iss.path.unshift(
|
|
1988
|
+
iss.path.unshift(path6);
|
|
1982
1989
|
return iss;
|
|
1983
1990
|
});
|
|
1984
1991
|
}
|
|
@@ -2146,7 +2153,7 @@ function treeifyError(error45, _mapper) {
|
|
|
2146
2153
|
return issue2.message;
|
|
2147
2154
|
};
|
|
2148
2155
|
const result = { errors: [] };
|
|
2149
|
-
const processError = (error46,
|
|
2156
|
+
const processError = (error46, path6 = []) => {
|
|
2150
2157
|
var _a, _b;
|
|
2151
2158
|
for (const issue2 of error46.issues) {
|
|
2152
2159
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
@@ -2156,7 +2163,7 @@ function treeifyError(error45, _mapper) {
|
|
|
2156
2163
|
} else if (issue2.code === "invalid_element") {
|
|
2157
2164
|
processError({ issues: issue2.issues }, issue2.path);
|
|
2158
2165
|
} else {
|
|
2159
|
-
const fullpath = [...
|
|
2166
|
+
const fullpath = [...path6, ...issue2.path];
|
|
2160
2167
|
if (fullpath.length === 0) {
|
|
2161
2168
|
result.errors.push(mapper(issue2));
|
|
2162
2169
|
continue;
|
|
@@ -2188,8 +2195,8 @@ function treeifyError(error45, _mapper) {
|
|
|
2188
2195
|
}
|
|
2189
2196
|
function toDotPath(_path) {
|
|
2190
2197
|
const segs = [];
|
|
2191
|
-
const
|
|
2192
|
-
for (const seg of
|
|
2198
|
+
const path6 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
|
|
2199
|
+
for (const seg of path6) {
|
|
2193
2200
|
if (typeof seg === "number")
|
|
2194
2201
|
segs.push(`[${seg}]`);
|
|
2195
2202
|
else if (typeof seg === "symbol")
|
|
@@ -13679,6 +13686,70 @@ var SHARED_AST_TOOLS = `<ast_tools>
|
|
|
13679
13686
|
- Always verify structural changes with \`${TOOL_NAMES.LSP_DIAGNOSTICS}\`.
|
|
13680
13687
|
</ast_tools>`;
|
|
13681
13688
|
|
|
13689
|
+
// src/agents/prompts/common/modularity.ts
|
|
13690
|
+
var MODULARITY_ENFORCEMENT = `${PROMPT_TAGS.QUALITY_CHECKLIST.open}
|
|
13691
|
+
\u{1F3D7}\uFE0F UNIVERSAL ARCHITECTURAL MODULARITY (Language-Agnostic)
|
|
13692
|
+
|
|
13693
|
+
To maintain a scalable and maintainable codebase, follow these structural principles regardless of the programming language:
|
|
13694
|
+
|
|
13695
|
+
### 1. Structural Layering (The "Layer Separation" Rule)
|
|
13696
|
+
Physically separate code based on its functional role. Do not mix these layers in a single file:
|
|
13697
|
+
- **Definitions & Contracts**: Data structures, types, interfaces, or schemas that define the "shape" of data.
|
|
13698
|
+
- **Static Values & Constants**: Hard-coded values, configuration keys, translations, or design tokens.
|
|
13699
|
+
- **Core Implementation**: The active logic, algorithms, functions, or classes that perform the work.
|
|
13700
|
+
- **State & Storage**: Persistent data handling, database interactions, or memory management logic.
|
|
13701
|
+
|
|
13702
|
+
### 2. Folder-Based Encapsulation (Feature-Oriented)
|
|
13703
|
+
- **Group by Domain/Feature**: Instead of grouping by technical type (e.g., all "utils" in one flat folder), create a directory for each meaningful feature or domain.
|
|
13704
|
+
- **Internal Structure**: For any feature complex enough to need multiple files, use a dedicated folder.
|
|
13705
|
+
- **Public Interface**: Each folder should have a clear entry point (e.g., \`index\`, \`mod.rs\`, \`main\`, or exports) that acts as the "Receptionist" for that module, hiding internal complexity.
|
|
13706
|
+
|
|
13707
|
+
### 3. Complexity Sharding
|
|
13708
|
+
If a single unit of code (file or module) starts to handle multiple distinct concerns, **shard it** into a directory:
|
|
13709
|
+
- **High Cohesion**: Keep related code close together within the same folder.
|
|
13710
|
+
- **Low Coupling**: Minimize dependencies between folders. Use "Shared/Common" directories only for truly universal helpers.
|
|
13711
|
+
|
|
13712
|
+
### 4. Code "Mass" Limits
|
|
13713
|
+
- Keep individual files concise and focused on a single responsibility.
|
|
13714
|
+
- If you have to scroll through "screens of code" to find a different type of logic, it belongs in a new file or sub-folder.
|
|
13715
|
+
${PROMPT_TAGS.QUALITY_CHECKLIST.close}`;
|
|
13716
|
+
|
|
13717
|
+
// src/agents/prompts/common/hyper-parallel.ts
|
|
13718
|
+
var HYPER_PARALLEL_ENFORCEMENT = `${PROMPT_TAGS.QUALITY_CHECKLIST.open}
|
|
13719
|
+
\u{1F680} HYPER-PARALLEL COGNITIVE ARCHITECTURE (HPFA)
|
|
13720
|
+
|
|
13721
|
+
To achieve maximum velocity, you MUST leverage these advanced parallel execution patterns:
|
|
13722
|
+
|
|
13723
|
+
### 1. Fractal Self-Delegation (Recursive Scaling)
|
|
13724
|
+
If you are a Worker and your assigned task is complex (e.g., implementing multiple endpoints, refactoring several files), **do not do it sequentially**.
|
|
13725
|
+
- **Spawn Sub-Workers**: Use \`delegate_task\` to launch sub-agents for independent sub-components.
|
|
13726
|
+
- **Fractal Depth**: You can scale down to any depth. Each worker acts as a local coordinator for its sub-workers.
|
|
13727
|
+
- **Context Sharding**: Give each sub-worker a focused, atomic prompt and relevant file context.
|
|
13728
|
+
|
|
13729
|
+
### 2. Speculative Racing (Competitive Implementation)
|
|
13730
|
+
When faced with a high-uncertainty problem (bug fixing, complex refactoring with multiple possible approaches):
|
|
13731
|
+
- **Launch a Race**: Spawn multiple Workers (\`mode: "race"\`) with slightly different prompts or strategies.
|
|
13732
|
+
- **Winning Criteria**: The first agent to produce a solution that passes unit tests "wins".
|
|
13733
|
+
- **Efficiency**: This eliminates the "try-fail-repeat" loop by trying all likely solutions simultaneously.
|
|
13734
|
+
|
|
13735
|
+
### 3. Asynchronous Batching
|
|
13736
|
+
When you need to perform many independent reads or metadata checks:
|
|
13737
|
+
- **Batch Operations**: Group your tool calls to trigger massive parallel execution host-side.
|
|
13738
|
+
- **Avoid Serial Bottlenecks**: Never wait for a tool result if you have other independent tasks you could be launching in parallel.
|
|
13739
|
+
|
|
13740
|
+
### 4. Barrier-Sync Integrated Pipeline (BSIP)
|
|
13741
|
+
Don't wait for all workers to finish before starting reviews:
|
|
13742
|
+
- **Pipelined Verification**: Immediately spawn a Reviewer task as soon as a Worker finishes its individual sub-task. The review of Module A happens while Module B is still being built.
|
|
13743
|
+
- **Synchronization Point**: Use the "Final Sync Barrier" to wait for all parallel implementation AND individual reviews to complete.
|
|
13744
|
+
- **Global Integration**: The final master Reviewer only acts once all individual units have been verified by their respective sub-reviewers.
|
|
13745
|
+
|
|
13746
|
+
### 5. Real-time Brain Sync
|
|
13747
|
+
As you work in a parallel session, log your critical findings or discovered interface changes to the shared task log.
|
|
13748
|
+
Assume that:
|
|
13749
|
+
- **Global Awareness**: Other workers are aware of your public findings.
|
|
13750
|
+
- **Consistency**: You must check for "Global Context Updates" to ensure your parallel work aligns with the latest state of the system.
|
|
13751
|
+
${PROMPT_TAGS.QUALITY_CHECKLIST.close}`;
|
|
13752
|
+
|
|
13682
13753
|
// src/agents/prompts/commander/role.ts
|
|
13683
13754
|
var COMMANDER_ROLE = `${PROMPT_TAGS.ROLE.open}
|
|
13684
13755
|
You are ${AGENT_NAMES.COMMANDER}. Autonomous mission controller.
|
|
@@ -15295,6 +15366,8 @@ var commander = {
|
|
|
15295
15366
|
// src/agents/subagents/planner.ts
|
|
15296
15367
|
var systemPrompt2 = [
|
|
15297
15368
|
PLANNER_ROLE,
|
|
15369
|
+
MODULARITY_ENFORCEMENT,
|
|
15370
|
+
HYPER_PARALLEL_ENFORCEMENT,
|
|
15298
15371
|
PLANNER_FORBIDDEN,
|
|
15299
15372
|
PLANNER_REQUIRED,
|
|
15300
15373
|
ENVIRONMENT_DISCOVERY,
|
|
@@ -15320,6 +15393,8 @@ var planner = {
|
|
|
15320
15393
|
// src/agents/subagents/worker.ts
|
|
15321
15394
|
var systemPrompt3 = [
|
|
15322
15395
|
WORKER_ROLE,
|
|
15396
|
+
MODULARITY_ENFORCEMENT,
|
|
15397
|
+
HYPER_PARALLEL_ENFORCEMENT,
|
|
15323
15398
|
WORKER_FORBIDDEN,
|
|
15324
15399
|
WORKER_REQUIRED,
|
|
15325
15400
|
ANTI_HALLUCINATION_CORE,
|
|
@@ -15347,6 +15422,8 @@ var worker = {
|
|
|
15347
15422
|
// src/agents/subagents/reviewer.ts
|
|
15348
15423
|
var systemPrompt4 = [
|
|
15349
15424
|
REVIEWER_ROLE,
|
|
15425
|
+
MODULARITY_ENFORCEMENT,
|
|
15426
|
+
HYPER_PARALLEL_ENFORCEMENT,
|
|
15350
15427
|
REVIEWER_FORBIDDEN,
|
|
15351
15428
|
REVIEWER_REQUIRED,
|
|
15352
15429
|
REVIEWER_VERIFICATION,
|
|
@@ -16229,7 +16306,7 @@ var TaskStore = class {
|
|
|
16229
16306
|
return Array.from(this.tasks.values());
|
|
16230
16307
|
}
|
|
16231
16308
|
getRunning() {
|
|
16232
|
-
return this.getAll().filter((t) => t.status === TASK_STATUS.RUNNING);
|
|
16309
|
+
return this.getAll().filter((t) => t.status === TASK_STATUS.RUNNING || t.status === TASK_STATUS.PENDING);
|
|
16233
16310
|
}
|
|
16234
16311
|
getByParent(parentSessionID) {
|
|
16235
16312
|
return this.getAll().filter((t) => t.parentSessionID === parentSessionID);
|
|
@@ -16948,74 +17025,114 @@ var TaskLauncher = class {
|
|
|
16948
17025
|
this.onTaskError = onTaskError;
|
|
16949
17026
|
this.startPolling = startPolling;
|
|
16950
17027
|
}
|
|
16951
|
-
|
|
16952
|
-
|
|
16953
|
-
|
|
16954
|
-
|
|
16955
|
-
|
|
16956
|
-
|
|
16957
|
-
|
|
16958
|
-
|
|
16959
|
-
|
|
17028
|
+
/**
|
|
17029
|
+
* Unified launch method - handles both single and multiple tasks efficiently.
|
|
17030
|
+
* All session creations happen in parallel immediately.
|
|
17031
|
+
* Concurrency acquisition and prompt firing happen in the background.
|
|
17032
|
+
*/
|
|
17033
|
+
async launch(inputs) {
|
|
17034
|
+
const isArray = Array.isArray(inputs);
|
|
17035
|
+
const taskInputs = isArray ? inputs : [inputs];
|
|
17036
|
+
if (taskInputs.length === 0) return isArray ? [] : null;
|
|
17037
|
+
log(`[task-launcher.ts] Batch launching ${taskInputs.length} task(s)`);
|
|
17038
|
+
const startTime = Date.now();
|
|
17039
|
+
const tasks = await Promise.all(taskInputs.map(
|
|
17040
|
+
(input) => this.prepareTask(input).catch((error45) => {
|
|
17041
|
+
log(`[task-launcher.ts] Failed to prepare task ${input.description}:`, error45);
|
|
17042
|
+
return null;
|
|
17043
|
+
})
|
|
17044
|
+
));
|
|
17045
|
+
const successfulTasks = tasks.filter((t) => t !== null);
|
|
17046
|
+
successfulTasks.forEach((task) => {
|
|
17047
|
+
this.executeBackground(task).catch((error45) => {
|
|
17048
|
+
log(`[task-launcher.ts] Background execution failed for ${task.id}:`, error45);
|
|
17049
|
+
this.onTaskError(task.id, error45);
|
|
16960
17050
|
});
|
|
16961
|
-
|
|
16962
|
-
|
|
16963
|
-
|
|
16964
|
-
|
|
16965
|
-
|
|
16966
|
-
|
|
16967
|
-
|
|
16968
|
-
|
|
16969
|
-
|
|
17051
|
+
});
|
|
17052
|
+
const elapsed = Date.now() - startTime;
|
|
17053
|
+
log(`[task-launcher.ts] Batch launch prepared: ${successfulTasks.length} tasks in ${elapsed}ms`);
|
|
17054
|
+
if (successfulTasks.length > 0) {
|
|
17055
|
+
this.startPolling();
|
|
17056
|
+
}
|
|
17057
|
+
return isArray ? successfulTasks : successfulTasks[0] || null;
|
|
17058
|
+
}
|
|
17059
|
+
/**
|
|
17060
|
+
* Prepare task: Create session and registration without blocking on concurrency
|
|
17061
|
+
*/
|
|
17062
|
+
async prepareTask(input) {
|
|
17063
|
+
const createResult = await this.client.session.create({
|
|
17064
|
+
body: {
|
|
17065
|
+
parentID: input.parentSessionID,
|
|
17066
|
+
title: `${PARALLEL_TASK.SESSION_TITLE_PREFIX}: ${input.description}`
|
|
17067
|
+
},
|
|
17068
|
+
query: { directory: this.directory }
|
|
17069
|
+
});
|
|
17070
|
+
if (createResult.error || !createResult.data?.id) {
|
|
17071
|
+
throw new Error(`Session creation failed: ${createResult.error || "No ID"}`);
|
|
17072
|
+
}
|
|
17073
|
+
const sessionID = createResult.data.id;
|
|
17074
|
+
const taskId = `${ID_PREFIX.TASK}${crypto.randomUUID().slice(0, 8)}`;
|
|
17075
|
+
const task = {
|
|
17076
|
+
id: taskId,
|
|
17077
|
+
sessionID,
|
|
17078
|
+
parentSessionID: input.parentSessionID,
|
|
17079
|
+
description: input.description,
|
|
17080
|
+
prompt: input.prompt,
|
|
17081
|
+
agent: input.agent,
|
|
17082
|
+
status: TASK_STATUS.PENDING,
|
|
17083
|
+
// Start as PENDING
|
|
17084
|
+
startedAt: /* @__PURE__ */ new Date(),
|
|
17085
|
+
concurrencyKey: input.agent,
|
|
17086
|
+
depth: (input.depth ?? 0) + 1,
|
|
17087
|
+
mode: input.mode || "normal",
|
|
17088
|
+
groupID: input.groupID
|
|
17089
|
+
};
|
|
17090
|
+
this.store.set(taskId, task);
|
|
17091
|
+
this.store.trackPending(input.parentSessionID, taskId);
|
|
17092
|
+
taskWAL.log(WAL_ACTIONS.LAUNCH, task).catch(() => {
|
|
17093
|
+
});
|
|
17094
|
+
const toastManager = getTaskToastManager();
|
|
17095
|
+
if (toastManager) {
|
|
17096
|
+
toastManager.addTask({
|
|
16970
17097
|
id: taskId,
|
|
16971
|
-
sessionID,
|
|
16972
|
-
parentSessionID: input.parentSessionID,
|
|
16973
17098
|
description: input.description,
|
|
16974
|
-
prompt: input.prompt,
|
|
16975
17099
|
agent: input.agent,
|
|
16976
|
-
|
|
16977
|
-
|
|
16978
|
-
|
|
16979
|
-
|
|
16980
|
-
|
|
16981
|
-
|
|
16982
|
-
|
|
17100
|
+
isBackground: true,
|
|
17101
|
+
parentSessionID: input.parentSessionID,
|
|
17102
|
+
sessionID
|
|
17103
|
+
});
|
|
17104
|
+
}
|
|
17105
|
+
presets.sessionCreated(sessionID, input.agent);
|
|
17106
|
+
return task;
|
|
17107
|
+
}
|
|
17108
|
+
/**
|
|
17109
|
+
* Background execution: Acquire slot and fire prompt
|
|
17110
|
+
*/
|
|
17111
|
+
async executeBackground(task) {
|
|
17112
|
+
try {
|
|
17113
|
+
await this.concurrency.acquire(task.agent);
|
|
17114
|
+
task.status = TASK_STATUS.RUNNING;
|
|
17115
|
+
task.startedAt = /* @__PURE__ */ new Date();
|
|
17116
|
+
this.store.set(task.id, task);
|
|
16983
17117
|
taskWAL.log(WAL_ACTIONS.LAUNCH, task).catch(() => {
|
|
16984
17118
|
});
|
|
16985
|
-
this.
|
|
16986
|
-
|
|
16987
|
-
path: { id: sessionID },
|
|
17119
|
+
await this.client.session.prompt({
|
|
17120
|
+
path: { id: task.sessionID },
|
|
16988
17121
|
body: {
|
|
16989
|
-
agent:
|
|
17122
|
+
agent: task.agent,
|
|
16990
17123
|
tools: {
|
|
16991
|
-
//
|
|
16992
|
-
delegate_task:
|
|
16993
|
-
get_task_result:
|
|
16994
|
-
list_tasks:
|
|
16995
|
-
cancel_task:
|
|
17124
|
+
// HPFA: Allow agents to delegate sub-tasks (Fractal Spawning)
|
|
17125
|
+
delegate_task: true,
|
|
17126
|
+
get_task_result: true,
|
|
17127
|
+
list_tasks: true,
|
|
17128
|
+
cancel_task: true
|
|
16996
17129
|
},
|
|
16997
|
-
parts: [{ type: PART_TYPES.TEXT, text:
|
|
17130
|
+
parts: [{ type: PART_TYPES.TEXT, text: task.prompt }]
|
|
16998
17131
|
}
|
|
16999
|
-
}).catch((error45) => {
|
|
17000
|
-
log(`Prompt error for ${taskId}:`, error45);
|
|
17001
|
-
this.onTaskError(taskId, error45);
|
|
17002
17132
|
});
|
|
17003
|
-
|
|
17004
|
-
if (toastManager) {
|
|
17005
|
-
toastManager.addTask({
|
|
17006
|
-
id: taskId,
|
|
17007
|
-
description: input.description,
|
|
17008
|
-
agent: input.agent,
|
|
17009
|
-
isBackground: true,
|
|
17010
|
-
parentSessionID: input.parentSessionID,
|
|
17011
|
-
sessionID
|
|
17012
|
-
});
|
|
17013
|
-
}
|
|
17014
|
-
presets.sessionCreated(sessionID, input.agent);
|
|
17015
|
-
log(`Launched ${taskId} in session ${sessionID}`);
|
|
17016
|
-
return task;
|
|
17133
|
+
log(`[task-launcher.ts] Task ${task.id} (${task.agent}) started running`);
|
|
17017
17134
|
} catch (error45) {
|
|
17018
|
-
this.concurrency.release(
|
|
17135
|
+
this.concurrency.release(task.agent);
|
|
17019
17136
|
throw error45;
|
|
17020
17137
|
}
|
|
17021
17138
|
}
|
|
@@ -17079,13 +17196,14 @@ var CONFIG = {
|
|
|
17079
17196
|
|
|
17080
17197
|
// src/core/agents/manager/task-poller.ts
|
|
17081
17198
|
var TaskPoller = class {
|
|
17082
|
-
constructor(client, store, concurrency, notifyParentIfAllComplete, scheduleCleanup, pruneExpiredTasks) {
|
|
17199
|
+
constructor(client, store, concurrency, notifyParentIfAllComplete, scheduleCleanup, pruneExpiredTasks, onTaskComplete) {
|
|
17083
17200
|
this.client = client;
|
|
17084
17201
|
this.store = store;
|
|
17085
17202
|
this.concurrency = concurrency;
|
|
17086
17203
|
this.notifyParentIfAllComplete = notifyParentIfAllComplete;
|
|
17087
17204
|
this.scheduleCleanup = scheduleCleanup;
|
|
17088
17205
|
this.pruneExpiredTasks = pruneExpiredTasks;
|
|
17206
|
+
this.onTaskComplete = onTaskComplete;
|
|
17089
17207
|
}
|
|
17090
17208
|
pollingInterval;
|
|
17091
17209
|
start() {
|
|
@@ -17116,6 +17234,7 @@ var TaskPoller = class {
|
|
|
17116
17234
|
const allStatuses = statusResult.data ?? {};
|
|
17117
17235
|
for (const task of running) {
|
|
17118
17236
|
try {
|
|
17237
|
+
if (task.status === TASK_STATUS.PENDING) continue;
|
|
17119
17238
|
const sessionStatus = allStatuses[task.sessionID];
|
|
17120
17239
|
if (sessionStatus?.type === SESSION_STATUS.IDLE) {
|
|
17121
17240
|
const elapsed2 = Date.now() - task.startedAt.getTime();
|
|
@@ -17168,6 +17287,9 @@ var TaskPoller = class {
|
|
|
17168
17287
|
this.scheduleCleanup(task.id);
|
|
17169
17288
|
taskWAL.log(WAL_ACTIONS.COMPLETE, task).catch(() => {
|
|
17170
17289
|
});
|
|
17290
|
+
if (this.onTaskComplete) {
|
|
17291
|
+
Promise.resolve(this.onTaskComplete(task)).catch((err) => log("Error in onTaskComplete callback:", err));
|
|
17292
|
+
}
|
|
17171
17293
|
const duration3 = formatDuration(task.startedAt, task.completedAt);
|
|
17172
17294
|
presets.sessionCompleted(task.sessionID, duration3);
|
|
17173
17295
|
log(`Completed ${task.id} (${duration3})`);
|
|
@@ -17324,7 +17446,7 @@ You will be notified when ALL tasks complete. Continue productive work.`;
|
|
|
17324
17446
|
|
|
17325
17447
|
// src/core/agents/manager/event-handler.ts
|
|
17326
17448
|
var EventHandler = class {
|
|
17327
|
-
constructor(client, store, concurrency, findBySession, notifyParentIfAllComplete, scheduleCleanup, validateSessionHasOutput2) {
|
|
17449
|
+
constructor(client, store, concurrency, findBySession, notifyParentIfAllComplete, scheduleCleanup, validateSessionHasOutput2, onTaskComplete) {
|
|
17328
17450
|
this.client = client;
|
|
17329
17451
|
this.store = store;
|
|
17330
17452
|
this.concurrency = concurrency;
|
|
@@ -17332,6 +17454,7 @@ var EventHandler = class {
|
|
|
17332
17454
|
this.notifyParentIfAllComplete = notifyParentIfAllComplete;
|
|
17333
17455
|
this.scheduleCleanup = scheduleCleanup;
|
|
17334
17456
|
this.validateSessionHasOutput = validateSessionHasOutput2;
|
|
17457
|
+
this.onTaskComplete = onTaskComplete;
|
|
17335
17458
|
}
|
|
17336
17459
|
/**
|
|
17337
17460
|
* Handle OpenCode session events for proper resource cleanup.
|
|
@@ -17380,6 +17503,9 @@ var EventHandler = class {
|
|
|
17380
17503
|
this.scheduleCleanup(task.id);
|
|
17381
17504
|
taskWAL.log(WAL_ACTIONS.COMPLETE, task).catch(() => {
|
|
17382
17505
|
});
|
|
17506
|
+
if (this.onTaskComplete) {
|
|
17507
|
+
Promise.resolve(this.onTaskComplete(task)).catch((err) => log("Error in onTaskComplete callback:", err));
|
|
17508
|
+
}
|
|
17383
17509
|
log(`Task ${task.id} completed via session.idle event (${formatDuration(task.startedAt, task.completedAt)})`);
|
|
17384
17510
|
}
|
|
17385
17511
|
handleSessionDeleted(task) {
|
|
@@ -17426,7 +17552,8 @@ var ParallelAgentManager = class _ParallelAgentManager {
|
|
|
17426
17552
|
this.concurrency,
|
|
17427
17553
|
(parentSessionID) => this.cleaner.notifyParentIfAllComplete(parentSessionID),
|
|
17428
17554
|
(taskId) => this.cleaner.scheduleCleanup(taskId),
|
|
17429
|
-
() => this.cleaner.pruneExpiredTasks()
|
|
17555
|
+
() => this.cleaner.pruneExpiredTasks(),
|
|
17556
|
+
(task) => this.handleTaskComplete(task)
|
|
17430
17557
|
);
|
|
17431
17558
|
this.launcher = new TaskLauncher(
|
|
17432
17559
|
client,
|
|
@@ -17450,7 +17577,8 @@ var ParallelAgentManager = class _ParallelAgentManager {
|
|
|
17450
17577
|
(sessionID) => this.findBySession(sessionID),
|
|
17451
17578
|
(parentSessionID) => this.cleaner.notifyParentIfAllComplete(parentSessionID),
|
|
17452
17579
|
(taskId) => this.cleaner.scheduleCleanup(taskId),
|
|
17453
|
-
(sessionID) => this.poller.validateSessionHasOutput(sessionID)
|
|
17580
|
+
(sessionID) => this.poller.validateSessionHasOutput(sessionID),
|
|
17581
|
+
(task) => this.handleTaskComplete(task)
|
|
17454
17582
|
);
|
|
17455
17583
|
this.recoverActiveTasks().catch((err) => {
|
|
17456
17584
|
log("Recovery error:", err);
|
|
@@ -17468,9 +17596,9 @@ var ParallelAgentManager = class _ParallelAgentManager {
|
|
|
17468
17596
|
// ========================================================================
|
|
17469
17597
|
// Public API
|
|
17470
17598
|
// ========================================================================
|
|
17471
|
-
async launch(
|
|
17599
|
+
async launch(inputs) {
|
|
17472
17600
|
this.cleaner.pruneExpiredTasks();
|
|
17473
|
-
return this.launcher.launch(
|
|
17601
|
+
return this.launcher.launch(inputs);
|
|
17474
17602
|
}
|
|
17475
17603
|
async resume(input) {
|
|
17476
17604
|
return this.resumer.resume(input);
|
|
@@ -17570,6 +17698,30 @@ var ParallelAgentManager = class _ParallelAgentManager {
|
|
|
17570
17698
|
taskWAL.log(WAL_ACTIONS.UPDATE, task).catch(() => {
|
|
17571
17699
|
});
|
|
17572
17700
|
}
|
|
17701
|
+
async handleTaskComplete(task) {
|
|
17702
|
+
if (task.agent === AGENT_NAMES.WORKER && task.mode !== "race") {
|
|
17703
|
+
log(`[MSVP] Triggering 1\uCC28 \uB9AC\uBDF0 (Unit Review) for task ${task.id}`);
|
|
17704
|
+
try {
|
|
17705
|
+
await this.launch({
|
|
17706
|
+
agent: AGENT_NAMES.REVIEWER,
|
|
17707
|
+
description: `1\uCC28 \uB9AC\uBDF0: ${task.description}`,
|
|
17708
|
+
prompt: `\uC9C4\uD589\uB41C \uC791\uC5C5(\`${task.description}\`)\uC5D0 \uB300\uD574 1\uCC28 \uB9AC\uBDF0(\uC720\uB2DB \uAC80\uC99D)\uB97C \uC218\uD589\uD558\uC138\uC694.
|
|
17709
|
+
\uC8FC\uC694 \uC810\uAC80 \uC0AC\uD56D:
|
|
17710
|
+
1. \uD574\uB2F9 \uBAA8\uB4C8\uC758 \uC720\uB2DB \uD14C\uC2A4\uD2B8 \uCF54\uB4DC \uC791\uC131 \uC5EC\uBD80 \uBC0F \uD1B5\uACFC \uD655\uC778
|
|
17711
|
+
2. \uCF54\uB4DC \uD488\uC9C8 \uBC0F \uBAA8\uB4C8\uC131 \uC900\uC218 \uC5EC\uBD80
|
|
17712
|
+
3. \uBC1C\uACAC\uB41C \uACB0\uD568 \uC989\uC2DC \uC218\uC815 \uC9C0\uC2DC \uB610\uB294 \uB9AC\uD3EC\uD2B8
|
|
17713
|
+
|
|
17714
|
+
\uC774 \uC791\uC5C5\uC740 \uC804\uCCB4 \uD1B5\uD569 \uC804 \uBD80\uD488 \uB2E8\uC704\uC758 \uC644\uACB0\uC131\uC744 \uBCF4\uC7A5\uD558\uAE30 \uC704\uD568\uC785\uB2C8\uB2E4.`,
|
|
17715
|
+
parentSessionID: task.parentSessionID,
|
|
17716
|
+
depth: task.depth,
|
|
17717
|
+
groupID: task.groupID || task.id
|
|
17718
|
+
// Group reviews with their origins
|
|
17719
|
+
});
|
|
17720
|
+
} catch (error45) {
|
|
17721
|
+
log(`[MSVP] Failed to trigger review for ${task.id}:`, error45);
|
|
17722
|
+
}
|
|
17723
|
+
}
|
|
17724
|
+
}
|
|
17573
17725
|
async recoverActiveTasks() {
|
|
17574
17726
|
const tasks = await taskWAL.readAll();
|
|
17575
17727
|
if (tasks.size === 0) return;
|
|
@@ -17749,27 +17901,44 @@ var createDelegateTaskTool = (manager, client) => tool({
|
|
|
17749
17901
|
description: tool.schema.string().describe("Task description"),
|
|
17750
17902
|
prompt: tool.schema.string().describe("Prompt for the agent"),
|
|
17751
17903
|
background: tool.schema.boolean().describe("true=async, false=sync"),
|
|
17752
|
-
resume: tool.schema.string().optional().describe("Session ID to resume (from previous task.sessionID)")
|
|
17904
|
+
resume: tool.schema.string().optional().describe("Session ID to resume (from previous task.sessionID)"),
|
|
17905
|
+
mode: tool.schema.enum(["normal", "race", "fractal"]).optional().describe("Task mode (race=first wins, fractal=recursive)"),
|
|
17906
|
+
groupID: tool.schema.string().optional().describe("Group ID for racing or tracking recursive families")
|
|
17753
17907
|
},
|
|
17754
17908
|
async execute(args, context) {
|
|
17755
|
-
const { agent, description, prompt, background, resume } = args;
|
|
17909
|
+
const { agent, description, prompt, background, resume, mode, groupID } = args;
|
|
17756
17910
|
const ctx = context;
|
|
17757
|
-
log(`${PARALLEL_LOG.DELEGATE_TASK} execute() called`, { agent, description, background, resume, parentSession: ctx.sessionID });
|
|
17911
|
+
log(`${PARALLEL_LOG.DELEGATE_TASK} execute() called`, { agent, description, background, resume, mode, groupID, parentSession: ctx.sessionID });
|
|
17758
17912
|
const sessionClient = client;
|
|
17759
17913
|
if (background === void 0) {
|
|
17760
17914
|
return `${OUTPUT_LABEL.ERROR} 'background' parameter is REQUIRED.`;
|
|
17761
17915
|
}
|
|
17762
17916
|
if (resume) {
|
|
17763
17917
|
try {
|
|
17764
|
-
const
|
|
17918
|
+
const input = {
|
|
17765
17919
|
sessionId: resume,
|
|
17766
17920
|
prompt,
|
|
17767
|
-
parentSessionID: ctx.sessionID
|
|
17768
|
-
|
|
17921
|
+
parentSessionID: ctx.sessionID,
|
|
17922
|
+
agent,
|
|
17923
|
+
// Assuming agent is needed for resume context
|
|
17924
|
+
description,
|
|
17925
|
+
// Assuming description is needed for resume context
|
|
17926
|
+
mode,
|
|
17927
|
+
groupID
|
|
17928
|
+
};
|
|
17929
|
+
const launchResult = await manager.launch(input);
|
|
17930
|
+
const task = Array.isArray(launchResult) ? launchResult[0] : launchResult;
|
|
17931
|
+
if (!task) {
|
|
17932
|
+
return `Failed to launch task: ${input.description}`;
|
|
17933
|
+
}
|
|
17934
|
+
const taskId = task.id;
|
|
17769
17935
|
if (background === true) {
|
|
17770
|
-
|
|
17936
|
+
const message = `Launched ${input.agent} task: ${input.description}
|
|
17937
|
+
Task ID: ${taskId}
|
|
17938
|
+
Session: ${task.sessionID}`;
|
|
17939
|
+
return `${OUTPUT_LABEL.RESUME} task: \`${taskId}\` (${task.agent}) in session \`${task.sessionID}\`
|
|
17771
17940
|
|
|
17772
|
-
Previous context preserved. Use \`get_task_result({ taskId: "${
|
|
17941
|
+
Previous context preserved. Use \`get_task_result({ taskId: "${taskId}" })\` when complete.`;
|
|
17773
17942
|
}
|
|
17774
17943
|
const startTime = Date.now();
|
|
17775
17944
|
const session = sessionClient.session;
|
|
@@ -17789,12 +17958,15 @@ ${text || "(No output)"}`;
|
|
|
17789
17958
|
}
|
|
17790
17959
|
if (background === true) {
|
|
17791
17960
|
try {
|
|
17792
|
-
const
|
|
17961
|
+
const launchResult = await manager.launch({
|
|
17793
17962
|
agent,
|
|
17794
17963
|
description,
|
|
17795
17964
|
prompt,
|
|
17796
|
-
parentSessionID: ctx.sessionID
|
|
17965
|
+
parentSessionID: ctx.sessionID,
|
|
17966
|
+
mode,
|
|
17967
|
+
groupID
|
|
17797
17968
|
});
|
|
17969
|
+
const task = Array.isArray(launchResult) ? launchResult[0] : launchResult;
|
|
17798
17970
|
presets.taskStarted(task.id, agent);
|
|
17799
17971
|
return `${OUTPUT_LABEL.SPAWNED} task: \`${task.id}\` (${agent})
|
|
17800
17972
|
Session: \`${task.sessionID}\` (save for resume)`;
|
|
@@ -18841,10 +19013,10 @@ async function resolveCommandPath(key, commandName) {
|
|
|
18841
19013
|
const currentPending = pending.get(key);
|
|
18842
19014
|
if (currentPending) return currentPending;
|
|
18843
19015
|
const promise2 = (async () => {
|
|
18844
|
-
const
|
|
18845
|
-
cache[key] =
|
|
19016
|
+
const path6 = await findCommand(commandName);
|
|
19017
|
+
cache[key] = path6;
|
|
18846
19018
|
pending.delete(key);
|
|
18847
|
-
return
|
|
19019
|
+
return path6;
|
|
18848
19020
|
})();
|
|
18849
19021
|
pending.set(key, promise2);
|
|
18850
19022
|
return promise2;
|
|
@@ -18903,21 +19075,21 @@ import { exec as exec2 } from "node:child_process";
|
|
|
18903
19075
|
import { promisify as promisify2 } from "node:util";
|
|
18904
19076
|
var execAsync2 = promisify2(exec2);
|
|
18905
19077
|
async function notifyDarwin(title, message) {
|
|
18906
|
-
const
|
|
19078
|
+
const path6 = await resolveCommandPath(
|
|
18907
19079
|
NOTIFICATION_COMMAND_KEYS.OSASCRIPT,
|
|
18908
19080
|
NOTIFICATION_COMMANDS.OSASCRIPT
|
|
18909
19081
|
);
|
|
18910
|
-
if (!
|
|
19082
|
+
if (!path6) return;
|
|
18911
19083
|
const escT = title.replace(/"/g, '\\"');
|
|
18912
19084
|
const escM = message.replace(/"/g, '\\"');
|
|
18913
|
-
await execAsync2(`${
|
|
19085
|
+
await execAsync2(`${path6} -e 'display notification "${escM}" with title "${escT}" sound name "Glass"'`);
|
|
18914
19086
|
}
|
|
18915
19087
|
async function notifyLinux(title, message) {
|
|
18916
|
-
const
|
|
19088
|
+
const path6 = await resolveCommandPath(
|
|
18917
19089
|
NOTIFICATION_COMMAND_KEYS.NOTIFY_SEND,
|
|
18918
19090
|
NOTIFICATION_COMMANDS.NOTIFY_SEND
|
|
18919
19091
|
);
|
|
18920
|
-
if (
|
|
19092
|
+
if (path6) await execAsync2(`${path6} "${title}" "${message}" 2>/dev/null`);
|
|
18921
19093
|
}
|
|
18922
19094
|
async function notifyWindows(title, message) {
|
|
18923
19095
|
const ps = await resolveCommandPath(
|
|
@@ -18963,11 +19135,11 @@ import { exec as exec3 } from "node:child_process";
|
|
|
18963
19135
|
async function playDarwin(soundPath) {
|
|
18964
19136
|
if (!soundPath) return;
|
|
18965
19137
|
try {
|
|
18966
|
-
const
|
|
19138
|
+
const path6 = await resolveCommandPath(
|
|
18967
19139
|
NOTIFICATION_COMMAND_KEYS.AFPLAY,
|
|
18968
19140
|
NOTIFICATION_COMMANDS.AFPLAY
|
|
18969
19141
|
);
|
|
18970
|
-
if (
|
|
19142
|
+
if (path6) exec3(`"${path6}" "${soundPath}"`);
|
|
18971
19143
|
} catch (err) {
|
|
18972
19144
|
log(`[session-notify] Error playing sound (Darwin): ${err}`);
|
|
18973
19145
|
}
|
|
@@ -20237,10 +20409,65 @@ function createEventHandler(ctx) {
|
|
|
20237
20409
|
};
|
|
20238
20410
|
}
|
|
20239
20411
|
|
|
20412
|
+
// src/utils/compatibility/claude.ts
|
|
20413
|
+
import fs6 from "fs";
|
|
20414
|
+
import path5 from "path";
|
|
20415
|
+
function findClaudeRules(startDir = process.cwd()) {
|
|
20416
|
+
try {
|
|
20417
|
+
let currentDir = startDir;
|
|
20418
|
+
const root = path5.parse(startDir).root;
|
|
20419
|
+
while (true) {
|
|
20420
|
+
const claudeMdPath = path5.join(currentDir, "CLAUDE.md");
|
|
20421
|
+
if (fs6.existsSync(claudeMdPath)) {
|
|
20422
|
+
try {
|
|
20423
|
+
const content = fs6.readFileSync(claudeMdPath, "utf-8");
|
|
20424
|
+
log(`[compatibility] Loaded CLAUDE.md from ${claudeMdPath}`);
|
|
20425
|
+
return formatRules("CLAUDE.md", content);
|
|
20426
|
+
} catch (e) {
|
|
20427
|
+
log(`[compatibility] Error reading CLAUDE.md: ${e}`);
|
|
20428
|
+
}
|
|
20429
|
+
}
|
|
20430
|
+
if (currentDir === root) break;
|
|
20431
|
+
currentDir = path5.dirname(currentDir);
|
|
20432
|
+
}
|
|
20433
|
+
const copilotPath = path5.join(startDir, ".github", "copilot-instructions.md");
|
|
20434
|
+
if (fs6.existsSync(copilotPath)) {
|
|
20435
|
+
return formatRules("Copilot Instructions", fs6.readFileSync(copilotPath, "utf-8"));
|
|
20436
|
+
}
|
|
20437
|
+
return null;
|
|
20438
|
+
} catch (error45) {
|
|
20439
|
+
log(`[compatibility] Error finding Claude rules: ${error45}`);
|
|
20440
|
+
return null;
|
|
20441
|
+
}
|
|
20442
|
+
}
|
|
20443
|
+
function formatRules(source, content) {
|
|
20444
|
+
return `
|
|
20445
|
+
<project_rules source="${source}">
|
|
20446
|
+
${content}
|
|
20447
|
+
</project_rules>
|
|
20448
|
+
|
|
20449
|
+
<claude_compatibility>
|
|
20450
|
+
These rules are from the project's ${source}.
|
|
20451
|
+
You MUST follow them as strictly as if they were your system prompt.
|
|
20452
|
+
This plugin runs in "Claude Code Compatibility Mode".
|
|
20453
|
+
</claude_compatibility>
|
|
20454
|
+
`;
|
|
20455
|
+
}
|
|
20456
|
+
|
|
20240
20457
|
// src/plugin-handlers/config-handler.ts
|
|
20241
20458
|
function createConfigHandler() {
|
|
20242
|
-
const commanderPrompt = AGENTS[AGENT_NAMES.COMMANDER]?.systemPrompt || "";
|
|
20243
20459
|
return async (config2) => {
|
|
20460
|
+
const claudeRules = findClaudeRules();
|
|
20461
|
+
const injectRules = (prompt) => {
|
|
20462
|
+
if (!claudeRules) return prompt;
|
|
20463
|
+
return `${prompt}
|
|
20464
|
+
|
|
20465
|
+
${claudeRules}`;
|
|
20466
|
+
};
|
|
20467
|
+
const commanderPrompt = injectRules(AGENTS[AGENT_NAMES.COMMANDER]?.systemPrompt || "");
|
|
20468
|
+
const plannerPrompt = injectRules(AGENTS[AGENT_NAMES.PLANNER]?.systemPrompt || "");
|
|
20469
|
+
const workerPrompt = injectRules(AGENTS[AGENT_NAMES.WORKER]?.systemPrompt || "");
|
|
20470
|
+
const reviewerPrompt = injectRules(AGENTS[AGENT_NAMES.REVIEWER]?.systemPrompt || "");
|
|
20244
20471
|
const existingCommands = config2.command ?? {};
|
|
20245
20472
|
const existingAgents = config2.agent ?? {};
|
|
20246
20473
|
const orchestratorCommands = {};
|
|
@@ -20266,7 +20493,7 @@ function createConfigHandler() {
|
|
|
20266
20493
|
description: "Strategic planning and research specialist",
|
|
20267
20494
|
mode: "subagent",
|
|
20268
20495
|
hidden: true,
|
|
20269
|
-
prompt:
|
|
20496
|
+
prompt: plannerPrompt,
|
|
20270
20497
|
maxTokens: AGENT_TOKENS.SUBAGENT_MAX_TOKENS,
|
|
20271
20498
|
color: "#9B59B6"
|
|
20272
20499
|
},
|
|
@@ -20274,7 +20501,7 @@ function createConfigHandler() {
|
|
|
20274
20501
|
description: "Implementation and documentation specialist",
|
|
20275
20502
|
mode: "subagent",
|
|
20276
20503
|
hidden: true,
|
|
20277
|
-
prompt:
|
|
20504
|
+
prompt: workerPrompt,
|
|
20278
20505
|
maxTokens: AGENT_TOKENS.SUBAGENT_MAX_TOKENS,
|
|
20279
20506
|
color: "#E67E22"
|
|
20280
20507
|
},
|
|
@@ -20282,7 +20509,7 @@ function createConfigHandler() {
|
|
|
20282
20509
|
description: "Verification and context management specialist",
|
|
20283
20510
|
mode: "subagent",
|
|
20284
20511
|
hidden: true,
|
|
20285
|
-
prompt:
|
|
20512
|
+
prompt: reviewerPrompt,
|
|
20286
20513
|
maxTokens: AGENT_TOKENS.SUBAGENT_MAX_TOKENS,
|
|
20287
20514
|
color: "#27AE60"
|
|
20288
20515
|
}
|
|
@@ -1,18 +1,23 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Parallel Task Configuration
|
|
3
3
|
*/
|
|
4
|
+
export declare const TASK_MODE: {
|
|
5
|
+
readonly NORMAL: "normal";
|
|
6
|
+
readonly RACE: "race";
|
|
7
|
+
readonly FRACTAL: "fractal";
|
|
8
|
+
};
|
|
4
9
|
export declare const PARALLEL_TASK: {
|
|
5
10
|
readonly TTL_MS: number;
|
|
6
11
|
readonly CLEANUP_DELAY_MS: number;
|
|
7
|
-
readonly MAX_DEPTH:
|
|
8
|
-
readonly DEFAULT_CONCURRENCY:
|
|
9
|
-
readonly MAX_CONCURRENCY:
|
|
12
|
+
readonly MAX_DEPTH: 5;
|
|
13
|
+
readonly DEFAULT_CONCURRENCY: 5;
|
|
14
|
+
readonly MAX_CONCURRENCY: 20;
|
|
10
15
|
readonly SYNC_TIMEOUT_MS: number;
|
|
11
|
-
readonly POLL_INTERVAL_MS:
|
|
16
|
+
readonly POLL_INTERVAL_MS: 2000;
|
|
12
17
|
readonly MIN_IDLE_TIME_MS: number;
|
|
13
18
|
readonly MIN_STABILITY_MS: number;
|
|
14
|
-
readonly STABLE_POLLS_REQUIRED:
|
|
15
|
-
readonly MAX_POLL_COUNT:
|
|
19
|
+
readonly STABLE_POLLS_REQUIRED: 2;
|
|
20
|
+
readonly MAX_POLL_COUNT: 150;
|
|
16
21
|
readonly SESSION_TITLE_PREFIX: "Parallel";
|
|
17
22
|
readonly LABEL: "parallel";
|
|
18
23
|
readonly GROUP_PREFIX: "parallel:";
|
|
@@ -18,6 +18,12 @@ export declare const createDelegateTaskTool: (manager: ParallelAgentManager, cli
|
|
|
18
18
|
prompt: import("zod").ZodString;
|
|
19
19
|
background: import("zod").ZodBoolean;
|
|
20
20
|
resume: import("zod").ZodOptional<import("zod").ZodString>;
|
|
21
|
+
mode: import("zod").ZodOptional<import("zod").ZodEnum<{
|
|
22
|
+
normal: "normal";
|
|
23
|
+
race: "race";
|
|
24
|
+
fractal: "fractal";
|
|
25
|
+
}>>;
|
|
26
|
+
groupID: import("zod").ZodOptional<import("zod").ZodString>;
|
|
21
27
|
};
|
|
22
28
|
execute(args: {
|
|
23
29
|
agent: string;
|
|
@@ -25,5 +31,7 @@ export declare const createDelegateTaskTool: (manager: ParallelAgentManager, cli
|
|
|
25
31
|
prompt: string;
|
|
26
32
|
background: boolean;
|
|
27
33
|
resume?: string | undefined;
|
|
34
|
+
mode?: "normal" | "race" | "fractal" | undefined;
|
|
35
|
+
groupID?: string | undefined;
|
|
28
36
|
}, context: import("@opencode-ai/plugin").ToolContext): Promise<string>;
|
|
29
37
|
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Find and read CLAUDE.md guidelines.
|
|
3
|
+
* Follows Claude Code's discovery logic:
|
|
4
|
+
* 1. CLAUDE.md in current directory or parents
|
|
5
|
+
* 2. .github/instructions/ *.md (checking main ones)
|
|
6
|
+
* 3. .cursor/rules/ *.md
|
|
7
|
+
* 4. .claude/rules/ *.md
|
|
8
|
+
*/
|
|
9
|
+
export declare function findClaudeRules(startDir?: string): string | 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": "1.0.
|
|
5
|
+
"version": "1.0.10",
|
|
6
6
|
"author": "agnusdei1207",
|
|
7
7
|
"license": "MIT",
|
|
8
8
|
"repository": {
|