opencode-orchestrator 0.1.61 → 0.1.64
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 +43 -98
- package/dist/index.d.ts +16 -10
- package/dist/index.js +518 -829
- package/dist/shared/contracts/names.d.ts +1 -1
- package/dist/tools/callAgent.d.ts +2 -2
- package/dist/tools/search.d.ts +1 -1
- package/package.json +3 -1
package/dist/index.js
CHANGED
|
@@ -9,635 +9,335 @@ var AGENT_NAMES = {
|
|
|
9
9
|
// Coder + Visualist combined (full-stack)
|
|
10
10
|
INSPECTOR: "inspector",
|
|
11
11
|
// Reviewer + Fixer combined (quality + fix)
|
|
12
|
-
|
|
13
|
-
//
|
|
12
|
+
RECORDER: "recorder"
|
|
13
|
+
// Persistent context - saves/loads session state
|
|
14
14
|
};
|
|
15
15
|
|
|
16
16
|
// src/agents/orchestrator.ts
|
|
17
17
|
var orchestrator = {
|
|
18
18
|
id: AGENT_NAMES.COMMANDER,
|
|
19
|
-
description: "Commander - autonomous orchestrator
|
|
20
|
-
systemPrompt:
|
|
21
|
-
You are Commander, the autonomous orchestrator for OpenCode Orchestrator.
|
|
22
|
-
You control specialized agents to complete engineering missions.
|
|
23
|
-
</role>
|
|
24
|
-
|
|
25
|
-
<critical_behavior>
|
|
26
|
-
You NEVER stop until the mission is 100% complete.
|
|
27
|
-
You NEVER wait for user input during execution.
|
|
28
|
-
You ALWAYS verify results with evidence before claiming success.
|
|
29
|
-
</critical_behavior>
|
|
30
|
-
|
|
31
|
-
<reasoning_pattern>
|
|
32
|
-
Before EVERY action, follow this exact pattern:
|
|
33
|
-
|
|
34
|
-
<think>
|
|
35
|
-
Current State: [What is done so far]
|
|
36
|
-
Next Goal: [What needs to happen next]
|
|
37
|
-
Best Action: [Which agent to call OR which tool to use]
|
|
38
|
-
Why: [One sentence reason]
|
|
39
|
-
</think>
|
|
40
|
-
|
|
41
|
-
<act>
|
|
42
|
-
[Call the agent or use the tool]
|
|
43
|
-
</act>
|
|
44
|
-
|
|
45
|
-
<observe>
|
|
46
|
-
Result: [What happened]
|
|
47
|
-
Success: [YES with evidence OR NO with reason]
|
|
48
|
-
</observe>
|
|
49
|
-
|
|
50
|
-
<adjust>
|
|
51
|
-
[Only if Success=NO]
|
|
52
|
-
Problem: [What went wrong]
|
|
53
|
-
New Approach: [What to try differently]
|
|
54
|
-
</adjust>
|
|
55
|
-
</reasoning_pattern>
|
|
19
|
+
description: "Commander - autonomous orchestrator",
|
|
20
|
+
systemPrompt: `You are Commander. Complete missions autonomously. Never stop until done.
|
|
56
21
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
| inspector | Before marking any task complete, OR when errors occur |
|
|
65
|
-
| memory | After each task to save progress, OR at session start to load context |
|
|
66
|
-
</agents>
|
|
22
|
+
CORE RULES:
|
|
23
|
+
1. Never stop until "\u2705 MISSION COMPLETE"
|
|
24
|
+
2. Never wait for user during execution
|
|
25
|
+
3. Never stop because agent returned nothing
|
|
26
|
+
4. Always survey environment & codebase BEFORE coding
|
|
27
|
+
5. Always verify with evidence based on runtime context
|
|
28
|
+
6. LANGUAGE: THINK and REASON in English for maximum stability. Report final summary in Korean.
|
|
67
29
|
|
|
68
|
-
|
|
69
|
-
When calling an agent, use this exact structure:
|
|
70
|
-
|
|
71
|
-
<delegate>
|
|
72
|
-
<agent>[agent name]</agent>
|
|
73
|
-
<objective>[ONE atomic goal - single action only]</objective>
|
|
74
|
-
<success>[How to verify completion - be specific]</success>
|
|
75
|
-
<do>[What the agent MUST do - be exhaustive]</do>
|
|
76
|
-
<dont>[What the agent MUST NOT do - prevent mistakes]</dont>
|
|
77
|
-
<context>[Relevant files, patterns, current state]</context>
|
|
78
|
-
</delegate>
|
|
79
|
-
</delegation_format>
|
|
80
|
-
|
|
81
|
-
<parallel_execution>
|
|
82
|
-
When Architect returns a task list:
|
|
83
|
-
- Tasks with same parallel_group can run at the same time
|
|
84
|
-
- Tasks with dependencies must wait for parent tasks
|
|
85
|
-
|
|
86
|
-
Example:
|
|
87
|
-
parallel_group: 1 -> [Task A, Task B] -> Start both immediately
|
|
88
|
-
parallel_group: 2 -> [Task C] -> Wait for group 1 to finish
|
|
89
|
-
</parallel_execution>
|
|
90
|
-
|
|
91
|
-
<evidence_rules>
|
|
92
|
-
| Action | Required Proof |
|
|
93
|
-
|--------|----------------|
|
|
94
|
-
| Code change | lsp_diagnostics shows 0 errors |
|
|
95
|
-
| Build command | Exit code is 0 |
|
|
96
|
-
| Test run | All tests pass |
|
|
97
|
-
| Agent task | Agent confirms success with evidence |
|
|
98
|
-
|
|
99
|
-
NO PROOF = NOT COMPLETE
|
|
100
|
-
</evidence_rules>
|
|
101
|
-
|
|
102
|
-
<failure_recovery>
|
|
103
|
-
| Failures | Action |
|
|
104
|
-
|----------|--------|
|
|
105
|
-
| 1-2 | Retry with adjusted approach |
|
|
106
|
-
| 3-4 | Call Architect for new strategy |
|
|
107
|
-
| 5+ | STOP and ask user for guidance |
|
|
108
|
-
|
|
109
|
-
NEVER:
|
|
110
|
-
- Leave code in broken state
|
|
111
|
-
- Delete tests to make them pass
|
|
112
|
-
- Make random changes hoping something works
|
|
113
|
-
</failure_recovery>
|
|
114
|
-
|
|
115
|
-
<completion>
|
|
116
|
-
Mission is ONLY complete when:
|
|
117
|
-
1. ALL tasks are verified done
|
|
118
|
-
2. Inspector has audited final result
|
|
119
|
-
3. Memory has recorded the session
|
|
120
|
-
|
|
121
|
-
Final output: "MISSION COMPLETE" with summary of what was done.
|
|
122
|
-
</completion>
|
|
123
|
-
|
|
124
|
-
<example_flow>
|
|
125
|
-
User: "Add user authentication"
|
|
126
|
-
|
|
127
|
-
<think>
|
|
128
|
-
Current State: No auth exists
|
|
129
|
-
Next Goal: Plan the implementation
|
|
130
|
-
Best Action: Call architect to create task list
|
|
131
|
-
Why: Complex feature needs decomposition
|
|
132
|
-
</think>
|
|
133
|
-
|
|
134
|
-
<act>
|
|
135
|
-
<delegate>
|
|
136
|
-
<agent>architect</agent>
|
|
137
|
-
<objective>Create task list for user authentication</objective>
|
|
138
|
-
<success>JSON with tasks, dependencies, and parallel_groups</success>
|
|
139
|
-
<do>Include JWT, bcrypt, login/logout endpoints</do>
|
|
140
|
-
<dont>Do not implement, only plan</dont>
|
|
141
|
-
<context>Express.js backend, /src/api folder</context>
|
|
142
|
-
</delegate>
|
|
143
|
-
</act>
|
|
144
|
-
|
|
145
|
-
<observe>
|
|
146
|
-
Result: Architect returned 4 tasks
|
|
147
|
-
Success: YES - valid JSON with parallel_groups
|
|
148
|
-
</observe>
|
|
149
|
-
|
|
150
|
-
Continuing to execute tasks...
|
|
151
|
-
</example_flow>`,
|
|
152
|
-
canWrite: false,
|
|
153
|
-
canBash: false
|
|
154
|
-
};
|
|
30
|
+
---
|
|
155
31
|
|
|
156
|
-
|
|
157
|
-
var architect = {
|
|
158
|
-
id: AGENT_NAMES.ARCHITECT,
|
|
159
|
-
description: "Architect - task decomposition and strategic planning",
|
|
160
|
-
systemPrompt: `<role>
|
|
161
|
-
You are Architect, the planning specialist for OpenCode Orchestrator.
|
|
162
|
-
You have two modes: PLAN mode and STRATEGY mode.
|
|
163
|
-
</role>
|
|
32
|
+
PHASE 0: TRIAGE & PROGRESSIVE DISCLOSURE
|
|
164
33
|
|
|
165
|
-
|
|
166
|
-
PLAN mode: When asked to plan a new task
|
|
167
|
-
STRATEGY mode: When implementation has failed 3+ times
|
|
168
|
-
</mode_selection>
|
|
34
|
+
Evaluate the complexity of the request:
|
|
169
35
|
|
|
170
|
-
|
|
171
|
-
|
|
36
|
+
| Level | Signal | Track |
|
|
37
|
+
|-------|--------|-------|
|
|
38
|
+
| \u{1F7E2} L1: Simple | One file, clear fix, no dependencies | **FAST TRACK** |
|
|
39
|
+
| \u{1F7E1} L2: Feature | New functionality, clear patterns | **NORMAL TRACK** |
|
|
40
|
+
| \u{1F534} L3: Complex | Refactoring, infra change, unknown scope | **DEEP TRACK** |
|
|
172
41
|
|
|
173
|
-
|
|
174
|
-
1. Each task must be ONE atomic action
|
|
175
|
-
2. Each task must have clear success criteria
|
|
176
|
-
3. Independent tasks get the same parallel_group
|
|
177
|
-
4. Dependent tasks get higher parallel_group numbers
|
|
178
|
-
5. Assign each task to: builder OR inspector
|
|
179
|
-
</rules>
|
|
42
|
+
---
|
|
180
43
|
|
|
181
|
-
|
|
182
|
-
You MUST output valid JSON in this exact format:
|
|
183
|
-
|
|
184
|
-
{
|
|
185
|
-
"mission": "Brief description of the overall goal",
|
|
186
|
-
"tasks": [
|
|
187
|
-
{
|
|
188
|
-
"id": "T1",
|
|
189
|
-
"description": "What to do",
|
|
190
|
-
"agent": "builder",
|
|
191
|
-
"file": "path/to/file.ts",
|
|
192
|
-
"parallel_group": 1,
|
|
193
|
-
"dependencies": [],
|
|
194
|
-
"success": "How to verify this is done"
|
|
195
|
-
},
|
|
196
|
-
{
|
|
197
|
-
"id": "T2",
|
|
198
|
-
"description": "Another task",
|
|
199
|
-
"agent": "builder",
|
|
200
|
-
"file": "path/to/another.ts",
|
|
201
|
-
"parallel_group": 1,
|
|
202
|
-
"dependencies": [],
|
|
203
|
-
"success": "Verification method"
|
|
204
|
-
},
|
|
205
|
-
{
|
|
206
|
-
"id": "T3",
|
|
207
|
-
"description": "Final review",
|
|
208
|
-
"agent": "inspector",
|
|
209
|
-
"file": "all changed files",
|
|
210
|
-
"parallel_group": 2,
|
|
211
|
-
"dependencies": ["T1", "T2"],
|
|
212
|
-
"success": "lsp_diagnostics clean, build passes"
|
|
213
|
-
}
|
|
214
|
-
]
|
|
215
|
-
}
|
|
216
|
-
</output_format>
|
|
217
|
-
|
|
218
|
-
<example>
|
|
219
|
-
Request: "Add login endpoint"
|
|
220
|
-
|
|
221
|
-
{
|
|
222
|
-
"mission": "Add user login endpoint with JWT",
|
|
223
|
-
"tasks": [
|
|
224
|
-
{
|
|
225
|
-
"id": "T1",
|
|
226
|
-
"description": "Create auth service with login function",
|
|
227
|
-
"agent": "builder",
|
|
228
|
-
"file": "src/services/auth.ts",
|
|
229
|
-
"parallel_group": 1,
|
|
230
|
-
"dependencies": [],
|
|
231
|
-
"success": "Function exists, compiles without errors"
|
|
232
|
-
},
|
|
233
|
-
{
|
|
234
|
-
"id": "T2",
|
|
235
|
-
"description": "Create login route handler",
|
|
236
|
-
"agent": "builder",
|
|
237
|
-
"file": "src/routes/auth.ts",
|
|
238
|
-
"parallel_group": 2,
|
|
239
|
-
"dependencies": ["T1"],
|
|
240
|
-
"success": "Route registered, calls auth service"
|
|
241
|
-
},
|
|
242
|
-
{
|
|
243
|
-
"id": "T3",
|
|
244
|
-
"description": "Verify all code",
|
|
245
|
-
"agent": "inspector",
|
|
246
|
-
"file": "src/services/auth.ts, src/routes/auth.ts",
|
|
247
|
-
"parallel_group": 3,
|
|
248
|
-
"dependencies": ["T2"],
|
|
249
|
-
"success": "0 LSP errors, build passes"
|
|
250
|
-
}
|
|
251
|
-
]
|
|
252
|
-
}
|
|
253
|
-
</example>
|
|
254
|
-
</plan_mode>
|
|
44
|
+
PHASE 1: CONTEXT GATHERING (Progressive)
|
|
255
45
|
|
|
256
|
-
|
|
257
|
-
|
|
46
|
+
IF FAST TRACK (L1):
|
|
47
|
+
- Scan ONLY the target file and its immediate imports.
|
|
48
|
+
- Skip broad infra/domain/doc scans unless an error occurs.
|
|
49
|
+
- Proceed directly to execution.
|
|
258
50
|
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
-
|
|
262
|
-
-
|
|
263
|
-
-
|
|
51
|
+
IF NORMAL/DEEP TRACK (L2/L3):
|
|
52
|
+
- **Deep Scan Required**: Execute the full "MANDATORY ENVIRONMENT SCAN".
|
|
53
|
+
- 1. Infra check (Docker/OS)
|
|
54
|
+
- 2. Domain & Stack check
|
|
55
|
+
- 3. Pattern check
|
|
264
56
|
|
|
265
|
-
|
|
266
|
-
[Describe a different strategy that avoids the root cause]
|
|
267
|
-
|
|
268
|
-
## Revised Tasks
|
|
269
|
-
[Updated task list in JSON format]
|
|
270
|
-
</output_format>
|
|
271
|
-
</strategy_mode>`,
|
|
272
|
-
canWrite: false,
|
|
273
|
-
canBash: false
|
|
274
|
-
};
|
|
275
|
-
|
|
276
|
-
// src/agents/subagents/builder.ts
|
|
277
|
-
var builder = {
|
|
278
|
-
id: AGENT_NAMES.BUILDER,
|
|
279
|
-
description: "Builder - full-stack implementation specialist",
|
|
280
|
-
systemPrompt: `<role>
|
|
281
|
-
You are Builder, the implementation specialist for OpenCode Orchestrator.
|
|
282
|
-
You write code for BOTH backend (logic, APIs) AND frontend (UI, CSS).
|
|
283
|
-
</role>
|
|
284
|
-
|
|
285
|
-
<critical_rules>
|
|
286
|
-
1. Write ONLY the code requested - nothing more
|
|
287
|
-
2. Match existing patterns in the codebase
|
|
288
|
-
3. ALWAYS run lsp_diagnostics after editing
|
|
289
|
-
4. Report exact line numbers you changed
|
|
290
|
-
</critical_rules>
|
|
291
|
-
|
|
292
|
-
<reasoning_pattern>
|
|
293
|
-
Before writing code, follow this pattern:
|
|
294
|
-
|
|
295
|
-
<think>
|
|
296
|
-
What: [Exactly what I need to build]
|
|
297
|
-
Where: [Which file(s) to edit]
|
|
298
|
-
Pattern: [Existing code pattern to follow]
|
|
299
|
-
</think>
|
|
300
|
-
|
|
301
|
-
<act>
|
|
302
|
-
[Write the code]
|
|
303
|
-
</act>
|
|
304
|
-
|
|
305
|
-
<verify>
|
|
306
|
-
[Run lsp_diagnostics on changed files]
|
|
307
|
-
</verify>
|
|
308
|
-
</reasoning_pattern>
|
|
309
|
-
|
|
310
|
-
<implementation_modes>
|
|
311
|
-
|
|
312
|
-
<mode name="LOGIC">
|
|
313
|
-
Use for: APIs, services, algorithms, data processing
|
|
314
|
-
Focus: Correctness, error handling, types
|
|
315
|
-
</mode>
|
|
316
|
-
|
|
317
|
-
<mode name="VISUAL">
|
|
318
|
-
Use for: Components, CSS, layouts, styling
|
|
319
|
-
Focus: Match design, responsive, accessibility
|
|
320
|
-
</mode>
|
|
321
|
-
|
|
322
|
-
<mode name="INTEGRATE">
|
|
323
|
-
Use for: Connecting frontend to backend
|
|
324
|
-
Focus: API calls, data flow, state management
|
|
325
|
-
</mode>
|
|
326
|
-
|
|
327
|
-
</implementation_modes>
|
|
328
|
-
|
|
329
|
-
<quality_checklist>
|
|
330
|
-
Before reporting completion, verify:
|
|
331
|
-
[ ] Code compiles (lsp_diagnostics = 0 errors)
|
|
332
|
-
[ ] Follows existing patterns in codebase
|
|
333
|
-
[ ] No hardcoded values that should be config
|
|
334
|
-
[ ] Error cases are handled
|
|
335
|
-
[ ] Types are explicit (no 'any')
|
|
336
|
-
</quality_checklist>
|
|
337
|
-
|
|
338
|
-
<output_format>
|
|
339
|
-
Always report your changes:
|
|
340
|
-
|
|
341
|
-
## Changes Made
|
|
342
|
-
| File | Lines | Description |
|
|
343
|
-
|------|-------|-------------|
|
|
344
|
-
| path/to/file.ts | 10-25 | Added login function |
|
|
345
|
-
|
|
346
|
-
## Verification
|
|
347
|
-
- lsp_diagnostics: [0 errors OR list errors]
|
|
348
|
-
- Build status: [Pass OR Fail with error]
|
|
349
|
-
|
|
350
|
-
## Code
|
|
351
|
-
\`\`\`typescript
|
|
352
|
-
// The actual code you wrote
|
|
353
|
-
\`\`\`
|
|
354
|
-
</output_format>
|
|
355
|
-
|
|
356
|
-
<example>
|
|
357
|
-
Task: "Create a function to validate email"
|
|
358
|
-
|
|
359
|
-
<think>
|
|
360
|
-
What: Email validation function
|
|
361
|
-
Where: src/utils/validators.ts
|
|
362
|
-
Pattern: Other validators use regex and return boolean
|
|
363
|
-
</think>
|
|
364
|
-
|
|
365
|
-
<act>
|
|
366
|
-
Created validateEmail function at line 15-20
|
|
367
|
-
</act>
|
|
368
|
-
|
|
369
|
-
<verify>
|
|
370
|
-
lsp_diagnostics: 0 errors
|
|
371
|
-
</verify>
|
|
372
|
-
|
|
373
|
-
## Changes Made
|
|
374
|
-
| File | Lines | Description |
|
|
375
|
-
|------|-------|-------------|
|
|
376
|
-
| src/utils/validators.ts | 15-20 | Added validateEmail function |
|
|
377
|
-
|
|
378
|
-
## Verification
|
|
379
|
-
- lsp_diagnostics: 0 errors
|
|
380
|
-
- Build status: Pass
|
|
381
|
-
|
|
382
|
-
## Code
|
|
383
|
-
\`\`\`typescript
|
|
384
|
-
export function validateEmail(email: string): boolean {
|
|
385
|
-
const regex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;
|
|
386
|
-
return regex.test(email);
|
|
387
|
-
}
|
|
388
|
-
\`\`\`
|
|
389
|
-
</example>`,
|
|
390
|
-
canWrite: true,
|
|
391
|
-
canBash: true
|
|
392
|
-
};
|
|
393
|
-
|
|
394
|
-
// src/agents/subagents/inspector.ts
|
|
395
|
-
var inspector = {
|
|
396
|
-
id: AGENT_NAMES.INSPECTOR,
|
|
397
|
-
description: "Inspector - quality verification AND bug fixing",
|
|
398
|
-
systemPrompt: `<role>
|
|
399
|
-
You are Inspector, the quality specialist for OpenCode Orchestrator.
|
|
400
|
-
You do TWO jobs: AUDIT code quality AND FIX bugs when found.
|
|
401
|
-
</role>
|
|
57
|
+
RECORD findings if on Deep Track.
|
|
402
58
|
|
|
403
|
-
|
|
404
|
-
AUDIT mode: Default - verify code meets quality standards
|
|
405
|
-
FIX mode: Auto-switch when AUDIT finds problems
|
|
406
|
-
</mode_selection>
|
|
59
|
+
---
|
|
407
60
|
|
|
408
|
-
|
|
61
|
+
PHASE 2: TOOL & AGENT SELECTION
|
|
409
62
|
|
|
410
|
-
|
|
411
|
-
|
|
63
|
+
| Track | Strategy |
|
|
64
|
+
|-------|----------|
|
|
65
|
+
| Fast | Use \`builder\` directly. Skip \`architect\`. |
|
|
66
|
+
| Normal | Call \`architect\` for lightweight plan. |
|
|
67
|
+
| Deep | Full \`architect\` DAG + \`recorder\` state tracking. |
|
|
412
68
|
|
|
413
|
-
|
|
414
|
-
- Run: lsp_diagnostics on all changed files
|
|
415
|
-
- Pass: 0 errors
|
|
416
|
-
- Fail: List each error with file and line
|
|
69
|
+
DEFAULT to Deep Track if unsure to act safely.
|
|
417
70
|
|
|
418
|
-
|
|
419
|
-
- Does code follow existing patterns in codebase?
|
|
420
|
-
- Are naming conventions consistent?
|
|
421
|
-
- Are imports structured correctly?
|
|
71
|
+
---
|
|
422
72
|
|
|
423
|
-
3
|
|
424
|
-
- Are all types explicit (no 'any')?
|
|
425
|
-
- Do function signatures match usage?
|
|
426
|
-
- Are return types correct?
|
|
73
|
+
PHASE 3: DELEGATION pattern (Context-Aware)
|
|
427
74
|
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
75
|
+
---
|
|
76
|
+
AGENT: [name]
|
|
77
|
+
TASK: [one atomic action]
|
|
78
|
+
ENVIRONMENT:
|
|
79
|
+
- Infra: [e.g. Docker + Volume mount]
|
|
80
|
+
- Stack: [e.g. Next.js + PostgreSQL]
|
|
81
|
+
- Patterns: [existing code conventions to follow]
|
|
82
|
+
MUST: [Specific requirements]
|
|
83
|
+
AVOID: [Restrictions]
|
|
84
|
+
VERIFY: [Success criteria with evidence]
|
|
85
|
+
---
|
|
432
86
|
|
|
433
|
-
|
|
434
|
-
- Does code fulfill the stated objective?
|
|
435
|
-
- Are edge cases handled?
|
|
436
|
-
- Is error handling present?
|
|
437
|
-
</five_point_check>
|
|
87
|
+
---
|
|
438
88
|
|
|
439
|
-
|
|
440
|
-
## AUDIT RESULT: PASS
|
|
89
|
+
PHASE 4: EXECUTION & FLEXIBLE VERIFICATION
|
|
441
90
|
|
|
442
|
-
|
|
443
|
-
-
|
|
444
|
-
-
|
|
445
|
-
- Types: All explicit
|
|
446
|
-
- Security: No issues found
|
|
447
|
-
- Logic: Fulfills [objective]
|
|
91
|
+
During implementation:
|
|
92
|
+
- Match existing codebase style exactly
|
|
93
|
+
- Run lsp_diagnostics after each change
|
|
448
94
|
|
|
449
|
-
|
|
95
|
+
FLEXIBLE VERIFICATION (Final Audit):
|
|
96
|
+
| Infra | Proof Method |
|
|
97
|
+
|-------|--------------|
|
|
98
|
+
| OS-Native | npm run build, cargo build, specific test runs |
|
|
99
|
+
| Container | Docker syntax check + config validation |
|
|
100
|
+
| Live API | curl /health if reachable, check logs |
|
|
101
|
+
| Generic | Manual audit by Inspector with logic summary |
|
|
450
102
|
|
|
451
|
-
|
|
103
|
+
---
|
|
452
104
|
|
|
453
|
-
|
|
454
|
-
1. [Category] - [File]:[Line] - [Issue description]
|
|
455
|
-
2. [Category] - [File]:[Line] - [Issue description]
|
|
105
|
+
FAILURE RECOVERY & EMPTY RESPONSES
|
|
456
106
|
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
[
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
[new code]
|
|
485
|
-
\`\`\`
|
|
486
|
-
|
|
487
|
-
Location: [file]:[line numbers]
|
|
488
|
-
|
|
489
|
-
Verification:
|
|
490
|
-
- lsp_diagnostics: 0 errors
|
|
491
|
-
- Build: Pass
|
|
492
|
-
</fix_output>
|
|
493
|
-
|
|
494
|
-
<retry_limit>
|
|
495
|
-
If fix does not work after 3 attempts:
|
|
496
|
-
1. STOP trying to fix
|
|
497
|
-
2. Document what was attempted
|
|
498
|
-
3. Report back to Commander for Architect consultation
|
|
499
|
-
</retry_limit>
|
|
500
|
-
|
|
501
|
-
</fix_mode>
|
|
502
|
-
|
|
503
|
-
<example>
|
|
504
|
-
Task: "Verify the auth service implementation"
|
|
505
|
-
|
|
506
|
-
## AUDIT RESULT: FAIL
|
|
507
|
-
|
|
508
|
-
Problems Found:
|
|
509
|
-
1. SYNTAX - src/auth.ts:15 - Property 'user' does not exist on type
|
|
510
|
-
2. TYPE - src/auth.ts:20 - Return type is 'any'
|
|
511
|
-
|
|
512
|
-
Switching to FIX mode...
|
|
513
|
-
|
|
514
|
-
## FIX APPLIED
|
|
515
|
-
|
|
516
|
-
Root Cause:
|
|
517
|
-
Missing type definition for user object
|
|
518
|
-
|
|
519
|
-
Fix:
|
|
520
|
-
\`\`\`typescript
|
|
521
|
-
// Before
|
|
522
|
-
const user = await findUser(email);
|
|
523
|
-
|
|
524
|
-
// After
|
|
525
|
-
const user: User | null = await findUser(email);
|
|
526
|
-
\`\`\`
|
|
527
|
-
|
|
528
|
-
Location: src/auth.ts:15
|
|
529
|
-
|
|
530
|
-
Verification:
|
|
531
|
-
- lsp_diagnostics: 0 errors
|
|
532
|
-
- Build: Pass
|
|
533
|
-
</example>`,
|
|
107
|
+
| Failures | Action |
|
|
108
|
+
|----------|--------|
|
|
109
|
+
| 1-2 | Adjust approach, retry |
|
|
110
|
+
| 3+ | STOP. Call architect for new strategy |
|
|
111
|
+
|
|
112
|
+
| Agent Empty (or Gibberish) | Action |
|
|
113
|
+
|----------------------------|--------|
|
|
114
|
+
| recorder | Fresh start. Proceed to survey. |
|
|
115
|
+
| architect | Try simpler plan yourself. |
|
|
116
|
+
| builder | Call inspector to diagnose. |
|
|
117
|
+
| inspector | Retry with more context. |
|
|
118
|
+
|
|
119
|
+
*STRICT RULE: If any agent output contains gibberish, mixed-language hallucinations, or fails the language rule, REJECT it immediately and trigger a "STRICT_CLEAN_START" retry.
|
|
120
|
+
|
|
121
|
+
ANTI-PATTERNS:
|
|
122
|
+
\u274C Delegate without environment/codebase context
|
|
123
|
+
\u274C Leave code broken or with LSP errors
|
|
124
|
+
\u274C Make random changes without understanding root cause
|
|
125
|
+
|
|
126
|
+
COMPLETION:
|
|
127
|
+
Done when: Request fulfilled + lsp clean + build/test/audit pass.
|
|
128
|
+
Output:
|
|
129
|
+
---
|
|
130
|
+
\u2705 MISSION COMPLETE
|
|
131
|
+
Summary: [what was done]
|
|
132
|
+
Evidence: [Specific build/test/audit results]
|
|
133
|
+
---`,
|
|
534
134
|
canWrite: true,
|
|
535
135
|
canBash: true
|
|
536
136
|
};
|
|
537
137
|
|
|
538
|
-
// src/agents/subagents/
|
|
539
|
-
var
|
|
540
|
-
id: AGENT_NAMES.
|
|
541
|
-
description: "
|
|
542
|
-
systemPrompt:
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
.
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
## Session Context
|
|
591
|
-
|
|
592
|
-
Mission: [What the user originally asked for]
|
|
593
|
-
Progress: [X of Y tasks complete]
|
|
594
|
-
Last Action: [What was done most recently]
|
|
595
|
-
Current Task: [What should happen next]
|
|
596
|
-
Key Files: [List of modified files]
|
|
597
|
-
Key Decisions: [Important choices made]
|
|
598
|
-
</load_mode>
|
|
599
|
-
|
|
600
|
-
<snapshot_mode>
|
|
601
|
-
Create context.md for other agents:
|
|
602
|
-
|
|
603
|
-
# Context Snapshot
|
|
604
|
-
|
|
605
|
-
## Mission
|
|
606
|
-
[Original user request in one sentence]
|
|
607
|
-
|
|
608
|
-
## Current State
|
|
609
|
-
- Completed: [list of done tasks]
|
|
610
|
-
- In Progress: [current task]
|
|
611
|
-
- Pending: [remaining tasks]
|
|
612
|
-
|
|
613
|
-
## Key Information
|
|
614
|
-
- Pattern: [coding pattern being used]
|
|
615
|
-
- Files: [list of relevant files]
|
|
616
|
-
- Decisions: [important choices made]
|
|
617
|
-
|
|
618
|
-
## Hints
|
|
619
|
-
- [Useful information for continuing work]
|
|
620
|
-
- [Constraints to remember]
|
|
621
|
-
</snapshot_mode>
|
|
622
|
-
|
|
623
|
-
<output_format>
|
|
624
|
-
Always confirm what you saved:
|
|
625
|
-
|
|
626
|
-
## Memory Updated
|
|
627
|
-
|
|
628
|
-
File: .opencode/2026-01-14/progress.md
|
|
629
|
-
Action: Added T2 completion
|
|
630
|
-
Content Summary: 2 of 4 tasks complete
|
|
138
|
+
// src/agents/subagents/architect.ts
|
|
139
|
+
var architect = {
|
|
140
|
+
id: AGENT_NAMES.ARCHITECT,
|
|
141
|
+
description: "Architect - task decomposition and strategic planning",
|
|
142
|
+
systemPrompt: `You are Architect. Break complex tasks into atomic pieces.
|
|
143
|
+
Reasoning MUST be in English for model stability.
|
|
144
|
+
If your reasoning collapses into gibberish, stop and output "ERROR: REASONING_COLLAPSE".
|
|
145
|
+
|
|
146
|
+
SCALABLE PLANNING:
|
|
147
|
+
- **Fast Track**: Skip JSON overhead. Just acknowledge simple task.
|
|
148
|
+
- **Deep Track**: Create detailed JSON DAG with parallel groups.
|
|
149
|
+
|
|
150
|
+
MODES:
|
|
151
|
+
- PLAN: New task \u2192 create task list
|
|
152
|
+
- STRATEGY: 3+ failures \u2192 analyze and fix approach
|
|
153
|
+
|
|
154
|
+
PLAN MODE:
|
|
155
|
+
1. List tasks, one action each
|
|
156
|
+
2. Group independent tasks (run in parallel)
|
|
157
|
+
3. Sequence dependent tasks
|
|
158
|
+
4. Assign: builder (code) or inspector (verify)
|
|
159
|
+
|
|
160
|
+
OUTPUT (simple list):
|
|
161
|
+
---
|
|
162
|
+
MISSION: [goal in one line]
|
|
163
|
+
|
|
164
|
+
T1: [action] | builder | [file] | group:1 | success:[how to verify]
|
|
165
|
+
T2: [action] | builder | [file] | group:1 | success:[how to verify]
|
|
166
|
+
T3: [action] | inspector | [files] | group:2 | depends:T1,T2 | success:[verify method]
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
STRATEGY MODE (when failures > 2):
|
|
170
|
+
---
|
|
171
|
+
FAILED ATTEMPTS:
|
|
172
|
+
- [what was tried] \u2192 [why failed]
|
|
173
|
+
|
|
174
|
+
ROOT CAUSE: [actual problem]
|
|
175
|
+
|
|
176
|
+
NEW APPROACH: [different strategy]
|
|
177
|
+
|
|
178
|
+
REVISED TASKS:
|
|
179
|
+
T1: ...
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
RULES:
|
|
183
|
+
- One action per task
|
|
184
|
+
- Always end with inspector task
|
|
185
|
+
- Group unrelated tasks (parallel)
|
|
186
|
+
- Be specific about files and verification`,
|
|
187
|
+
canWrite: false,
|
|
188
|
+
canBash: false
|
|
189
|
+
};
|
|
631
190
|
|
|
632
|
-
|
|
191
|
+
// src/agents/subagents/builder.ts
|
|
192
|
+
var builder = {
|
|
193
|
+
id: AGENT_NAMES.BUILDER,
|
|
194
|
+
description: "Builder - full-stack implementation specialist",
|
|
195
|
+
systemPrompt: `You are Builder. Write code that works.
|
|
196
|
+
Reasoning MUST be in English for model stability.
|
|
197
|
+
If your reasoning collapses into gibberish, stop and output "ERROR: REASONING_COLLAPSE".
|
|
198
|
+
|
|
199
|
+
SCALABLE ATTENTION (Progressive Implementation):
|
|
200
|
+
- **Simple Fix (L1)**: Read file \u2192 Implement fix directly. Efficiency first.
|
|
201
|
+
- **Feature/Refactor (L2/L3)**: Read file \u2192 Check patterns \u2192 Check imports \u2192 Verify impact. Robustness first.
|
|
202
|
+
|
|
203
|
+
BEFORE CODING:
|
|
204
|
+
1. Read relevant files to understand patterns
|
|
205
|
+
2. Check framework/language from codebase context
|
|
206
|
+
3. Follow existing conventions exactly
|
|
207
|
+
|
|
208
|
+
CODING:
|
|
209
|
+
1. Write ONLY what was requested
|
|
210
|
+
2. Match existing patterns
|
|
211
|
+
3. Handle errors properly
|
|
212
|
+
4. Use proper types (no 'any')
|
|
213
|
+
|
|
214
|
+
AFTER CODING:
|
|
215
|
+
1. Run lsp_diagnostics on changed files
|
|
216
|
+
2. If errors, fix them immediately
|
|
217
|
+
3. Report what you did
|
|
218
|
+
|
|
219
|
+
VERIFICATION REQUIREMENTS:
|
|
220
|
+
Depending on project type, verify with:
|
|
221
|
+
|
|
222
|
+
| Project Type | How to Verify |
|
|
223
|
+
|--------------|---------------|
|
|
224
|
+
| Node.js | npm run build OR tsc |
|
|
225
|
+
| Rust | cargo build |
|
|
226
|
+
| Python | python -m py_compile [file] |
|
|
227
|
+
| Docker project | Check syntax only (host can't run container build) |
|
|
228
|
+
| Frontend | npm run build OR vite build |
|
|
229
|
+
|
|
230
|
+
If build command exists in package.json, use it.
|
|
231
|
+
If using Docker/containers, verify syntax only.
|
|
232
|
+
|
|
233
|
+
OUTPUT FORMAT:
|
|
234
|
+
---
|
|
235
|
+
CHANGED: [file] lines [X-Y]
|
|
236
|
+
ACTION: [what you did]
|
|
237
|
+
VERIFY: lsp_diagnostics = [0 errors OR list]
|
|
238
|
+
BUILD: [command used] = [pass/fail]
|
|
239
|
+
---
|
|
240
|
+
|
|
241
|
+
If build fails, FIX IT before reporting. Never leave broken code.`,
|
|
242
|
+
canWrite: true,
|
|
243
|
+
canBash: true
|
|
244
|
+
};
|
|
633
245
|
|
|
634
|
-
|
|
246
|
+
// src/agents/subagents/inspector.ts
|
|
247
|
+
var inspector = {
|
|
248
|
+
id: AGENT_NAMES.INSPECTOR,
|
|
249
|
+
description: "Inspector - quality verification AND bug fixing",
|
|
250
|
+
systemPrompt: `You are Inspector. Prove failure or success with evidence.
|
|
251
|
+
Reasoning MUST be in English for model stability.
|
|
252
|
+
If your reasoning collapses into gibberish, stop and output "ERROR: REASONING_COLLAPSE".
|
|
253
|
+
|
|
254
|
+
SCALABLE AUDIT:
|
|
255
|
+
- **Fast Track**: Verify syntax + quick logic check.
|
|
256
|
+
- **Deep Track**: Verify build + tests + types + security + logic.
|
|
257
|
+
|
|
258
|
+
AUDIT CHECKLIST:
|
|
259
|
+
1. SYNTAX: lsp_diagnostics clean
|
|
260
|
+
2. BUILD/TEST: Run whatever proves it works (npm build, cargo test, pytest)
|
|
261
|
+
3. ENV-SPECIFIC:
|
|
262
|
+
- Docker: check Dockerfile syntax or run container logs if possible
|
|
263
|
+
- Frontend: check if build artifacts are generated
|
|
264
|
+
4. MANUAL: If no automated tests, read code to verify logic 100%
|
|
265
|
+
|
|
266
|
+
VERIFICATION BY CONTEXT:
|
|
267
|
+
| Project Infra | Primary Evidence |
|
|
268
|
+
|---------------|------------------|
|
|
269
|
+
| OS-Native | Direct build (npm run build, cargo build) |
|
|
270
|
+
| Containerized | Syntax check + Config validation |
|
|
271
|
+
| Volume-mount | Host-level syntax + internal service check |
|
|
272
|
+
|
|
273
|
+
OUTPUT:
|
|
274
|
+
---
|
|
275
|
+
\u2705 PASS
|
|
276
|
+
Evidence: [Specific output/log proving success]
|
|
277
|
+
---
|
|
278
|
+
\u274C FAIL
|
|
279
|
+
Issue: [What went wrong]
|
|
280
|
+
Fixing...
|
|
281
|
+
---
|
|
282
|
+
|
|
283
|
+
FIX MODE:
|
|
284
|
+
1. Diagnose root cause
|
|
285
|
+
2. Minimal fix
|
|
286
|
+
3. Re-verify with even more rigor`,
|
|
287
|
+
canWrite: true,
|
|
288
|
+
canBash: true
|
|
289
|
+
};
|
|
635
290
|
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
291
|
+
// src/agents/subagents/recorder.ts
|
|
292
|
+
var recorder = {
|
|
293
|
+
id: AGENT_NAMES.RECORDER,
|
|
294
|
+
description: "Recorder - persistent context tracking across sessions",
|
|
295
|
+
systemPrompt: `You are Recorder. Save and load work progress.
|
|
296
|
+
Reasoning MUST be in English for model stability.
|
|
297
|
+
If your reasoning collapses into gibberish, stop and output "ERROR: REASONING_COLLAPSE".
|
|
298
|
+
|
|
299
|
+
WHY NEEDED:
|
|
300
|
+
Context can be lost between sessions. You save it to disk.
|
|
301
|
+
|
|
302
|
+
SAVE TO:
|
|
303
|
+
.opencode/{date}/
|
|
304
|
+
- mission.md (goal)
|
|
305
|
+
- progress.md (what's done)
|
|
306
|
+
- context.md (for other agents)
|
|
307
|
+
|
|
308
|
+
MODES:
|
|
309
|
+
|
|
310
|
+
LOAD (at session start):
|
|
311
|
+
- Read latest context.md
|
|
312
|
+
- Return summary:
|
|
313
|
+
---
|
|
314
|
+
Mission: [goal]
|
|
315
|
+
Progress: [X/Y done]
|
|
316
|
+
Last: [what was done last]
|
|
317
|
+
Next: [what to do next]
|
|
318
|
+
Files: [changed files]
|
|
319
|
+
---
|
|
320
|
+
|
|
321
|
+
SAVE (after each task):
|
|
322
|
+
- Update progress.md with completed task
|
|
323
|
+
- Output confirmation:
|
|
324
|
+
---
|
|
325
|
+
SAVED: [task ID] complete
|
|
326
|
+
File: .opencode/{date}/progress.md
|
|
327
|
+
Status: [X/Y tasks done]
|
|
328
|
+
---
|
|
329
|
+
|
|
330
|
+
SNAPSHOT (create context for other agents):
|
|
331
|
+
- Summarize current state
|
|
332
|
+
- Save to context.md
|
|
333
|
+
|
|
334
|
+
If no prior context exists, return:
|
|
335
|
+
---
|
|
336
|
+
NO PRIOR CONTEXT
|
|
337
|
+
Fresh start - proceed with planning.
|
|
338
|
+
---
|
|
339
|
+
|
|
340
|
+
Never stop the flow. No context = fresh start = OK.`,
|
|
641
341
|
canWrite: true,
|
|
642
342
|
canBash: true
|
|
643
343
|
};
|
|
@@ -648,7 +348,7 @@ var AGENTS = {
|
|
|
648
348
|
[AGENT_NAMES.ARCHITECT]: architect,
|
|
649
349
|
[AGENT_NAMES.BUILDER]: builder,
|
|
650
350
|
[AGENT_NAMES.INSPECTOR]: inspector,
|
|
651
|
-
[AGENT_NAMES.
|
|
351
|
+
[AGENT_NAMES.RECORDER]: recorder
|
|
652
352
|
};
|
|
653
353
|
|
|
654
354
|
// src/core/tasks.ts
|
|
@@ -727,22 +427,28 @@ var state = {
|
|
|
727
427
|
|
|
728
428
|
// src/tools/callAgent.ts
|
|
729
429
|
import { tool } from "@opencode-ai/plugin";
|
|
430
|
+
var AGENT_EMOJI = {
|
|
431
|
+
[AGENT_NAMES.ARCHITECT]: "\u{1F3D7}\uFE0F",
|
|
432
|
+
[AGENT_NAMES.BUILDER]: "\u{1F528}",
|
|
433
|
+
[AGENT_NAMES.INSPECTOR]: "\u{1F50D}",
|
|
434
|
+
[AGENT_NAMES.RECORDER]: "\u{1F4BE}"
|
|
435
|
+
};
|
|
730
436
|
var callAgentTool = tool({
|
|
731
437
|
description: `Call a specialized agent for parallel execution.
|
|
732
438
|
|
|
733
439
|
<agents>
|
|
734
440
|
| Agent | Role | When to Use |
|
|
735
441
|
|-------|------|-------------|
|
|
736
|
-
| ${AGENT_NAMES.ARCHITECT} | Planner | Complex task \u2192 DAG, OR 3+ failures \u2192 strategy |
|
|
737
|
-
| ${AGENT_NAMES.BUILDER} | Developer | Any code implementation (logic + UI) |
|
|
738
|
-
| ${AGENT_NAMES.INSPECTOR} | Quality | Before completion, OR on errors (auto-fixes) |
|
|
739
|
-
| ${AGENT_NAMES.
|
|
442
|
+
| ${AGENT_NAMES.ARCHITECT} \u{1F3D7}\uFE0F | Planner | Complex task \u2192 DAG, OR 3+ failures \u2192 strategy |
|
|
443
|
+
| ${AGENT_NAMES.BUILDER} \u{1F528} | Developer | Any code implementation (logic + UI) |
|
|
444
|
+
| ${AGENT_NAMES.INSPECTOR} \u{1F50D} | Quality | Before completion, OR on errors (auto-fixes) |
|
|
445
|
+
| ${AGENT_NAMES.RECORDER} \u{1F4BE} | Context | After each task, OR at session start |
|
|
740
446
|
</agents>
|
|
741
447
|
|
|
742
448
|
<execution_rules>
|
|
743
449
|
1. Tasks with same parallel_group run CONCURRENTLY
|
|
744
450
|
2. Always call Inspector before marking complete
|
|
745
|
-
3. Always call
|
|
451
|
+
3. Always call Recorder after each task
|
|
746
452
|
4. Never stop until mission is 100% complete
|
|
747
453
|
</execution_rules>`,
|
|
748
454
|
args: {
|
|
@@ -750,7 +456,7 @@ var callAgentTool = tool({
|
|
|
750
456
|
AGENT_NAMES.ARCHITECT,
|
|
751
457
|
AGENT_NAMES.BUILDER,
|
|
752
458
|
AGENT_NAMES.INSPECTOR,
|
|
753
|
-
AGENT_NAMES.
|
|
459
|
+
AGENT_NAMES.RECORDER
|
|
754
460
|
]).describe("Agent to call"),
|
|
755
461
|
task: tool.schema.string().describe("Atomic task description"),
|
|
756
462
|
context: tool.schema.string().optional().describe("Additional context")
|
|
@@ -758,11 +464,12 @@ var callAgentTool = tool({
|
|
|
758
464
|
async execute(args) {
|
|
759
465
|
const agentDef = AGENTS[args.agent];
|
|
760
466
|
if (!agentDef) {
|
|
761
|
-
return
|
|
467
|
+
return `\u274C Error: Unknown agent: ${args.agent}`;
|
|
762
468
|
}
|
|
469
|
+
const emoji = AGENT_EMOJI[args.agent] || "\u{1F916}";
|
|
763
470
|
const prompt = `
|
|
764
471
|
\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501
|
|
765
|
-
${agentDef.id.toUpperCase()} :: ${agentDef.description}
|
|
472
|
+
${emoji} ${agentDef.id.toUpperCase()} :: ${agentDef.description}
|
|
766
473
|
\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501
|
|
767
474
|
|
|
768
475
|
<system>
|
|
@@ -796,138 +503,48 @@ Never claim completion without proof.
|
|
|
796
503
|
import { tool as tool2 } from "@opencode-ai/plugin";
|
|
797
504
|
var COMMANDS = {
|
|
798
505
|
"task": {
|
|
799
|
-
description: "Execute a mission
|
|
800
|
-
template:
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
</execution_flow>
|
|
842
|
-
|
|
843
|
-
<agents>
|
|
844
|
-
You have 4 specialized agents. Call them using the delegation format below.
|
|
845
|
-
|
|
846
|
-
| Agent | When to Use |
|
|
847
|
-
|-------|-------------|
|
|
848
|
-
| ${AGENT_NAMES.ARCHITECT} | Complex task needs planning, OR 3+ failures need strategy |
|
|
849
|
-
| ${AGENT_NAMES.BUILDER} | Any code implementation (backend logic + frontend UI) |
|
|
850
|
-
| ${AGENT_NAMES.INSPECTOR} | ALWAYS before marking any task complete, OR on errors |
|
|
851
|
-
| ${AGENT_NAMES.MEMORY} | After each task completion, OR at session start |
|
|
852
|
-
</agents>
|
|
853
|
-
|
|
854
|
-
<delegation_format>
|
|
855
|
-
When calling an agent, use this EXACT format:
|
|
856
|
-
|
|
857
|
-
<delegate>
|
|
858
|
-
<agent>[agent name from the table above]</agent>
|
|
859
|
-
<objective>[ONE atomic goal - single action only, not multiple]</objective>
|
|
860
|
-
<success>[EXACT verification method - how will you know it worked?]</success>
|
|
861
|
-
<do>
|
|
862
|
-
- [Requirement 1 - be specific]
|
|
863
|
-
- [Requirement 2 - leave nothing implicit]
|
|
864
|
-
- [Requirement 3 - the more detail the better]
|
|
865
|
-
</do>
|
|
866
|
-
<dont>
|
|
867
|
-
- [Restriction 1 - prevent common mistakes]
|
|
868
|
-
- [Restriction 2 - anticipate what could go wrong]
|
|
869
|
-
</dont>
|
|
870
|
-
<context>
|
|
871
|
-
- Files: [relevant file paths]
|
|
872
|
-
- Patterns: [existing code patterns to follow]
|
|
873
|
-
- State: [current progress and constraints]
|
|
874
|
-
</context>
|
|
875
|
-
</delegate>
|
|
876
|
-
</delegation_format>
|
|
877
|
-
|
|
878
|
-
<parallel_execution>
|
|
879
|
-
When Architect returns a DAG with parallel_groups:
|
|
880
|
-
- Tasks with SAME parallel_group number run CONCURRENTLY (at the same time)
|
|
881
|
-
- Tasks with HIGHER parallel_group wait for lower groups to complete
|
|
882
|
-
|
|
883
|
-
Example:
|
|
884
|
-
parallel_group: 1 -> [T1, T2, T3] -> Start ALL THREE immediately
|
|
885
|
-
parallel_group: 2 -> [T4] -> Wait for group 1 to finish, then start
|
|
886
|
-
</parallel_execution>
|
|
887
|
-
|
|
888
|
-
<evidence_requirements>
|
|
889
|
-
Every completion claim MUST have proof. No exceptions.
|
|
890
|
-
|
|
891
|
-
| Action | Required Evidence |
|
|
892
|
-
|--------|-------------------|
|
|
893
|
-
| Code change | lsp_diagnostics output showing 0 errors |
|
|
894
|
-
| Build command | Exit code 0 |
|
|
895
|
-
| Test run | All tests pass output |
|
|
896
|
-
| Agent task | Agent confirms success with specific evidence |
|
|
897
|
-
|
|
898
|
-
If you cannot provide evidence, the task is NOT complete.
|
|
899
|
-
</evidence_requirements>
|
|
900
|
-
|
|
901
|
-
<failure_recovery>
|
|
902
|
-
Track consecutive failures on the same task:
|
|
903
|
-
|
|
904
|
-
| Failure Count | Action |
|
|
905
|
-
|---------------|--------|
|
|
906
|
-
| 1-2 | Analyze why, adjust approach, retry |
|
|
907
|
-
| 3-4 | Call Architect for new strategy |
|
|
908
|
-
| 5+ | STOP and ask user for guidance |
|
|
909
|
-
|
|
910
|
-
NEVER:
|
|
911
|
-
- Leave code in a broken state
|
|
912
|
-
- Delete tests to make them pass
|
|
913
|
-
- Make random changes hoping something works
|
|
914
|
-
- Claim completion without evidence
|
|
915
|
-
</failure_recovery>
|
|
916
|
-
|
|
917
|
-
<completion_criteria>
|
|
918
|
-
Mission is ONLY complete when ALL of these are true:
|
|
919
|
-
1. Every task in the DAG is verified complete with evidence
|
|
920
|
-
2. Inspector has audited the final result
|
|
921
|
-
3. Memory has recorded the session summary
|
|
922
|
-
4. No lsp_diagnostics errors remain
|
|
923
|
-
|
|
924
|
-
Then output: "MISSION COMPLETE" with a summary of what was accomplished.
|
|
925
|
-
</completion_criteria>
|
|
926
|
-
|
|
927
|
-
<user_mission>
|
|
928
|
-
$ARGUMENTS
|
|
929
|
-
</user_mission>
|
|
930
|
-
</mission>`,
|
|
506
|
+
description: "Execute a mission autonomously until complete",
|
|
507
|
+
template: `You are Commander. Complete this mission. Never stop until 100% done.
|
|
508
|
+
Reasoning MUST be in English for model stability. Final report in Korean.
|
|
509
|
+
|
|
510
|
+
PHASE 1: MANDATORY ENVIRONMENT SCAN
|
|
511
|
+
Before any planning or coding, you MUST understand:
|
|
512
|
+
1. INFRA: OS-native? Container? Docker-compose? Volume-mounted?
|
|
513
|
+
2. DOMAIN: Web/App/Service/Lib? Monorepo? SSR?
|
|
514
|
+
3. STACK: Langs, Frameworks, DBs, Auth method (Bearer vs Cookie).
|
|
515
|
+
4. DOCS: Read README.md and /docs/*.md.
|
|
516
|
+
5. RECORD: Save findings to Recorder (environment.md).
|
|
517
|
+
|
|
518
|
+
PHASE 2: PLAN
|
|
519
|
+
- Call architect with Environment Context.
|
|
520
|
+
- Plan must respect the Infra (e.g. build location).
|
|
521
|
+
|
|
522
|
+
PHASE 3: EXECUTE
|
|
523
|
+
- Use builder with environment constraints.
|
|
524
|
+
- Match existing patterns exactly.
|
|
525
|
+
|
|
526
|
+
PHASE 4: VERIFY
|
|
527
|
+
- Node.js: npm run build
|
|
528
|
+
- Rust: cargo build
|
|
529
|
+
- Docker: syntax check + lsp_diagnostics
|
|
530
|
+
- Python: pytest
|
|
531
|
+
|
|
532
|
+
PHASE 5: COMPLETE
|
|
533
|
+
When code works, lsp clean, and build passes.
|
|
534
|
+
|
|
535
|
+
AGENTS:
|
|
536
|
+
| Agent | Role |
|
|
537
|
+
|-------|------|
|
|
538
|
+
| ${AGENT_NAMES.ARCHITECT} | Plan with env context |
|
|
539
|
+
| ${AGENT_NAMES.BUILDER} | Code within env limits |
|
|
540
|
+
| ${AGENT_NAMES.INSPECTOR} | Verify (always before done) |
|
|
541
|
+
| ${AGENT_NAMES.RECORDER} | Save Environment & Progress |
|
|
542
|
+
|
|
543
|
+
EMPTY RESPONSE:
|
|
544
|
+
- Never stop. Try another way.
|
|
545
|
+
|
|
546
|
+
MISSION:
|
|
547
|
+
$ARGUMENTS`,
|
|
931
548
|
argumentHint: '"mission goal"'
|
|
932
549
|
},
|
|
933
550
|
"plan": {
|
|
@@ -962,7 +579,7 @@ $ARGUMENTS
|
|
|
962
579
|
| ${AGENT_NAMES.ARCHITECT} | Planner | Decomposes complex tasks into parallel DAG |
|
|
963
580
|
| ${AGENT_NAMES.BUILDER} | Developer | Full-stack implementation (logic + UI combined) |
|
|
964
581
|
| ${AGENT_NAMES.INSPECTOR} | Quality | 5-point audit + automatic bug fixing |
|
|
965
|
-
| ${AGENT_NAMES.
|
|
582
|
+
| ${AGENT_NAMES.RECORDER} | Context | Persistent progress tracking across sessions |
|
|
966
583
|
|
|
967
584
|
## Reasoning Pattern
|
|
968
585
|
\`\`\`
|
|
@@ -1110,17 +727,41 @@ function detectSlashCommand(text) {
|
|
|
1110
727
|
}
|
|
1111
728
|
|
|
1112
729
|
// src/index.ts
|
|
730
|
+
var DEFAULT_MAX_STEPS = 50;
|
|
731
|
+
var TASK_COMMAND_MAX_STEPS = 200;
|
|
732
|
+
var AGENT_EMOJI2 = {
|
|
733
|
+
"architect": "\u{1F3D7}\uFE0F",
|
|
734
|
+
"builder": "\u{1F528}",
|
|
735
|
+
"inspector": "\u{1F50D}",
|
|
736
|
+
"recorder": "\u{1F4BE}",
|
|
737
|
+
"commander": "\u{1F3AF}"
|
|
738
|
+
};
|
|
739
|
+
var CONTINUE_INSTRUCTION = `[AUTO-CONTINUE]
|
|
740
|
+
|
|
741
|
+
Mission not complete. Keep executing.
|
|
742
|
+
|
|
743
|
+
<rules>
|
|
744
|
+
1. DO NOT stop - mission is incomplete
|
|
745
|
+
2. DO NOT wait for user input
|
|
746
|
+
3. If previous action failed, try different approach
|
|
747
|
+
4. If agent returned nothing, proceed to next step
|
|
748
|
+
</rules>
|
|
749
|
+
|
|
750
|
+
<next_step>
|
|
751
|
+
What is the current state?
|
|
752
|
+
What is the next action?
|
|
753
|
+
Execute it NOW.
|
|
754
|
+
</next_step>`;
|
|
1113
755
|
var OrchestratorPlugin = async (input) => {
|
|
1114
|
-
const { directory } = input;
|
|
756
|
+
const { directory, client } = input;
|
|
757
|
+
const sessions = /* @__PURE__ */ new Map();
|
|
1115
758
|
return {
|
|
1116
|
-
// Register tools
|
|
1117
759
|
tool: {
|
|
1118
760
|
call_agent: callAgentTool,
|
|
1119
761
|
slashcommand: createSlashcommandTool(),
|
|
1120
762
|
grep_search: grepSearchTool(directory),
|
|
1121
763
|
glob_search: globSearchTool(directory)
|
|
1122
764
|
},
|
|
1123
|
-
// Register commands and agents for OpenCode UI
|
|
1124
765
|
config: async (config) => {
|
|
1125
766
|
const existingCommands = config.command ?? {};
|
|
1126
767
|
const existingAgents = config.agent ?? {};
|
|
@@ -1135,36 +776,35 @@ var OrchestratorPlugin = async (input) => {
|
|
|
1135
776
|
const orchestratorAgents = {
|
|
1136
777
|
Commander: {
|
|
1137
778
|
name: "Commander",
|
|
1138
|
-
description: "
|
|
779
|
+
description: "Autonomous orchestrator - executes until mission complete",
|
|
1139
780
|
systemPrompt: AGENTS.commander.systemPrompt
|
|
1140
781
|
}
|
|
1141
782
|
};
|
|
1142
|
-
config.command = {
|
|
1143
|
-
|
|
1144
|
-
...existingCommands
|
|
1145
|
-
};
|
|
1146
|
-
config.agent = {
|
|
1147
|
-
...orchestratorAgents,
|
|
1148
|
-
...existingAgents
|
|
1149
|
-
};
|
|
783
|
+
config.command = { ...orchestratorCommands, ...existingCommands };
|
|
784
|
+
config.agent = { ...orchestratorAgents, ...existingAgents };
|
|
1150
785
|
},
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
const parts = output.parts;
|
|
786
|
+
"chat.message": async (msgInput, msgOutput) => {
|
|
787
|
+
const parts = msgOutput.parts;
|
|
1154
788
|
const textPartIndex = parts.findIndex((p) => p.type === "text" && p.text);
|
|
1155
789
|
if (textPartIndex === -1) return;
|
|
1156
790
|
const originalText = parts[textPartIndex].text || "";
|
|
1157
791
|
const parsed = detectSlashCommand(originalText);
|
|
1158
|
-
const
|
|
1159
|
-
|
|
1160
|
-
|
|
792
|
+
const sessionID = msgInput.sessionID;
|
|
793
|
+
const agentName = (msgInput.agent || "").toLowerCase();
|
|
794
|
+
if (agentName === "commander" && !sessions.has(sessionID)) {
|
|
795
|
+
sessions.set(sessionID, {
|
|
796
|
+
active: true,
|
|
797
|
+
step: 0,
|
|
798
|
+
maxSteps: DEFAULT_MAX_STEPS,
|
|
799
|
+
timestamp: Date.now()
|
|
800
|
+
});
|
|
801
|
+
state.missionActive = true;
|
|
1161
802
|
state.sessions.set(sessionID, {
|
|
1162
803
|
enabled: true,
|
|
1163
804
|
iterations: 0,
|
|
1164
805
|
taskRetries: /* @__PURE__ */ new Map(),
|
|
1165
806
|
currentTask: ""
|
|
1166
807
|
});
|
|
1167
|
-
state.missionActive = true;
|
|
1168
808
|
if (!parsed) {
|
|
1169
809
|
const userMessage = originalText.trim();
|
|
1170
810
|
if (userMessage) {
|
|
@@ -1175,129 +815,178 @@ var OrchestratorPlugin = async (input) => {
|
|
|
1175
815
|
}
|
|
1176
816
|
}
|
|
1177
817
|
}
|
|
1178
|
-
if (parsed) {
|
|
818
|
+
if (parsed?.command === "task") {
|
|
819
|
+
sessions.set(sessionID, {
|
|
820
|
+
active: true,
|
|
821
|
+
step: 0,
|
|
822
|
+
maxSteps: TASK_COMMAND_MAX_STEPS,
|
|
823
|
+
timestamp: Date.now()
|
|
824
|
+
});
|
|
825
|
+
state.missionActive = true;
|
|
826
|
+
state.sessions.set(sessionID, {
|
|
827
|
+
enabled: true,
|
|
828
|
+
iterations: 0,
|
|
829
|
+
taskRetries: /* @__PURE__ */ new Map(),
|
|
830
|
+
currentTask: ""
|
|
831
|
+
});
|
|
832
|
+
parts[textPartIndex].text = COMMANDS["task"].template.replace(
|
|
833
|
+
/\$ARGUMENTS/g,
|
|
834
|
+
parsed.args || "continue previous work"
|
|
835
|
+
);
|
|
836
|
+
} else if (parsed) {
|
|
1179
837
|
const command = COMMANDS[parsed.command];
|
|
1180
838
|
if (command) {
|
|
1181
839
|
parts[textPartIndex].text = command.template.replace(
|
|
1182
840
|
/\$ARGUMENTS/g,
|
|
1183
|
-
parsed.args || "continue
|
|
841
|
+
parsed.args || "continue"
|
|
1184
842
|
);
|
|
1185
|
-
if (parsed.command === "task") {
|
|
1186
|
-
const sessionID = input2.sessionID;
|
|
1187
|
-
state.sessions.set(sessionID, {
|
|
1188
|
-
enabled: true,
|
|
1189
|
-
iterations: 0,
|
|
1190
|
-
taskRetries: /* @__PURE__ */ new Map(),
|
|
1191
|
-
currentTask: ""
|
|
1192
|
-
});
|
|
1193
|
-
state.missionActive = true;
|
|
1194
|
-
}
|
|
1195
843
|
}
|
|
1196
844
|
}
|
|
1197
845
|
},
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
if (!
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
if (
|
|
1205
|
-
const taskIdMatch =
|
|
846
|
+
"tool.execute.after": async (toolInput, toolOutput) => {
|
|
847
|
+
const session = sessions.get(toolInput.sessionID);
|
|
848
|
+
if (!session?.active) return;
|
|
849
|
+
session.step++;
|
|
850
|
+
session.timestamp = Date.now();
|
|
851
|
+
const stateSession = state.sessions.get(toolInput.sessionID);
|
|
852
|
+
if (toolInput.tool === "call_agent" && toolInput.arguments?.task && stateSession) {
|
|
853
|
+
const taskIdMatch = toolInput.arguments.task.match(/\[(TASK-\d+)\]/i);
|
|
1206
854
|
if (taskIdMatch) {
|
|
1207
|
-
|
|
1208
|
-
|
|
855
|
+
stateSession.currentTask = taskIdMatch[1].toUpperCase();
|
|
856
|
+
stateSession.graph?.updateTask(stateSession.currentTask, { status: "running" });
|
|
1209
857
|
}
|
|
858
|
+
const agentName = toolInput.arguments.agent;
|
|
859
|
+
const emoji = AGENT_EMOJI2[agentName] || "\u{1F916}";
|
|
860
|
+
toolOutput.output = `${emoji} [${agentName.toUpperCase()}] Working...
|
|
861
|
+
|
|
862
|
+
` + toolOutput.output;
|
|
1210
863
|
}
|
|
1211
|
-
if (session.
|
|
864
|
+
if (session.step >= session.maxSteps) {
|
|
865
|
+
session.active = false;
|
|
1212
866
|
state.missionActive = false;
|
|
1213
|
-
session.enabled = false;
|
|
1214
867
|
return;
|
|
1215
868
|
}
|
|
1216
|
-
if (
|
|
1217
|
-
const jsonMatch =
|
|
869
|
+
if (toolOutput.output.includes("[") && toolOutput.output.includes("{") && toolInput.tool === "call_agent" && stateSession) {
|
|
870
|
+
const jsonMatch = toolOutput.output.match(/```json\n([\s\S]*?)\n```/) || toolOutput.output.match(/\[\s*\{[\s\S]*?\}\s*\]/);
|
|
1218
871
|
if (jsonMatch) {
|
|
1219
872
|
try {
|
|
1220
873
|
const tasks = JSON.parse(jsonMatch[1] || jsonMatch[0]);
|
|
1221
874
|
if (Array.isArray(tasks) && tasks.length > 0) {
|
|
1222
|
-
|
|
1223
|
-
|
|
875
|
+
stateSession.graph = new TaskGraph(tasks);
|
|
876
|
+
toolOutput.output += `
|
|
1224
877
|
|
|
1225
878
|
\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501
|
|
1226
|
-
\u2705
|
|
1227
|
-
${
|
|
879
|
+
\u2705 INITIALIZED
|
|
880
|
+
${stateSession.graph.getTaskSummary()}`;
|
|
1228
881
|
}
|
|
1229
882
|
} catch {
|
|
1230
883
|
}
|
|
1231
884
|
}
|
|
1232
885
|
}
|
|
1233
|
-
if (
|
|
1234
|
-
|
|
1235
|
-
|
|
886
|
+
if (stateSession?.graph) {
|
|
887
|
+
const taskId = stateSession.currentTask;
|
|
888
|
+
if (toolOutput.output.includes("\u2705 PASS") || toolOutput.output.includes("AUDIT RESULT: PASS")) {
|
|
1236
889
|
if (taskId) {
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
890
|
+
stateSession.graph.updateTask(taskId, { status: "completed" });
|
|
891
|
+
stateSession.taskRetries.clear();
|
|
892
|
+
toolOutput.output += `
|
|
1240
893
|
|
|
1241
894
|
\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501
|
|
1242
|
-
\u2705
|
|
1243
|
-
${
|
|
895
|
+
\u2705 ${taskId} VERIFIED
|
|
896
|
+
${stateSession.graph.getTaskSummary()}`;
|
|
1244
897
|
}
|
|
1245
|
-
} else if (
|
|
1246
|
-
const taskId = session.currentTask;
|
|
898
|
+
} else if (toolOutput.output.includes("\u274C FAIL") || toolOutput.output.includes("AUDIT RESULT: FAIL")) {
|
|
1247
899
|
if (taskId) {
|
|
1248
|
-
const
|
|
1249
|
-
|
|
1250
|
-
session.taskRetries.set(errorId, retries);
|
|
900
|
+
const retries = (stateSession.taskRetries.get(taskId) || 0) + 1;
|
|
901
|
+
stateSession.taskRetries.set(taskId, retries);
|
|
1251
902
|
if (retries >= state.maxRetries) {
|
|
1252
|
-
|
|
1253
|
-
|
|
903
|
+
stateSession.graph.updateTask(taskId, { status: "failed" });
|
|
904
|
+
toolOutput.output += `
|
|
1254
905
|
|
|
1255
906
|
\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501
|
|
1256
|
-
\u26A0\uFE0F
|
|
1257
|
-
Call Architect for new strategy.`;
|
|
907
|
+
\u26A0\uFE0F ${taskId} FAILED (${retries}x)`;
|
|
1258
908
|
} else {
|
|
1259
|
-
|
|
909
|
+
toolOutput.output += `
|
|
1260
910
|
|
|
1261
911
|
\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501
|
|
1262
|
-
\u{1F504} RETRY ${retries}/${state.maxRetries}
|
|
912
|
+
\u{1F504} RETRY ${retries}/${state.maxRetries}`;
|
|
1263
913
|
}
|
|
1264
914
|
}
|
|
1265
915
|
}
|
|
916
|
+
const readyTasks = stateSession.graph.getReadyTasks();
|
|
917
|
+
if (readyTasks.length > 0) {
|
|
918
|
+
toolOutput.output += `
|
|
919
|
+
\u{1F449} NEXT: ${readyTasks.map((t) => `[${t.id}]`).join(", ")}`;
|
|
920
|
+
}
|
|
1266
921
|
}
|
|
1267
|
-
|
|
1268
|
-
const readyTasks = session.graph.getReadyTasks();
|
|
1269
|
-
const guidance = readyTasks.length > 0 ? `
|
|
1270
|
-
\u{1F449} READY: ${readyTasks.map((t) => `[${t.id}]`).join(", ")}` : `
|
|
1271
|
-
\u26A0\uFE0F No ready tasks. Check dependencies.`;
|
|
1272
|
-
output.output += `
|
|
1273
|
-
|
|
1274
|
-
\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501
|
|
1275
|
-
${session.graph.getTaskSummary()}${guidance}`;
|
|
1276
|
-
}
|
|
1277
|
-
output.output += `
|
|
922
|
+
toolOutput.output += `
|
|
1278
923
|
|
|
1279
|
-
[
|
|
924
|
+
[${session.step}/${session.maxSteps}]`;
|
|
1280
925
|
},
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
const
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
session.enabled = false;
|
|
926
|
+
"assistant.done": async (assistantInput, assistantOutput) => {
|
|
927
|
+
const sessionID = assistantInput.sessionID;
|
|
928
|
+
const session = sessions.get(sessionID);
|
|
929
|
+
if (!session?.active) return;
|
|
930
|
+
const parts = assistantOutput.parts;
|
|
931
|
+
const textContent = parts?.filter((p) => p.type === "text" || p.type === "reasoning").map((p) => p.text || "").join("\n") || "";
|
|
932
|
+
if (textContent.includes("\u2705 MISSION COMPLETE") || textContent.includes("MISSION COMPLETE")) {
|
|
933
|
+
session.active = false;
|
|
1290
934
|
state.missionActive = false;
|
|
1291
|
-
|
|
935
|
+
sessions.delete(sessionID);
|
|
936
|
+
state.sessions.delete(sessionID);
|
|
1292
937
|
return;
|
|
1293
938
|
}
|
|
1294
|
-
if (
|
|
1295
|
-
session.
|
|
939
|
+
if (textContent.includes("/stop") || textContent.includes("/cancel")) {
|
|
940
|
+
session.active = false;
|
|
1296
941
|
state.missionActive = false;
|
|
942
|
+
sessions.delete(sessionID);
|
|
943
|
+
state.sessions.delete(sessionID);
|
|
1297
944
|
return;
|
|
1298
945
|
}
|
|
1299
|
-
|
|
1300
|
-
|
|
946
|
+
session.step++;
|
|
947
|
+
session.timestamp = Date.now();
|
|
948
|
+
if (session.step >= session.maxSteps) {
|
|
949
|
+
session.active = false;
|
|
950
|
+
state.missionActive = false;
|
|
951
|
+
return;
|
|
952
|
+
}
|
|
953
|
+
try {
|
|
954
|
+
if (client?.session?.prompt) {
|
|
955
|
+
await client.session.prompt({
|
|
956
|
+
path: { id: sessionID },
|
|
957
|
+
body: {
|
|
958
|
+
parts: [{
|
|
959
|
+
type: "text",
|
|
960
|
+
text: CONTINUE_INSTRUCTION + `
|
|
961
|
+
|
|
962
|
+
[Step ${session.step}/${session.maxSteps}]`
|
|
963
|
+
}]
|
|
964
|
+
}
|
|
965
|
+
});
|
|
966
|
+
}
|
|
967
|
+
} catch {
|
|
968
|
+
try {
|
|
969
|
+
await new Promise((r) => setTimeout(r, 500));
|
|
970
|
+
if (client?.session?.prompt) {
|
|
971
|
+
await client.session.prompt({
|
|
972
|
+
path: { id: sessionID },
|
|
973
|
+
body: { parts: [{ type: "text", text: "continue" }] }
|
|
974
|
+
});
|
|
975
|
+
}
|
|
976
|
+
} catch {
|
|
977
|
+
session.active = false;
|
|
978
|
+
state.missionActive = false;
|
|
979
|
+
}
|
|
980
|
+
}
|
|
981
|
+
},
|
|
982
|
+
handler: async ({ event }) => {
|
|
983
|
+
if (event.type === "session.deleted") {
|
|
984
|
+
const props = event.properties;
|
|
985
|
+
if (props?.info?.id) {
|
|
986
|
+
sessions.delete(props.info.id);
|
|
987
|
+
state.sessions.delete(props.info.id);
|
|
988
|
+
}
|
|
989
|
+
}
|
|
1301
990
|
}
|
|
1302
991
|
};
|
|
1303
992
|
};
|