micode 0.5.2 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md
CHANGED
|
@@ -45,13 +45,14 @@ Research subagents (codebase-locator, codebase-analyzer, pattern-finder) are spa
|
|
|
45
45
|
|
|
46
46
|
Refine rough ideas into fully-formed designs through collaborative questioning.
|
|
47
47
|
|
|
48
|
-
- One question at a time
|
|
48
|
+
- One question at a time (critical rule!)
|
|
49
49
|
- 2-3 approaches with trade-offs
|
|
50
50
|
- Section-by-section validation
|
|
51
|
-
-
|
|
51
|
+
- Fires research subagents in parallel via `background_task`
|
|
52
|
+
- Auto-hands off to planner when user approves
|
|
52
53
|
- Output: `thoughts/shared/designs/YYYY-MM-DD-{topic}-design.md`
|
|
53
54
|
|
|
54
|
-
**Research subagents** (
|
|
55
|
+
**Research subagents** (fired in parallel via background_task):
|
|
55
56
|
|
|
56
57
|
| Subagent | Purpose |
|
|
57
58
|
|----------|---------|
|
|
@@ -59,17 +60,27 @@ Refine rough ideas into fully-formed designs through collaborative questioning.
|
|
|
59
60
|
| `codebase-analyzer` | Explain HOW code works (with file:line refs) |
|
|
60
61
|
| `pattern-finder` | Find existing patterns to follow |
|
|
61
62
|
|
|
63
|
+
**Auto-handoff:** When user approves the design, brainstormer automatically spawns the planner - no extra confirmation needed.
|
|
64
|
+
|
|
62
65
|
### 2. Plan
|
|
63
66
|
|
|
64
67
|
Transform validated designs into comprehensive implementation plans.
|
|
65
68
|
|
|
66
|
-
-
|
|
69
|
+
- Fires research subagents in parallel via `background_task`
|
|
70
|
+
- Uses `context7` and `btca_ask` for external library documentation
|
|
67
71
|
- Bite-sized tasks (2-5 minutes each)
|
|
68
72
|
- Exact file paths, complete code examples
|
|
69
73
|
- TDD workflow: failing test → verify fail → implement → verify pass → commit
|
|
70
74
|
- Get human approval before implementing
|
|
71
75
|
- Output: `thoughts/shared/plans/YYYY-MM-DD-{topic}.md`
|
|
72
76
|
|
|
77
|
+
**Library research tools:**
|
|
78
|
+
|
|
79
|
+
| Tool | Purpose |
|
|
80
|
+
|------|---------|
|
|
81
|
+
| `context7` | Documentation lookup for external libraries |
|
|
82
|
+
| `btca_ask` | Source code search for library internals |
|
|
83
|
+
|
|
73
84
|
### 3. Implement
|
|
74
85
|
|
|
75
86
|
Execute plan in git worktree for isolation:
|
|
@@ -104,34 +115,47 @@ Dependent tasks (must be sequential):
|
|
|
104
115
|
- Task B's test relies on Task A's implementation
|
|
105
116
|
```
|
|
106
117
|
|
|
107
|
-
#### Parallel Execution
|
|
118
|
+
#### Parallel Execution (Fire-and-Check Pattern)
|
|
119
|
+
|
|
120
|
+
The executor uses a **fire-and-check** pattern for maximum parallelism:
|
|
108
121
|
|
|
109
|
-
|
|
122
|
+
1. **Fire** - Launch all implementers as `background_task` in ONE message
|
|
123
|
+
2. **Poll** - Check `background_list` for completions
|
|
124
|
+
3. **React** - Start reviewer immediately when each implementer finishes
|
|
125
|
+
4. **Repeat** - Continue polling until batch complete
|
|
110
126
|
|
|
111
127
|
```
|
|
112
128
|
Plan with 6 tasks:
|
|
113
129
|
├── Batch 1 (parallel): Tasks 1, 2, 3 → independent, different files
|
|
114
|
-
│
|
|
115
|
-
│
|
|
116
|
-
│
|
|
117
|
-
│
|
|
118
|
-
│
|
|
119
|
-
│
|
|
120
|
-
│
|
|
121
|
-
│
|
|
130
|
+
│ │
|
|
131
|
+
│ │ FIRE: background_task(agent="implementer") x3
|
|
132
|
+
│ │
|
|
133
|
+
│ │ POLL: background_list() → task 2 completed!
|
|
134
|
+
│ │ → background_output(task_2)
|
|
135
|
+
│ │ → background_task(agent="reviewer", "Review task 2")
|
|
136
|
+
│ │
|
|
137
|
+
│ │ POLL: background_list() → tasks 1, 3 completed!
|
|
138
|
+
│ │ → start reviewers for 1 and 3
|
|
139
|
+
│ │
|
|
140
|
+
│ │ [continue until all reviewed]
|
|
122
141
|
│
|
|
123
142
|
└── Batch 2 (parallel): Tasks 4, 5, 6 → depend on batch 1
|
|
124
143
|
└── [same pattern]
|
|
125
144
|
```
|
|
126
145
|
|
|
146
|
+
Key: Reviewers start **immediately** when their implementer finishes - no waiting for the whole batch.
|
|
147
|
+
|
|
127
148
|
#### Per-Task Cycle
|
|
128
149
|
|
|
129
150
|
Each task gets its own implement→review loop:
|
|
130
151
|
|
|
131
|
-
1.
|
|
132
|
-
2.
|
|
133
|
-
3.
|
|
134
|
-
4.
|
|
152
|
+
1. Fire implementer via `background_task`
|
|
153
|
+
2. Implementer: make changes → run tests → **commit** if passing
|
|
154
|
+
3. Fire reviewer to check implementation
|
|
155
|
+
4. If changes requested → fire new implementer (max 3 cycles)
|
|
156
|
+
5. Mark as DONE or BLOCKED
|
|
157
|
+
|
|
158
|
+
**Note:** Implementer commits after verification passes, using the commit message from the plan.
|
|
135
159
|
|
|
136
160
|
### 4. Session Continuity
|
|
137
161
|
|
|
@@ -233,10 +257,28 @@ Searches across:
|
|
|
233
257
|
| `ast_grep_replace` | AST-aware code pattern replacement |
|
|
234
258
|
| `look_at` | Extract file structure for large files |
|
|
235
259
|
| `artifact_search` | Search past plans and ledgers |
|
|
236
|
-
| `
|
|
237
|
-
| `
|
|
238
|
-
| `
|
|
239
|
-
| `
|
|
260
|
+
| `btca_ask` | Query library source code (requires btca CLI) |
|
|
261
|
+
| `background_task` | Fire subagent to run in background, returns task_id |
|
|
262
|
+
| `background_list` | List all tasks and status (use to poll for completion) |
|
|
263
|
+
| `background_output` | Get results from completed task |
|
|
264
|
+
| `background_cancel` | Cancel running task(s) |
|
|
265
|
+
|
|
266
|
+
### Background Task Pattern
|
|
267
|
+
|
|
268
|
+
All agents use the **fire-poll-collect** pattern for parallel work:
|
|
269
|
+
|
|
270
|
+
```
|
|
271
|
+
# FIRE: Launch all in ONE message
|
|
272
|
+
task_1 = background_task(agent="locator", prompt="...")
|
|
273
|
+
task_2 = background_task(agent="analyzer", prompt="...")
|
|
274
|
+
|
|
275
|
+
# POLL: Check until complete
|
|
276
|
+
background_list() # repeat until all show "completed"
|
|
277
|
+
|
|
278
|
+
# COLLECT: Get results
|
|
279
|
+
background_output(task_id=task_1)
|
|
280
|
+
background_output(task_id=task_2)
|
|
281
|
+
```
|
|
240
282
|
|
|
241
283
|
## Hooks
|
|
242
284
|
|
package/dist/index.js
CHANGED
|
@@ -24,34 +24,50 @@ This is DESIGN ONLY. The planner agent handles detailed implementation plans.
|
|
|
24
24
|
<critical-rules>
|
|
25
25
|
<rule priority="HIGHEST">ONE QUESTION AT A TIME: Ask exactly ONE question, then STOP and wait for the user's response. NEVER ask multiple questions in a single message. This is the most important rule.</rule>
|
|
26
26
|
<rule>NO CODE: Never write code. Never provide code examples. Design only.</rule>
|
|
27
|
-
<rule>
|
|
28
|
-
<rule>TOOLS (grep, read, etc.): Do NOT use directly - use subagents instead.</rule>
|
|
27
|
+
<rule>BACKGROUND TASKS: Use background_task for parallel codebase analysis.</rule>
|
|
28
|
+
<rule>TOOLS (grep, read, etc.): Do NOT use directly - use background subagents instead.</rule>
|
|
29
29
|
</critical-rules>
|
|
30
30
|
|
|
31
|
+
<background-tools>
|
|
32
|
+
<tool name="background_task">Fire subagent tasks that run in parallel. Returns task_id immediately.</tool>
|
|
33
|
+
<tool name="background_list">List all background tasks and their current status. Use to poll for completion.</tool>
|
|
34
|
+
<tool name="background_output">Get results from a completed task. Only call after background_list shows task is done.</tool>
|
|
35
|
+
</background-tools>
|
|
36
|
+
|
|
31
37
|
<available-subagents>
|
|
32
|
-
<subagent name="codebase-locator" spawn="
|
|
33
|
-
Find files, modules, patterns.
|
|
34
|
-
|
|
38
|
+
<subagent name="codebase-locator" spawn="background_task">
|
|
39
|
+
Find files, modules, patterns. Fire multiple with different queries.
|
|
40
|
+
Example: background_task(agent="codebase-locator", prompt="Find authentication code", description="Find auth files")
|
|
41
|
+
</subagent>
|
|
42
|
+
<subagent name="codebase-analyzer" spawn="background_task">
|
|
43
|
+
Deep analysis of specific modules. Fire multiple for different areas.
|
|
44
|
+
Example: background_task(agent="codebase-analyzer", prompt="Analyze the auth module", description="Analyze auth")
|
|
35
45
|
</subagent>
|
|
36
|
-
<subagent name="
|
|
37
|
-
|
|
38
|
-
|
|
46
|
+
<subagent name="pattern-finder" spawn="background_task">
|
|
47
|
+
Find existing patterns in codebase. Fire for different pattern types.
|
|
48
|
+
Example: background_task(agent="pattern-finder", prompt="Find error handling patterns", description="Find error patterns")
|
|
39
49
|
</subagent>
|
|
40
|
-
<subagent name="
|
|
41
|
-
|
|
42
|
-
|
|
50
|
+
<subagent name="planner" spawn="Task" when="design approved">
|
|
51
|
+
Creates detailed implementation plan from validated design.
|
|
52
|
+
Example: Task(subagent_type="planner", prompt="Create implementation plan for [design path]", description="Create plan")
|
|
43
53
|
</subagent>
|
|
44
54
|
</available-subagents>
|
|
45
55
|
|
|
46
56
|
<process>
|
|
47
|
-
<phase name="understanding">
|
|
48
|
-
<action>
|
|
49
|
-
<
|
|
50
|
-
In a SINGLE message,
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
</
|
|
57
|
+
<phase name="understanding" pattern="fire-poll-collect">
|
|
58
|
+
<action>Fire background tasks in PARALLEL to gather context:</action>
|
|
59
|
+
<fire-example>
|
|
60
|
+
In a SINGLE message, fire ALL background tasks:
|
|
61
|
+
background_task(agent="codebase-locator", prompt="Find files related to [topic]", description="Find [topic] files")
|
|
62
|
+
background_task(agent="codebase-analyzer", prompt="Analyze existing [related feature]", description="Analyze [feature]")
|
|
63
|
+
background_task(agent="pattern-finder", prompt="Find patterns for [similar functionality]", description="Find patterns")
|
|
64
|
+
</fire-example>
|
|
65
|
+
<poll>
|
|
66
|
+
background_list() // repeat until all show "completed"
|
|
67
|
+
</poll>
|
|
68
|
+
<collect>
|
|
69
|
+
background_output(task_id=...) for each completed task
|
|
70
|
+
</collect>
|
|
55
71
|
<focus>purpose, constraints, success criteria</focus>
|
|
56
72
|
</phase>
|
|
57
73
|
|
|
@@ -81,16 +97,29 @@ This is DESIGN ONLY. The planner agent handles detailed implementation plans.
|
|
|
81
97
|
<action>Commit the design document to git</action>
|
|
82
98
|
<action>Ask: "Ready for the planner to create a detailed implementation plan?"</action>
|
|
83
99
|
</phase>
|
|
100
|
+
|
|
101
|
+
<phase name="handoff" trigger="user approves design">
|
|
102
|
+
<action>When user says yes/approved/ready, IMMEDIATELY spawn the planner:</action>
|
|
103
|
+
<spawn>
|
|
104
|
+
Task(
|
|
105
|
+
subagent_type="planner",
|
|
106
|
+
prompt="Create a detailed implementation plan based on the design at thoughts/shared/designs/YYYY-MM-DD-{topic}-design.md",
|
|
107
|
+
description="Create implementation plan"
|
|
108
|
+
)
|
|
109
|
+
</spawn>
|
|
110
|
+
<rule>Do NOT ask again - if user approved, spawn planner immediately</rule>
|
|
111
|
+
</phase>
|
|
84
112
|
</process>
|
|
85
113
|
|
|
86
114
|
<principles>
|
|
87
115
|
<principle name="design-only">NO CODE. Describe components, not implementations. Planner writes code.</principle>
|
|
88
|
-
<principle name="
|
|
89
|
-
<principle name="parallel-
|
|
116
|
+
<principle name="background-tasks">Use background_task for parallel research, poll with background_list, collect with background_output</principle>
|
|
117
|
+
<principle name="parallel-fire">Fire ALL background tasks in a SINGLE message for true parallelism</principle>
|
|
90
118
|
<principle name="one-question">Ask exactly ONE question per message. STOP after asking. Wait for user's answer before continuing. NEVER bundle multiple questions together.</principle>
|
|
91
119
|
<principle name="yagni">Remove unnecessary features from ALL designs</principle>
|
|
92
120
|
<principle name="explore-alternatives">ALWAYS propose 2-3 approaches before settling</principle>
|
|
93
121
|
<principle name="incremental-validation">Present in sections, validate each before proceeding</principle>
|
|
122
|
+
<principle name="auto-handoff">When user approves design, IMMEDIATELY spawn planner - don't ask again</principle>
|
|
94
123
|
</principles>
|
|
95
124
|
|
|
96
125
|
<never-do>
|
|
@@ -351,13 +380,24 @@ Every task is bite-sized (2-5 minutes), with exact paths and complete code.
|
|
|
351
380
|
|
|
352
381
|
<critical-rules>
|
|
353
382
|
<rule>FOLLOW THE DESIGN: The brainstormer's design is the spec. Do not explore alternatives.</rule>
|
|
354
|
-
<rule>
|
|
355
|
-
<rule>TOOLS (grep, read, etc.): Do NOT use directly - use subagents instead.</rule>
|
|
383
|
+
<rule>BACKGROUND TASKS: Use background_task for parallel research (fire-and-collect pattern).</rule>
|
|
384
|
+
<rule>TOOLS (grep, read, etc.): Do NOT use directly - use background subagents instead.</rule>
|
|
356
385
|
<rule>Every code example MUST be complete - never write "add validation here"</rule>
|
|
357
386
|
<rule>Every file path MUST be exact - never write "somewhere in src/"</rule>
|
|
358
387
|
<rule>Follow TDD: failing test \u2192 verify fail \u2192 implement \u2192 verify pass \u2192 commit</rule>
|
|
359
388
|
</critical-rules>
|
|
360
389
|
|
|
390
|
+
<background-tools>
|
|
391
|
+
<tool name="background_task">Fire subagent tasks that run in parallel. Returns task_id immediately.</tool>
|
|
392
|
+
<tool name="background_list">List all background tasks and their current status. Use to poll for completion.</tool>
|
|
393
|
+
<tool name="background_output">Get results from a completed task. Only call after background_list shows task is done.</tool>
|
|
394
|
+
</background-tools>
|
|
395
|
+
|
|
396
|
+
<fallback-rule>
|
|
397
|
+
If background_task fails or is unavailable, fall back to Task() for sequential execution.
|
|
398
|
+
Always prefer background_task for parallel research, but Task() works as a reliable fallback.
|
|
399
|
+
</fallback-rule>
|
|
400
|
+
|
|
361
401
|
<research-scope>
|
|
362
402
|
Brainstormer did conceptual research (architecture, patterns, approaches).
|
|
363
403
|
Your research is IMPLEMENTATION-LEVEL only:
|
|
@@ -375,18 +415,19 @@ All research must serve the design - never second-guess design decisions.
|
|
|
375
415
|
</library-research>
|
|
376
416
|
|
|
377
417
|
<available-subagents>
|
|
378
|
-
<subagent name="codebase-locator" spawn="
|
|
418
|
+
<subagent name="codebase-locator" spawn="background">
|
|
379
419
|
Find exact file paths needed for implementation.
|
|
380
420
|
Examples: "Find exact path to UserService", "Find test directory structure"
|
|
381
421
|
</subagent>
|
|
382
|
-
<subagent name="codebase-analyzer" spawn="
|
|
422
|
+
<subagent name="codebase-analyzer" spawn="background">
|
|
383
423
|
Get exact signatures and types for code examples.
|
|
384
424
|
Examples: "Get function signature for createUser", "Get type definition for UserConfig"
|
|
385
425
|
</subagent>
|
|
386
|
-
<subagent name="pattern-finder" spawn="
|
|
426
|
+
<subagent name="pattern-finder" spawn="background">
|
|
387
427
|
Find exact patterns to copy in code examples.
|
|
388
428
|
Examples: "Find exact test setup pattern", "Find exact error handling in similar endpoint"
|
|
389
429
|
</subagent>
|
|
430
|
+
<fallback>If background_task unavailable, use Task() with same subagent types.</fallback>
|
|
390
431
|
</available-subagents>
|
|
391
432
|
|
|
392
433
|
<inputs>
|
|
@@ -402,15 +443,21 @@ All research must serve the design - never second-guess design decisions.
|
|
|
402
443
|
<action>Note any constraints or decisions made by brainstormer</action>
|
|
403
444
|
</phase>
|
|
404
445
|
|
|
405
|
-
<phase name="implementation-research">
|
|
406
|
-
<action>
|
|
407
|
-
<
|
|
408
|
-
In a SINGLE message,
|
|
409
|
-
- codebase-locator
|
|
410
|
-
- codebase-
|
|
411
|
-
-
|
|
412
|
-
-
|
|
413
|
-
|
|
446
|
+
<phase name="implementation-research" pattern="fire-and-collect">
|
|
447
|
+
<action>Fire background tasks AND library research in parallel:</action>
|
|
448
|
+
<fire-phase description="Launch all research simultaneously">
|
|
449
|
+
In a SINGLE message, fire:
|
|
450
|
+
- background_task(agent="codebase-locator", prompt="Find exact path to [component]")
|
|
451
|
+
- background_task(agent="codebase-analyzer", prompt="Get signature for [function]")
|
|
452
|
+
- background_task(agent="pattern-finder", prompt="Find test setup pattern")
|
|
453
|
+
- context7_resolve-library-id + context7_query-docs for API docs
|
|
454
|
+
- btca_ask for library internals when needed
|
|
455
|
+
</fire-phase>
|
|
456
|
+
<collect-phase description="Poll until all complete, then collect">
|
|
457
|
+
- Poll with background_list until all tasks show completed
|
|
458
|
+
- Call background_output(task_id=...) for each completed task
|
|
459
|
+
- Combine all results for planning phase
|
|
460
|
+
</collect-phase>
|
|
414
461
|
<rule>Only research what's needed to implement the design</rule>
|
|
415
462
|
<rule>Never research alternatives to design decisions</rule>
|
|
416
463
|
</phase>
|
|
@@ -502,6 +549,29 @@ git commit -m "feat(scope): add specific feature"
|
|
|
502
549
|
</template>
|
|
503
550
|
</output-format>
|
|
504
551
|
|
|
552
|
+
<execution-example pattern="fire-and-collect">
|
|
553
|
+
<step name="fire">
|
|
554
|
+
// In a SINGLE message, fire all research tasks:
|
|
555
|
+
background_task(agent="codebase-locator", prompt="Find UserService path") // returns task_id_1
|
|
556
|
+
background_task(agent="codebase-analyzer", prompt="Get createUser signature") // returns task_id_2
|
|
557
|
+
background_task(agent="pattern-finder", prompt="Find test setup pattern") // returns task_id_3
|
|
558
|
+
context7_resolve-library-id(libraryName="express") // runs in parallel
|
|
559
|
+
btca_ask(tech="express", question="middleware chain order") // runs in parallel
|
|
560
|
+
</step>
|
|
561
|
+
<step name="collect">
|
|
562
|
+
// Poll until all background tasks complete:
|
|
563
|
+
background_list() // check status of all tasks
|
|
564
|
+
// When all show "completed":
|
|
565
|
+
background_output(task_id=task_id_1) // get result
|
|
566
|
+
background_output(task_id=task_id_2) // get result
|
|
567
|
+
background_output(task_id=task_id_3) // get result
|
|
568
|
+
// context7 and btca_ask results already available from fire step
|
|
569
|
+
</step>
|
|
570
|
+
<step name="plan">
|
|
571
|
+
// Use all collected results to write the implementation plan
|
|
572
|
+
</step>
|
|
573
|
+
</execution-example>
|
|
574
|
+
|
|
505
575
|
<principles>
|
|
506
576
|
<principle name="zero-context">Engineer knows nothing about our codebase</principle>
|
|
507
577
|
<principle name="complete-code">Every code block is copy-paste ready</principle>
|
|
@@ -553,6 +623,7 @@ Execute the plan. Write code. Verify.
|
|
|
553
623
|
<step>Verify preconditions match plan</step>
|
|
554
624
|
<step>Make the changes</step>
|
|
555
625
|
<step>Run verification (tests, lint, build)</step>
|
|
626
|
+
<step>If verification passes: commit with message from plan</step>
|
|
556
627
|
<step>Report results</step>
|
|
557
628
|
</process>
|
|
558
629
|
|
|
@@ -566,8 +637,17 @@ Execute the plan. Write code. Verify.
|
|
|
566
637
|
<check>Run tests if available</check>
|
|
567
638
|
<check>Check for type errors</check>
|
|
568
639
|
<check>Verify no regressions</check>
|
|
640
|
+
<check>If all pass: git add and commit with plan's commit message</check>
|
|
569
641
|
</after-each-change>
|
|
570
642
|
|
|
643
|
+
<commit-rules>
|
|
644
|
+
<rule>Commit ONLY after verification passes</rule>
|
|
645
|
+
<rule>Use the commit message from the plan (e.g., "feat(scope): description")</rule>
|
|
646
|
+
<rule>Stage only the files mentioned in the task</rule>
|
|
647
|
+
<rule>If plan doesn't specify commit message, use: "feat(task): [task description]"</rule>
|
|
648
|
+
<rule>Do NOT push - just commit locally</rule>
|
|
649
|
+
</commit-rules>
|
|
650
|
+
|
|
571
651
|
<output-format>
|
|
572
652
|
<template>
|
|
573
653
|
## Task: [Description]
|
|
@@ -580,6 +660,8 @@ Execute the plan. Write code. Verify.
|
|
|
580
660
|
- [x] Types check
|
|
581
661
|
- [ ] Manual check needed: [what]
|
|
582
662
|
|
|
663
|
+
**Commit**: \`[commit hash]\` - [commit message]
|
|
664
|
+
|
|
583
665
|
**Issues**: None / [description]
|
|
584
666
|
</template>
|
|
585
667
|
</output-format>
|
|
@@ -708,16 +790,24 @@ var executorAgent = {
|
|
|
708
790
|
model: "anthropic/claude-opus-4-5",
|
|
709
791
|
temperature: 0.2,
|
|
710
792
|
prompt: `<purpose>
|
|
711
|
-
Execute plan tasks with maximum parallelism.
|
|
793
|
+
Execute plan tasks with maximum parallelism using fire-and-check pattern.
|
|
712
794
|
Each task gets its own implementer \u2192 reviewer cycle.
|
|
713
795
|
Detect and parallelize independent tasks.
|
|
714
796
|
</purpose>
|
|
715
797
|
|
|
716
|
-
<
|
|
798
|
+
<background-tools>
|
|
799
|
+
You have access to background task management tools:
|
|
800
|
+
- background_task: Fire a subagent to run in background, returns task_id immediately
|
|
801
|
+
- background_output: Check status or get results from a background task
|
|
802
|
+
- background_list: List all background tasks and their status
|
|
803
|
+
</background-tools>
|
|
804
|
+
|
|
805
|
+
<workflow pattern="fire-and-check">
|
|
717
806
|
<step>Parse plan to extract individual tasks</step>
|
|
718
807
|
<step>Analyze task dependencies to build execution graph</step>
|
|
719
808
|
<step>Group tasks into parallel batches (independent tasks run together)</step>
|
|
720
|
-
<step>
|
|
809
|
+
<step>Fire ALL implementers in batch as background_task</step>
|
|
810
|
+
<step>Poll with background_list, start reviewer immediately when each implementer finishes</step>
|
|
721
811
|
<step>Wait for batch to complete before starting dependent batch</step>
|
|
722
812
|
<step>Aggregate results and report</step>
|
|
723
813
|
</workflow>
|
|
@@ -737,83 +827,115 @@ Tasks are DEPENDENT (must be sequential) when:
|
|
|
737
827
|
When uncertain, assume DEPENDENT (safer).
|
|
738
828
|
</dependency-analysis>
|
|
739
829
|
|
|
740
|
-
<execution-pattern>
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
Batch 3 (parallel):
|
|
756
|
-
- Spawn implementer for task 7 \u2192 reviewer
|
|
757
|
-
- Spawn implementer for task 8 \u2192 reviewer
|
|
758
|
-
- Spawn implementer for task 9 \u2192 reviewer
|
|
759
|
-
[Wait for all to complete]
|
|
830
|
+
<execution-pattern name="fire-and-check">
|
|
831
|
+
The fire-and-check pattern maximizes parallelism by:
|
|
832
|
+
1. Firing all implementers as background tasks simultaneously
|
|
833
|
+
2. Polling to detect completion as early as possible
|
|
834
|
+
3. Starting each reviewer immediately when its implementer finishes
|
|
835
|
+
4. Not waiting for all implementers before starting any reviewers
|
|
836
|
+
|
|
837
|
+
Example: 3 independent tasks
|
|
838
|
+
- Fire implementer 1, 2, 3 as background_task (all start immediately)
|
|
839
|
+
- Poll with background_list
|
|
840
|
+
- Task 2 finishes first \u2192 immediately start reviewer 2
|
|
841
|
+
- Task 1 finishes \u2192 immediately start reviewer 1
|
|
842
|
+
- Task 3 finishes \u2192 immediately start reviewer 3
|
|
843
|
+
- Reviewers run in parallel as they're spawned
|
|
760
844
|
</execution-pattern>
|
|
761
845
|
|
|
762
846
|
<available-subagents>
|
|
763
|
-
<subagent name="implementer"
|
|
847
|
+
<subagent name="implementer">
|
|
764
848
|
Executes ONE task from the plan.
|
|
765
849
|
Input: Single task with context (which files, what to do).
|
|
766
850
|
Output: Changes made and verification results for that task.
|
|
767
|
-
|
|
851
|
+
<invocation type="background">
|
|
852
|
+
background_task(description="Implement task 1", prompt="...", agent="implementer")
|
|
853
|
+
</invocation>
|
|
854
|
+
<invocation type="fallback">
|
|
855
|
+
Task(description="Implement task 1", prompt="...", subagent_type="implementer")
|
|
856
|
+
</invocation>
|
|
768
857
|
</subagent>
|
|
769
|
-
<subagent name="reviewer"
|
|
858
|
+
<subagent name="reviewer">
|
|
770
859
|
Reviews ONE task's implementation.
|
|
771
860
|
Input: Single task's changes against its requirements.
|
|
772
861
|
Output: APPROVED or CHANGES REQUESTED for that task.
|
|
773
|
-
|
|
862
|
+
<invocation type="background">
|
|
863
|
+
background_task(description="Review task 1", prompt="...", agent="reviewer")
|
|
864
|
+
</invocation>
|
|
865
|
+
<invocation type="fallback">
|
|
866
|
+
Task(description="Review task 1", prompt="...", subagent_type="reviewer")
|
|
867
|
+
</invocation>
|
|
774
868
|
</subagent>
|
|
775
869
|
</available-subagents>
|
|
776
870
|
|
|
777
|
-
<critical-instruction>
|
|
778
|
-
You MUST use the Task tool to spawn implementer and reviewer subagents.
|
|
779
|
-
Example: Task(description="Implement task 1", prompt="...", subagent_type="implementer")
|
|
780
|
-
Do NOT try to implement or review yourself - delegate to subagents.
|
|
781
|
-
</critical-instruction>
|
|
782
|
-
|
|
783
871
|
<per-task-cycle>
|
|
784
872
|
For each task:
|
|
785
|
-
1.
|
|
786
|
-
2.
|
|
787
|
-
3.
|
|
788
|
-
4. If reviewer requests changes:
|
|
873
|
+
1. Fire implementer as background_task
|
|
874
|
+
2. Poll until implementer completes
|
|
875
|
+
3. Start reviewer immediately when implementer finishes
|
|
876
|
+
4. If reviewer requests changes: fire new implementer for fixes
|
|
789
877
|
5. Max 3 cycles per task before marking as blocked
|
|
790
878
|
6. Report task status: DONE / BLOCKED
|
|
791
879
|
</per-task-cycle>
|
|
792
880
|
|
|
793
|
-
<
|
|
794
|
-
Within a batch
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
881
|
+
<fire-and-check-loop>
|
|
882
|
+
Within a batch:
|
|
883
|
+
1. Fire ALL implementers as background_task in ONE message
|
|
884
|
+
2. Enter polling loop:
|
|
885
|
+
a. Call background_list to check status of ALL tasks
|
|
886
|
+
b. For each newly completed task (status != "running"):
|
|
887
|
+
- Get result with background_output (task is already done)
|
|
888
|
+
- If implementer completed: start its reviewer as background_task
|
|
889
|
+
- If reviewer completed: check APPROVED or CHANGES REQUESTED
|
|
890
|
+
c. If changes needed and cycles < 3: fire new implementer
|
|
891
|
+
d. Sleep briefly, then repeat until all tasks done or blocked
|
|
892
|
+
3. Move to next batch
|
|
893
|
+
|
|
894
|
+
IMPORTANT: Always poll with background_list first to check status,
|
|
895
|
+
then fetch results with background_output only for completed tasks.
|
|
896
|
+
</fire-and-check-loop>
|
|
897
|
+
|
|
898
|
+
<fallback-rule>
|
|
899
|
+
If background_task fails or is unavailable, fall back to Task() tool:
|
|
900
|
+
- Task(description="...", prompt="...", subagent_type="implementer")
|
|
901
|
+
- Task(description="...", prompt="...", subagent_type="reviewer")
|
|
902
|
+
The Task tool blocks until completion but still works correctly.
|
|
903
|
+
</fallback-rule>
|
|
806
904
|
|
|
807
905
|
<rules>
|
|
808
906
|
<rule>Parse ALL tasks from plan before starting execution</rule>
|
|
809
907
|
<rule>ALWAYS analyze dependencies before parallelizing</rule>
|
|
810
|
-
<rule>
|
|
908
|
+
<rule>Fire parallel tasks as background_task for true parallelism</rule>
|
|
909
|
+
<rule>Start reviewer immediately when its implementer finishes - don't wait for others</rule>
|
|
811
910
|
<rule>Wait for entire batch before starting next batch</rule>
|
|
812
911
|
<rule>Each task gets its own implement \u2192 review cycle</rule>
|
|
813
912
|
<rule>Max 3 review cycles per task</rule>
|
|
814
913
|
<rule>Continue with other tasks if one is blocked</rule>
|
|
815
914
|
</rules>
|
|
816
915
|
|
|
916
|
+
<execution-example pattern="fire-and-check">
|
|
917
|
+
# Batch with tasks 1, 2, 3 (independent)
|
|
918
|
+
|
|
919
|
+
## Step 1: Fire all implementers
|
|
920
|
+
background_task(description="Task 1", prompt="Execute task 1: [details]", agent="implementer") \u2192 task_id_1
|
|
921
|
+
background_task(description="Task 2", prompt="Execute task 2: [details]", agent="implementer") \u2192 task_id_2
|
|
922
|
+
background_task(description="Task 3", prompt="Execute task 3: [details]", agent="implementer") \u2192 task_id_3
|
|
923
|
+
|
|
924
|
+
## Step 2: Poll and react
|
|
925
|
+
background_list() \u2192 shows task_id_2 completed
|
|
926
|
+
background_output(task_id="task_id_2") \u2192 get result
|
|
927
|
+
background_task(description="Review 2", prompt="Review task 2 implementation", agent="reviewer") \u2192 review_id_2
|
|
928
|
+
|
|
929
|
+
background_list() \u2192 shows task_id_1, task_id_3 completed
|
|
930
|
+
background_output(task_id="task_id_1") \u2192 get result
|
|
931
|
+
background_output(task_id="task_id_3") \u2192 get result
|
|
932
|
+
background_task(description="Review 1", prompt="Review task 1 implementation", agent="reviewer") \u2192 review_id_1
|
|
933
|
+
background_task(description="Review 3", prompt="Review task 3 implementation", agent="reviewer") \u2192 review_id_3
|
|
934
|
+
|
|
935
|
+
## Step 3: Continue polling until all reviews complete
|
|
936
|
+
...
|
|
937
|
+
</execution-example>
|
|
938
|
+
|
|
817
939
|
<output-format>
|
|
818
940
|
<template>
|
|
819
941
|
## Execution Complete
|
|
@@ -848,11 +970,13 @@ Then after all complete, in ONE message call Task tool for reviewers:
|
|
|
848
970
|
</output-format>
|
|
849
971
|
|
|
850
972
|
<never-do>
|
|
973
|
+
<forbidden>NEVER call background_output on running tasks - always poll with background_list first</forbidden>
|
|
851
974
|
<forbidden>Never skip dependency analysis</forbidden>
|
|
852
975
|
<forbidden>Never spawn dependent tasks in parallel</forbidden>
|
|
853
976
|
<forbidden>Never skip reviewer for any task</forbidden>
|
|
854
977
|
<forbidden>Never continue past 3 cycles for a single task</forbidden>
|
|
855
978
|
<forbidden>Never report success if any task is blocked</forbidden>
|
|
979
|
+
<forbidden>Never wait for all implementers before starting any reviewer</forbidden>
|
|
856
980
|
</never-do>`
|
|
857
981
|
};
|
|
858
982
|
|
|
@@ -986,7 +1110,7 @@ var PROMPT2 = `
|
|
|
986
1110
|
|
|
987
1111
|
<critical-rule>
|
|
988
1112
|
MAXIMIZE PARALLELISM. Speed is critical.
|
|
989
|
-
-
|
|
1113
|
+
- Fire ALL background tasks simultaneously
|
|
990
1114
|
- Run multiple tool calls in single message
|
|
991
1115
|
- Never wait for one thing when you can do many
|
|
992
1116
|
</critical-rule>
|
|
@@ -999,16 +1123,33 @@ var PROMPT2 = `
|
|
|
999
1123
|
</outputs>
|
|
1000
1124
|
</task>
|
|
1001
1125
|
|
|
1002
|
-
<
|
|
1003
|
-
<
|
|
1004
|
-
|
|
1005
|
-
|
|
1126
|
+
<background-tools>
|
|
1127
|
+
<tool name="background_task">
|
|
1128
|
+
Fire a subagent to run in background. Returns task_id immediately.
|
|
1129
|
+
Parameters: description, prompt, agent (subagent type)
|
|
1130
|
+
Example: background_task(description="Find entry points", prompt="Find all entry points", agent="codebase-locator")
|
|
1131
|
+
</tool>
|
|
1132
|
+
<tool name="background_list">
|
|
1133
|
+
List all background tasks and their status. Use to poll for completion.
|
|
1134
|
+
No parameters required.
|
|
1135
|
+
</tool>
|
|
1136
|
+
<tool name="background_output">
|
|
1137
|
+
Get results from a completed task. Only call after background_list shows task is done.
|
|
1138
|
+
Parameters: task_id
|
|
1139
|
+
Example: background_output(task_id="abc123")
|
|
1140
|
+
</tool>
|
|
1141
|
+
</background-tools>
|
|
1142
|
+
|
|
1143
|
+
<parallel-execution-strategy pattern="fire-and-collect">
|
|
1144
|
+
<phase name="1-fire" description="Fire ALL tasks simultaneously">
|
|
1145
|
+
<description>Launch ALL discovery agents + run tools in a SINGLE message</description>
|
|
1146
|
+
<fire-agents>
|
|
1006
1147
|
<agent name="codebase-locator">Find entry points, configs, main modules</agent>
|
|
1007
1148
|
<agent name="codebase-locator">Find test files and test patterns</agent>
|
|
1008
1149
|
<agent name="codebase-locator">Find linter, formatter, CI configs</agent>
|
|
1009
1150
|
<agent name="codebase-analyzer">Analyze directory structure</agent>
|
|
1010
1151
|
<agent name="pattern-finder">Find naming conventions across files</agent>
|
|
1011
|
-
</
|
|
1152
|
+
</fire-agents>
|
|
1012
1153
|
<parallel-tools>
|
|
1013
1154
|
<tool>Glob for package.json, pyproject.toml, go.mod, Cargo.toml, etc.</tool>
|
|
1014
1155
|
<tool>Glob for *.config.*, .eslintrc*, .prettierrc*, ruff.toml, etc.</tool>
|
|
@@ -1017,13 +1158,20 @@ var PROMPT2 = `
|
|
|
1017
1158
|
</parallel-tools>
|
|
1018
1159
|
</phase>
|
|
1019
1160
|
|
|
1020
|
-
<phase name="2-
|
|
1021
|
-
<description>
|
|
1022
|
-
<
|
|
1161
|
+
<phase name="2-collect" description="Poll and collect all results">
|
|
1162
|
+
<description>Poll background_list until all tasks complete, then collect with background_output</description>
|
|
1163
|
+
<action>Poll background_list until all tasks show "completed"</action>
|
|
1164
|
+
<action>Call background_output for each completed task</action>
|
|
1165
|
+
<action>Process tool results from phase 1</action>
|
|
1166
|
+
</phase>
|
|
1167
|
+
|
|
1168
|
+
<phase name="3-deep-analysis" description="Fire deep analysis tasks">
|
|
1169
|
+
<description>Based on discovery, fire more background tasks</description>
|
|
1170
|
+
<fire-agents>
|
|
1023
1171
|
<agent name="codebase-analyzer">Analyze core/domain logic</agent>
|
|
1024
1172
|
<agent name="codebase-analyzer">Analyze API/entry points</agent>
|
|
1025
1173
|
<agent name="codebase-analyzer">Analyze data layer</agent>
|
|
1026
|
-
</
|
|
1174
|
+
</fire-agents>
|
|
1027
1175
|
<parallel-tools>
|
|
1028
1176
|
<tool>Read 5 core source files simultaneously</tool>
|
|
1029
1177
|
<tool>Read 3 test files simultaneously</tool>
|
|
@@ -1031,8 +1179,9 @@ var PROMPT2 = `
|
|
|
1031
1179
|
</parallel-tools>
|
|
1032
1180
|
</phase>
|
|
1033
1181
|
|
|
1034
|
-
<phase name="
|
|
1035
|
-
<description>
|
|
1182
|
+
<phase name="4-collect-and-write" description="Collect and write output">
|
|
1183
|
+
<description>Collect deep analysis results, then write both files</description>
|
|
1184
|
+
<action>Collect all deep analysis results</action>
|
|
1036
1185
|
<action>Write ARCHITECTURE.md</action>
|
|
1037
1186
|
<action>Write CODE_STYLE.md</action>
|
|
1038
1187
|
</phase>
|
|
@@ -1042,23 +1191,37 @@ var PROMPT2 = `
|
|
|
1042
1191
|
<subagent name="codebase-locator" spawn="multiple">
|
|
1043
1192
|
Fast file/pattern finder. Spawn multiple with different queries.
|
|
1044
1193
|
Examples: "Find all entry points", "Find all config files", "Find test directories"
|
|
1045
|
-
|
|
1194
|
+
|
|
1195
|
+
Background: background_task(description="Find entry points", prompt="Find all entry points and main files", agent="codebase-locator")
|
|
1196
|
+
Fallback: Task(description="Find entry points", prompt="Find all entry points and main files", subagent_type="codebase-locator")
|
|
1046
1197
|
</subagent>
|
|
1047
1198
|
<subagent name="codebase-analyzer" spawn="multiple">
|
|
1048
1199
|
Deep module analyzer. Spawn multiple for different areas.
|
|
1049
1200
|
Examples: "Analyze src/core", "Analyze api layer", "Analyze database module"
|
|
1050
|
-
|
|
1201
|
+
|
|
1202
|
+
Background: background_task(description="Analyze core", prompt="Analyze the core module", agent="codebase-analyzer")
|
|
1203
|
+
Fallback: Task(description="Analyze core", prompt="Analyze the core module", subagent_type="codebase-analyzer")
|
|
1051
1204
|
</subagent>
|
|
1052
1205
|
<subagent name="pattern-finder" spawn="multiple">
|
|
1053
1206
|
Pattern extractor. Spawn for different pattern types.
|
|
1054
1207
|
Examples: "Find naming patterns", "Find error handling patterns", "Find async patterns"
|
|
1055
|
-
|
|
1208
|
+
|
|
1209
|
+
Background: background_task(description="Find patterns", prompt="Find naming conventions", agent="pattern-finder")
|
|
1210
|
+
Fallback: Task(description="Find patterns", prompt="Find naming conventions", subagent_type="pattern-finder")
|
|
1056
1211
|
</subagent>
|
|
1057
1212
|
</available-subagents>
|
|
1058
1213
|
|
|
1214
|
+
<fallback-rule>
|
|
1215
|
+
If background_task fails or is unavailable, fall back to Task() tool.
|
|
1216
|
+
The Task tool provides synchronous subagent execution.
|
|
1217
|
+
Example fallback: Task(description="Find entry points", prompt="Find all entry points", subagent_type="codebase-locator")
|
|
1218
|
+
</fallback-rule>
|
|
1219
|
+
|
|
1059
1220
|
<critical-instruction>
|
|
1060
|
-
|
|
1061
|
-
|
|
1221
|
+
Use background_task to fire subagents for TRUE parallelism.
|
|
1222
|
+
Fire ALL background_task calls in a SINGLE message.
|
|
1223
|
+
Then poll with background_list until all complete, and collect with background_output.
|
|
1224
|
+
This is the fire-and-collect pattern - fire everything, poll, then collect everything.
|
|
1062
1225
|
</critical-instruction>
|
|
1063
1226
|
|
|
1064
1227
|
<language-detection>
|
|
@@ -1124,10 +1287,10 @@ var PROMPT2 = `
|
|
|
1124
1287
|
|
|
1125
1288
|
<rules>
|
|
1126
1289
|
<category name="Speed">
|
|
1127
|
-
<rule>ALWAYS
|
|
1290
|
+
<rule>ALWAYS fire multiple background_task calls in a SINGLE message</rule>
|
|
1128
1291
|
<rule>ALWAYS run multiple tool calls in a SINGLE message</rule>
|
|
1129
1292
|
<rule>NEVER wait for one task when you can start others</rule>
|
|
1130
|
-
<rule>
|
|
1293
|
+
<rule>Use fire-and-collect: fire all, then collect all</rule>
|
|
1131
1294
|
</category>
|
|
1132
1295
|
|
|
1133
1296
|
<category name="Analysis">
|
|
@@ -1152,27 +1315,40 @@ var PROMPT2 = `
|
|
|
1152
1315
|
</category>
|
|
1153
1316
|
</rules>
|
|
1154
1317
|
|
|
1155
|
-
<execution-example>
|
|
1156
|
-
<step description="
|
|
1157
|
-
In a SINGLE message,
|
|
1158
|
-
-
|
|
1159
|
-
-
|
|
1160
|
-
-
|
|
1161
|
-
-
|
|
1162
|
-
-
|
|
1318
|
+
<execution-example pattern="fire-and-collect">
|
|
1319
|
+
<step description="FIRE: Launch all discovery tasks simultaneously">
|
|
1320
|
+
In a SINGLE message, fire ALL background_task calls AND run other tools:
|
|
1321
|
+
- background_task(description="Find entry points", prompt="Find all entry points and main files", agent="codebase-locator") -> task_id_1
|
|
1322
|
+
- background_task(description="Find configs", prompt="Find all config files (linters, formatters, build)", agent="codebase-locator") -> task_id_2
|
|
1323
|
+
- background_task(description="Find tests", prompt="Find test directories and test files", agent="codebase-locator") -> task_id_3
|
|
1324
|
+
- background_task(description="Analyze structure", prompt="Analyze the directory structure and organization", agent="codebase-analyzer") -> task_id_4
|
|
1325
|
+
- background_task(description="Find patterns", prompt="Find naming conventions used across the codebase", agent="pattern-finder") -> task_id_5
|
|
1163
1326
|
- Glob: package.json, pyproject.toml, go.mod, Cargo.toml, etc.
|
|
1164
1327
|
- Glob: README*, ARCHITECTURE*, docs/*
|
|
1165
1328
|
</step>
|
|
1166
1329
|
|
|
1167
|
-
<step description="
|
|
1168
|
-
|
|
1169
|
-
-
|
|
1330
|
+
<step description="COLLECT: Poll and gather all results">
|
|
1331
|
+
First poll until all tasks complete:
|
|
1332
|
+
- background_list() // repeat until all show "completed"
|
|
1333
|
+
Then collect ALL results:
|
|
1334
|
+
- background_output(task_id=task_id_1)
|
|
1335
|
+
- background_output(task_id=task_id_2)
|
|
1336
|
+
- background_output(task_id=task_id_3)
|
|
1337
|
+
- background_output(task_id=task_id_4)
|
|
1338
|
+
- background_output(task_id=task_id_5)
|
|
1339
|
+
</step>
|
|
1340
|
+
|
|
1341
|
+
<step description="FIRE: Deep analysis based on discovery">
|
|
1342
|
+
Based on discovery, in a SINGLE message fire more tasks:
|
|
1343
|
+
- background_task for each major module: agent="codebase-analyzer"
|
|
1170
1344
|
- Read multiple source files simultaneously
|
|
1171
1345
|
- Read multiple test files simultaneously
|
|
1172
1346
|
</step>
|
|
1173
1347
|
|
|
1174
|
-
<step description="
|
|
1175
|
-
|
|
1348
|
+
<step description="COLLECT and WRITE">
|
|
1349
|
+
Collect deep analysis results, then write:
|
|
1350
|
+
- Write ARCHITECTURE.md
|
|
1351
|
+
- Write CODE_STYLE.md
|
|
1176
1352
|
</step>
|
|
1177
1353
|
</execution-example>
|
|
1178
1354
|
</agent>
|
|
@@ -15495,6 +15671,7 @@ function createArtifactAutoIndexHook(_ctx) {
|
|
|
15495
15671
|
|
|
15496
15672
|
// src/tools/background-task/manager.ts
|
|
15497
15673
|
var POLL_INTERVAL_MS = 2000;
|
|
15674
|
+
var TASK_TTL_MS = 60 * 60 * 1000;
|
|
15498
15675
|
function generateTaskId() {
|
|
15499
15676
|
const chars = "abcdefghijklmnopqrstuvwxyz0123456789";
|
|
15500
15677
|
let result = "bg_";
|
|
@@ -15556,6 +15733,7 @@ class BackgroundTaskManager {
|
|
|
15556
15733
|
},
|
|
15557
15734
|
query: { directory: this.ctx.directory }
|
|
15558
15735
|
}).catch((error45) => {
|
|
15736
|
+
console.error(`[background-task] Failed to prompt session ${sessionID}:`, error45);
|
|
15559
15737
|
task.status = "error";
|
|
15560
15738
|
task.error = error45 instanceof Error ? error45.message : String(error45);
|
|
15561
15739
|
task.completedAt = new Date;
|
|
@@ -15573,7 +15751,9 @@ class BackgroundTaskManager {
|
|
|
15573
15751
|
this.ctx.client.session.abort({
|
|
15574
15752
|
path: { id: task.sessionID },
|
|
15575
15753
|
query: { directory: this.ctx.directory }
|
|
15576
|
-
}).catch(() => {
|
|
15754
|
+
}).catch((error45) => {
|
|
15755
|
+
console.error(`[background-task] Failed to abort session ${task.sessionID}:`, error45);
|
|
15756
|
+
});
|
|
15577
15757
|
task.status = "cancelled";
|
|
15578
15758
|
task.completedAt = new Date;
|
|
15579
15759
|
this.markForNotification(task);
|
|
@@ -15615,20 +15795,18 @@ class BackgroundTaskManager {
|
|
|
15615
15795
|
path: { id: task.sessionID },
|
|
15616
15796
|
query: { directory: this.ctx.directory }
|
|
15617
15797
|
});
|
|
15618
|
-
const
|
|
15619
|
-
const
|
|
15620
|
-
|
|
15621
|
-
const info = msg.info;
|
|
15622
|
-
return info?.role === "assistant";
|
|
15623
|
-
});
|
|
15798
|
+
const messagesResp = resp;
|
|
15799
|
+
const messages = messagesResp.data || [];
|
|
15800
|
+
const lastAssistant = [...messages].reverse().find((m) => m.info?.role === "assistant");
|
|
15624
15801
|
if (lastAssistant) {
|
|
15625
|
-
const
|
|
15626
|
-
const textParts = parts?.filter((p) => p.type === "text") || [];
|
|
15802
|
+
const textParts = lastAssistant.parts?.filter((p) => p.type === "text") || [];
|
|
15627
15803
|
task.result = textParts.map((p) => p.text || "").join(`
|
|
15628
15804
|
`);
|
|
15629
15805
|
return task.result;
|
|
15630
15806
|
}
|
|
15631
|
-
} catch {
|
|
15807
|
+
} catch (error45) {
|
|
15808
|
+
console.error(`[background-task] Failed to fetch result for task ${taskId}:`, error45);
|
|
15809
|
+
}
|
|
15632
15810
|
return;
|
|
15633
15811
|
}
|
|
15634
15812
|
formatTaskStatus(task) {
|
|
@@ -15660,13 +15838,6 @@ class BackgroundTaskManager {
|
|
|
15660
15838
|
output += `
|
|
15661
15839
|
### Error
|
|
15662
15840
|
${task.error}
|
|
15663
|
-
`;
|
|
15664
|
-
}
|
|
15665
|
-
if (task.progress?.lastMessage) {
|
|
15666
|
-
const preview = task.progress.lastMessage.length > 200 ? `${task.progress.lastMessage.slice(0, 200)}...` : task.progress.lastMessage;
|
|
15667
|
-
output += `
|
|
15668
|
-
### Last Message Preview
|
|
15669
|
-
${preview}
|
|
15670
15841
|
`;
|
|
15671
15842
|
}
|
|
15672
15843
|
return output;
|
|
@@ -15684,7 +15855,19 @@ ${preview}
|
|
|
15684
15855
|
this.pollingInterval = undefined;
|
|
15685
15856
|
}
|
|
15686
15857
|
}
|
|
15858
|
+
cleanupOldTasks() {
|
|
15859
|
+
const now = Date.now();
|
|
15860
|
+
for (const [taskId, task] of this.tasks) {
|
|
15861
|
+
if (task.status === "running")
|
|
15862
|
+
continue;
|
|
15863
|
+
const completedAt = task.completedAt?.getTime() || 0;
|
|
15864
|
+
if (now - completedAt > TASK_TTL_MS) {
|
|
15865
|
+
this.tasks.delete(taskId);
|
|
15866
|
+
}
|
|
15867
|
+
}
|
|
15868
|
+
}
|
|
15687
15869
|
async pollRunningTasks() {
|
|
15870
|
+
this.cleanupOldTasks();
|
|
15688
15871
|
const runningTasks = this.getRunningTasks();
|
|
15689
15872
|
if (runningTasks.length === 0) {
|
|
15690
15873
|
this.stopPolling();
|
|
@@ -15710,9 +15893,12 @@ ${preview}
|
|
|
15710
15893
|
variant: "success",
|
|
15711
15894
|
duration: 5000
|
|
15712
15895
|
}
|
|
15713
|
-
}).catch(() => {
|
|
15896
|
+
}).catch((error45) => {
|
|
15897
|
+
console.error(`[background-task] Failed to show toast for task ${task.id}:`, error45);
|
|
15898
|
+
});
|
|
15714
15899
|
}
|
|
15715
|
-
} catch {
|
|
15900
|
+
} catch (error45) {
|
|
15901
|
+
console.error(`[background-task] Failed to poll task ${task.id}:`, error45);
|
|
15716
15902
|
if (task.status === "running") {
|
|
15717
15903
|
task.status = "error";
|
|
15718
15904
|
task.error = "Session lost";
|
|
@@ -15801,27 +15987,17 @@ Use \`background_output\` with task_id="${task.id}" to check progress or get res
|
|
|
15801
15987
|
}
|
|
15802
15988
|
});
|
|
15803
15989
|
const background_output = tool({
|
|
15804
|
-
description: `
|
|
15805
|
-
|
|
15806
|
-
Set block=true to wait for completion (with timeout).`,
|
|
15990
|
+
description: `Get status or results from a background task.
|
|
15991
|
+
Returns immediately with current status. Use background_list to poll for completion.`,
|
|
15807
15992
|
args: {
|
|
15808
|
-
task_id: tool.schema.string().describe("ID of the task to check (e.g., 'bg_abc12345')")
|
|
15809
|
-
block: tool.schema.boolean().optional().describe("Wait for task completion (default: false)"),
|
|
15810
|
-
timeout: tool.schema.number().optional().describe("Max seconds to wait if blocking (default: 60, max: 600)")
|
|
15993
|
+
task_id: tool.schema.string().describe("ID of the task to check (e.g., 'bg_abc12345')")
|
|
15811
15994
|
},
|
|
15812
15995
|
execute: async (args) => {
|
|
15813
|
-
const { task_id
|
|
15996
|
+
const { task_id } = args;
|
|
15814
15997
|
const task = manager.getTask(task_id);
|
|
15815
15998
|
if (!task) {
|
|
15816
15999
|
return `Task not found: ${task_id}`;
|
|
15817
16000
|
}
|
|
15818
|
-
if (block && task.status === "running") {
|
|
15819
|
-
const maxWait = Math.min(timeout || 60, 600) * 1000;
|
|
15820
|
-
const startTime = Date.now();
|
|
15821
|
-
while (task.status === "running" && Date.now() - startTime < maxWait) {
|
|
15822
|
-
await new Promise((resolve2) => setTimeout(resolve2, 1000));
|
|
15823
|
-
}
|
|
15824
|
-
}
|
|
15825
16001
|
let output = manager.formatTaskStatus(task);
|
|
15826
16002
|
if (task.status === "completed") {
|
|
15827
16003
|
const result = await manager.getTaskResult(task_id);
|
|
@@ -16,6 +16,7 @@ export declare class BackgroundTaskManager {
|
|
|
16
16
|
formatTaskStatus(task: BackgroundTask): string;
|
|
17
17
|
private startPolling;
|
|
18
18
|
private stopPolling;
|
|
19
|
+
private cleanupOldTasks;
|
|
19
20
|
private pollRunningTasks;
|
|
20
21
|
private markForNotification;
|
|
21
22
|
getPendingNotifications(parentSessionID: string): BackgroundTask[];
|
|
@@ -17,13 +17,9 @@ export declare function createBackgroundTaskTools(manager: BackgroundTaskManager
|
|
|
17
17
|
description: string;
|
|
18
18
|
args: {
|
|
19
19
|
task_id: import("zod").ZodString;
|
|
20
|
-
block: import("zod").ZodOptional<import("zod").ZodBoolean>;
|
|
21
|
-
timeout: import("zod").ZodOptional<import("zod").ZodNumber>;
|
|
22
20
|
};
|
|
23
21
|
execute(args: {
|
|
24
22
|
task_id: string;
|
|
25
|
-
block?: boolean | undefined;
|
|
26
|
-
timeout?: number | undefined;
|
|
27
23
|
}, context: import("@opencode-ai/plugin").ToolContext): Promise<string>;
|
|
28
24
|
};
|
|
29
25
|
background_cancel: {
|
|
@@ -15,7 +15,6 @@ export interface BackgroundTask {
|
|
|
15
15
|
toolCalls: number;
|
|
16
16
|
lastTool?: string;
|
|
17
17
|
lastUpdate: Date;
|
|
18
|
-
lastMessage?: string;
|
|
19
18
|
};
|
|
20
19
|
}
|
|
21
20
|
export interface BackgroundTaskInput {
|
|
@@ -25,3 +24,30 @@ export interface BackgroundTaskInput {
|
|
|
25
24
|
parentSessionID: string;
|
|
26
25
|
parentMessageID: string;
|
|
27
26
|
}
|
|
27
|
+
export interface SessionCreateResponse {
|
|
28
|
+
data?: {
|
|
29
|
+
id?: string;
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
export interface SessionGetResponse {
|
|
33
|
+
data?: {
|
|
34
|
+
status?: "idle" | "running" | "error";
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
export interface MessagePart {
|
|
38
|
+
type: string;
|
|
39
|
+
text?: string;
|
|
40
|
+
}
|
|
41
|
+
export interface MessageInfo {
|
|
42
|
+
role?: "user" | "assistant";
|
|
43
|
+
sessionID?: string;
|
|
44
|
+
type?: string;
|
|
45
|
+
name?: string;
|
|
46
|
+
}
|
|
47
|
+
export interface SessionMessage {
|
|
48
|
+
info?: MessageInfo;
|
|
49
|
+
parts?: MessagePart[];
|
|
50
|
+
}
|
|
51
|
+
export interface SessionMessagesResponse {
|
|
52
|
+
data?: SessionMessage[];
|
|
53
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "micode",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "OpenCode plugin with Brainstorm-Research-Plan-Implement workflow",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"url": "https://github.com/vtemian/micode/issues"
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
|
-
"@opencode-ai/plugin": "^1.0.
|
|
47
|
+
"@opencode-ai/plugin": "^1.0.224"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
50
|
"@biomejs/biome": "^2.3.10",
|