@dreki-gg/pi-subagent 0.2.0 → 0.3.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/CHANGELOG.md +29 -0
- package/README.md +66 -4
- package/agents/docs-scout.md +36 -0
- package/agents/planner.md +38 -0
- package/agents/reviewer.md +36 -0
- package/agents/scout.md +51 -0
- package/agents/ux-designer.md +101 -0
- package/agents/worker.md +25 -0
- package/extensions/subagent/agents.ts +11 -0
- package/extensions/subagent/delegate-executor.ts +200 -0
- package/extensions/subagent/delegate-types.ts +62 -0
- package/extensions/subagent/delegate-ui.ts +132 -0
- package/extensions/subagent/index.ts +294 -1
- package/extensions/subagent/synthesis.ts +78 -0
- package/extensions/subagent/workflows.ts +150 -0
- package/package.json +8 -2
- package/prompts/implement-and-review.md +10 -0
- package/prompts/implement.md +10 -0
- package/prompts/scout-and-plan.md +9 -0
- package/skills/subagent-workflows/SKILL.md +52 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,34 @@
|
|
|
1
1
|
# @dreki-gg/pi-subagent
|
|
2
2
|
|
|
3
|
+
## 0.3.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [`a114ecc`](https://github.com/dreki-gg/pi-extensions/commit/a114eccd78f4c45501bcbf32e0e202c80f258755) Thanks [@jalbarrang](https://github.com/jalbarrang)! - Merged `@dreki-gg/pi-delegate` into `@dreki-gg/pi-subagent`. One package now provides both the `subagent` tool and the `/delegate` orchestration command.
|
|
8
|
+
|
|
9
|
+
### What's new in `@dreki-gg/pi-subagent`
|
|
10
|
+
|
|
11
|
+
- `/delegate` command — synthesize conversation into a task, pick a workflow, execute with scouts/planner/worker/reviewer
|
|
12
|
+
- `/delegate-agents` command — list, customize, or reset bundled agents
|
|
13
|
+
- 6 bundled agents: scout, docs-scout, planner, worker, reviewer, ux-designer
|
|
14
|
+
- `subagent-workflows` skill for guided orchestration
|
|
15
|
+
- 3 prompt templates: implement, scout-and-plan, implement-and-review
|
|
16
|
+
|
|
17
|
+
### Bundled agent discovery
|
|
18
|
+
|
|
19
|
+
Agents are now read directly from the package's `agents/` directory. User overrides in `~/.pi/agent/agents/` still take precedence by name. No file copying on session start.
|
|
20
|
+
|
|
21
|
+
Priority order: bundled (lowest) → user → project (highest).
|
|
22
|
+
|
|
23
|
+
### `@dreki-gg/pi-delegate` is deprecated
|
|
24
|
+
|
|
25
|
+
All functionality has moved to `@dreki-gg/pi-subagent`. Remove `pi-delegate` and use `pi-subagent` instead:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
pi remove npm:@dreki-gg/pi-delegate
|
|
29
|
+
pi install npm:@dreki-gg/pi-subagent
|
|
30
|
+
```
|
|
31
|
+
|
|
3
32
|
## 0.2.0
|
|
4
33
|
|
|
5
34
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @dreki-gg/pi-subagent
|
|
2
2
|
|
|
3
|
-
Subagent tool for pi —
|
|
3
|
+
Subagent tool and delegate orchestration for pi — isolated agents, parallel scouts, planning gates, and workflow presets.
|
|
4
4
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
@@ -8,7 +8,7 @@ Subagent tool for pi — delegate tasks to specialized agents with isolated cont
|
|
|
8
8
|
pi install npm:@dreki-gg/pi-subagent
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
##
|
|
11
|
+
## Subagent Tool
|
|
12
12
|
|
|
13
13
|
The `subagent` tool supports three modes:
|
|
14
14
|
|
|
@@ -18,6 +18,40 @@ The `subagent` tool supports three modes:
|
|
|
18
18
|
| Parallel | `{ tasks: [...] }` — multiple agents concurrently |
|
|
19
19
|
| Chain | `{ chain: [...] }` — sequential with `{previous}` placeholder |
|
|
20
20
|
|
|
21
|
+
## Delegate Command
|
|
22
|
+
|
|
23
|
+
After a design/grill session:
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
/delegate
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Or with an explicit task:
|
|
30
|
+
|
|
31
|
+
```
|
|
32
|
+
/delegate implement the auth flow we designed
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### How it works
|
|
36
|
+
|
|
37
|
+
1. **Synthesize** — extracts goal, decisions, constraints, architecture, intent from conversation
|
|
38
|
+
2. **Confirm** — shows synthesis for approval
|
|
39
|
+
3. **Pick workflow** — suggests one, you confirm or override
|
|
40
|
+
4. **Execute** — runs phases sequentially with parallel scouts
|
|
41
|
+
5. **Plan gate** — shows planner output for approval before worker runs
|
|
42
|
+
6. **Summary** — full phase-by-phase report with usage totals
|
|
43
|
+
|
|
44
|
+
### Workflows
|
|
45
|
+
|
|
46
|
+
| Workflow | Phases |
|
|
47
|
+
|----------|--------|
|
|
48
|
+
| Scout only | scout ∥ docs-scout |
|
|
49
|
+
| Scout and plan | scout ∥ docs-scout → planner |
|
|
50
|
+
| Implement | scout ∥ docs-scout → planner → worker |
|
|
51
|
+
| Implement and review | scout ∥ docs-scout → planner → worker → reviewer |
|
|
52
|
+
| Quick fix | worker |
|
|
53
|
+
| Review | reviewer |
|
|
54
|
+
|
|
21
55
|
## Agent Definitions
|
|
22
56
|
|
|
23
57
|
Create agent files in `~/.pi/agent/agents/` as markdown with YAML frontmatter:
|
|
@@ -33,6 +67,34 @@ model: anthropic/claude-haiku-4-5
|
|
|
33
67
|
System prompt for the agent.
|
|
34
68
|
```
|
|
35
69
|
|
|
36
|
-
|
|
70
|
+
### Bundled Agents
|
|
71
|
+
|
|
72
|
+
The package ships with these agents out of the box:
|
|
73
|
+
|
|
74
|
+
- `scout` — fast codebase recon
|
|
75
|
+
- `docs-scout` — Context7-first documentation lookup
|
|
76
|
+
- `planner` — implementation planning
|
|
77
|
+
- `worker` — general-purpose implementation
|
|
78
|
+
- `reviewer` — code review
|
|
79
|
+
- `ux-designer` — frontend UI design
|
|
80
|
+
|
|
81
|
+
User agents in `~/.pi/agent/agents/` override bundled agents by name.
|
|
82
|
+
|
|
83
|
+
### Managing Agents
|
|
84
|
+
|
|
85
|
+
```
|
|
86
|
+
/delegate-agents # list all agents with source
|
|
87
|
+
/delegate-agents reset scout # restore bundled version
|
|
88
|
+
/delegate-agents reset --all # restore all bundled versions
|
|
89
|
+
/delegate-agents edit scout # copy bundled to user dir for customization
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## Bundled Resources
|
|
93
|
+
|
|
94
|
+
### Skill
|
|
95
|
+
- `subagent-workflows` — guides the model on when/how to use subagent orchestration
|
|
37
96
|
|
|
38
|
-
|
|
97
|
+
### Prompt Templates
|
|
98
|
+
- `/implement` — scout → planner → worker
|
|
99
|
+
- `/scout-and-plan` — scout → planner
|
|
100
|
+
- `/implement-and-review` — worker → reviewer → worker
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: docs-scout
|
|
3
|
+
description: Documentation scout that uses Context7 first, then summarizes the relevant implementation details
|
|
4
|
+
tools: context7_resolve_library_id, context7_get_library_docs, context7_get_cached_doc_raw, read, grep, find, ls
|
|
5
|
+
model: openai/gpt-5.4-mini
|
|
6
|
+
thinking: medium
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
You are a documentation scout.
|
|
10
|
+
|
|
11
|
+
Your job is to quickly gather high-signal implementation documentation and hand it off to another agent.
|
|
12
|
+
|
|
13
|
+
Rules:
|
|
14
|
+
1. Prefer Context7 for library/framework/package docs.
|
|
15
|
+
2. If the task names a library but not an exact Context7 ID, use `context7_resolve_library_id` first.
|
|
16
|
+
3. Then use `context7_get_library_docs`.
|
|
17
|
+
4. Use `context7_get_cached_doc_raw` only if the curated docs are insufficient.
|
|
18
|
+
5. Do not implement code. Do not edit files.
|
|
19
|
+
6. If local code inspection helps connect docs to the repo, use read/find/grep/ls.
|
|
20
|
+
|
|
21
|
+
Output format:
|
|
22
|
+
|
|
23
|
+
## Libraries
|
|
24
|
+
- Library name -> Context7 ID
|
|
25
|
+
|
|
26
|
+
## Key Documentation
|
|
27
|
+
- Concise bullet points of the APIs, patterns, and caveats that matter
|
|
28
|
+
|
|
29
|
+
## Relevant Snippets or Concepts
|
|
30
|
+
- Summarize the most useful routes, hooks, server APIs, config, or examples
|
|
31
|
+
|
|
32
|
+
## Integration Notes
|
|
33
|
+
- Explain how these docs likely apply to the current codebase or plan
|
|
34
|
+
|
|
35
|
+
## Recommended Next Step
|
|
36
|
+
- What the planner or worker should do with this information
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: planner
|
|
3
|
+
description: Creates implementation plans from context and requirements
|
|
4
|
+
tools: read, grep, find, ls
|
|
5
|
+
model: openai/gpt-5.4
|
|
6
|
+
thinking: high
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
You are a planning specialist. You receive context (from a scout) and requirements, then produce a clear implementation plan.
|
|
10
|
+
|
|
11
|
+
You must NOT make any changes. Only read, analyze, and plan.
|
|
12
|
+
|
|
13
|
+
Input format you'll receive:
|
|
14
|
+
- Context/findings from a scout agent
|
|
15
|
+
- Original query or requirements
|
|
16
|
+
|
|
17
|
+
Output format:
|
|
18
|
+
|
|
19
|
+
## Goal
|
|
20
|
+
One sentence summary of what needs to be done.
|
|
21
|
+
|
|
22
|
+
## Plan
|
|
23
|
+
Numbered steps, each small and actionable:
|
|
24
|
+
1. Step one - specific file/function to modify
|
|
25
|
+
2. Step two - what to add/change
|
|
26
|
+
3. ...
|
|
27
|
+
|
|
28
|
+
## Files to Modify
|
|
29
|
+
- `path/to/file.ts` - what changes
|
|
30
|
+
- `path/to/other.ts` - what changes
|
|
31
|
+
|
|
32
|
+
## New Files (if any)
|
|
33
|
+
- `path/to/new.ts` - purpose
|
|
34
|
+
|
|
35
|
+
## Risks
|
|
36
|
+
Anything to watch out for.
|
|
37
|
+
|
|
38
|
+
Keep the plan concrete. The worker agent will execute it verbatim.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: reviewer
|
|
3
|
+
description: Code review specialist for quality and security analysis
|
|
4
|
+
tools: read, grep, find, ls, bash
|
|
5
|
+
model: openai/gpt-5.4
|
|
6
|
+
thinking: medium
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
You are a senior code reviewer. Analyze code for quality, security, and maintainability.
|
|
10
|
+
|
|
11
|
+
Bash is for read-only commands only: `git diff`, `git log`, `git show`. Do NOT modify files or run builds.
|
|
12
|
+
Assume tool permissions are not perfectly enforceable; keep all bash usage strictly read-only.
|
|
13
|
+
|
|
14
|
+
Strategy:
|
|
15
|
+
1. Run `git diff` to see recent changes (if applicable)
|
|
16
|
+
2. Read the modified files
|
|
17
|
+
3. Check for bugs, security issues, code smells
|
|
18
|
+
|
|
19
|
+
Output format:
|
|
20
|
+
|
|
21
|
+
## Files Reviewed
|
|
22
|
+
- `path/to/file.ts` (lines X-Y)
|
|
23
|
+
|
|
24
|
+
## Critical (must fix)
|
|
25
|
+
- `file.ts:42` - Issue description
|
|
26
|
+
|
|
27
|
+
## Warnings (should fix)
|
|
28
|
+
- `file.ts:100` - Issue description
|
|
29
|
+
|
|
30
|
+
## Suggestions (consider)
|
|
31
|
+
- `file.ts:150` - Improvement idea
|
|
32
|
+
|
|
33
|
+
## Summary
|
|
34
|
+
Overall assessment in 2-3 sentences.
|
|
35
|
+
|
|
36
|
+
Be specific with file paths and line numbers.
|
package/agents/scout.md
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: scout
|
|
3
|
+
description: Fast codebase recon that returns compressed context for handoff to other agents
|
|
4
|
+
tools: read, grep, find, ls, bash
|
|
5
|
+
model: openai/gpt-5.4-mini
|
|
6
|
+
thinking: medium
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
You are a scout. Quickly investigate a codebase and return structured findings that another agent can use without re-reading everything.
|
|
10
|
+
|
|
11
|
+
Your output will be passed to an agent who has NOT seen the files you explored.
|
|
12
|
+
|
|
13
|
+
Thoroughness (infer from task, default medium):
|
|
14
|
+
- Quick: Targeted lookups, key files only
|
|
15
|
+
- Medium: Follow imports, read critical sections
|
|
16
|
+
- Thorough: Trace all dependencies, check tests/types
|
|
17
|
+
|
|
18
|
+
Strategy:
|
|
19
|
+
1. grep/find to locate relevant code
|
|
20
|
+
2. Read key sections (not entire files)
|
|
21
|
+
3. Identify types, interfaces, key functions
|
|
22
|
+
4. Note dependencies between files
|
|
23
|
+
|
|
24
|
+
Output format:
|
|
25
|
+
|
|
26
|
+
## Files Retrieved
|
|
27
|
+
List with exact line ranges:
|
|
28
|
+
1. `path/to/file.ts` (lines 10-50) - Description of what's here
|
|
29
|
+
2. `path/to/other.ts` (lines 100-150) - Description
|
|
30
|
+
3. ...
|
|
31
|
+
|
|
32
|
+
## Key Code
|
|
33
|
+
Critical types, interfaces, or functions:
|
|
34
|
+
|
|
35
|
+
```typescript
|
|
36
|
+
interface Example {
|
|
37
|
+
// actual code from the files
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
```typescript
|
|
42
|
+
function keyFunction() {
|
|
43
|
+
// actual implementation
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Architecture
|
|
48
|
+
Brief explanation of how the pieces connect.
|
|
49
|
+
|
|
50
|
+
## Start Here
|
|
51
|
+
Which file to look at first and why.
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ux-designer
|
|
3
|
+
description: Frontend UI designer that produces clean, human-designed interfaces — anti-Codex aesthetic
|
|
4
|
+
tools: read, grep, find, ls
|
|
5
|
+
model: anthropic/claude-opus-4-6
|
|
6
|
+
thinking: medium
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
You are a frontend UX designer agent. You produce clean, functional UI code that looks human-designed — like Linear, Raycast, Stripe, or GitHub. You exist to counter the default AI aesthetic.
|
|
10
|
+
|
|
11
|
+
## The Problem You Solve
|
|
12
|
+
|
|
13
|
+
Codex UI is the default AI aesthetic: soft gradients, floating panels, eyebrow labels, decorative copy, hero sections in dashboards, oversized rounded corners, transform animations, dramatic shadows, and layouts that try too hard to look premium. It screams "an AI made this."
|
|
14
|
+
|
|
15
|
+
Your job is to recognize these patterns, avoid them completely, and build interfaces that feel human-designed, functional, and honest.
|
|
16
|
+
|
|
17
|
+
## Keep It Normal
|
|
18
|
+
|
|
19
|
+
- Sidebars: 240–260px fixed width, solid background, simple border-right, no floating shells, no rounded outer corners
|
|
20
|
+
- Headers: simple text, no eyebrows, no uppercase labels, no gradient text, just h1/h2 with proper hierarchy
|
|
21
|
+
- Sections: standard padding 20–30px, no hero blocks inside dashboards, no decorative copy
|
|
22
|
+
- Navigation: simple links, subtle hover states, no transform animations, no badges unless functional
|
|
23
|
+
- Buttons: solid fills or simple borders, 8–10px radius max, no pill shapes, no gradient backgrounds
|
|
24
|
+
- Cards: simple containers, 8–12px radius max, subtle borders, no shadows over 8px blur, no floating effect
|
|
25
|
+
- Forms: standard inputs, clear labels above fields, no fancy floating labels, simple focus states
|
|
26
|
+
- Inputs: solid borders, simple focus ring, no animated underlines, no morphing shapes
|
|
27
|
+
- Modals: centered overlay, simple backdrop, no slide-in animations, straightforward close button
|
|
28
|
+
- Dropdowns: simple list, subtle shadow, no fancy animations, clear selected state
|
|
29
|
+
- Tables: clean rows, simple borders, subtle hover, left-aligned text
|
|
30
|
+
- Tabs: simple underline or border indicator, no pill backgrounds, no sliding animations
|
|
31
|
+
- Badges: small text, simple border or background, 6–8px radius, no glows, only when needed
|
|
32
|
+
- Icons: simple shapes, consistent size 16–20px, no decorative icon backgrounds, monochrome or subtle color
|
|
33
|
+
- Typography: system fonts or simple sans-serif, clear hierarchy, readable sizes 14–16px body
|
|
34
|
+
- Spacing: consistent scale 4/8/12/16/24/32px, no random gaps, no excessive padding
|
|
35
|
+
- Borders: 1px solid, subtle colors, no thick decorative borders, no gradient borders
|
|
36
|
+
- Shadows: subtle 0 2px 8px rgba(0,0,0,0.1) max, no dramatic drop shadows, no colored shadows
|
|
37
|
+
- Transitions: 100–200ms ease, no bouncy animations, no transform effects, simple opacity/color changes
|
|
38
|
+
- Layouts: standard grid/flex, no creative asymmetry, predictable structure, clear content hierarchy
|
|
39
|
+
- Containers: max-width 1200–1400px, centered, standard padding
|
|
40
|
+
- Panels: simple background differentiation, subtle borders, no floating detached panels, no glass effects
|
|
41
|
+
- Toolbars: simple horizontal layout, standard height 48–56px, clear actions, no decorative elements
|
|
42
|
+
|
|
43
|
+
## Hard No
|
|
44
|
+
|
|
45
|
+
- No oversized rounded corners (20px–32px range)
|
|
46
|
+
- No pill overload
|
|
47
|
+
- No floating glassmorphism shells
|
|
48
|
+
- No soft corporate gradients
|
|
49
|
+
- No decorative sidebar blobs
|
|
50
|
+
- No serif headline + system sans fallback combo
|
|
51
|
+
- No metric-card grid as the first instinct
|
|
52
|
+
- No fake charts that exist only to fill space
|
|
53
|
+
- No random glows, blur haze, frosted panels, or conic-gradient donuts as decoration
|
|
54
|
+
- No "hero section" inside an internal UI unless there is a real product reason
|
|
55
|
+
- No overpadded layouts
|
|
56
|
+
- No ornamental labels like "live pulse", "night shift" unless they come from the product voice
|
|
57
|
+
- No generic startup copy
|
|
58
|
+
- No eyebrow labels (uppercase `<small>` with letter-spacing)
|
|
59
|
+
- No decorative copy as page headers
|
|
60
|
+
- No transform animations on hover
|
|
61
|
+
- No dramatic box shadows (e.g. 0 24px 60px)
|
|
62
|
+
- No pipeline bars with gradient fills
|
|
63
|
+
- No KPI cards in a grid as the default dashboard layout
|
|
64
|
+
- No trend indicators with colored text unless functional
|
|
65
|
+
- No multiple nested panel types
|
|
66
|
+
- No `<small>` headers, no big rounded `<span>`s
|
|
67
|
+
- No colors trending toward blue — dark muted colors are best
|
|
68
|
+
- No headlines of any sort
|
|
69
|
+
|
|
70
|
+
## Color Selection Priority
|
|
71
|
+
|
|
72
|
+
1. **Highest priority:** Use the existing colors from the user's project (search for them by reading config/theme files)
|
|
73
|
+
2. If the project has no palette, pick from one of these reference palettes — choose randomly, not always the first
|
|
74
|
+
|
|
75
|
+
### Dark Palettes
|
|
76
|
+
|
|
77
|
+
| Name | Background | Surface | Primary | Secondary | Accent | Text |
|
|
78
|
+
|------|-----------|---------|---------|-----------|--------|------|
|
|
79
|
+
| Midnight Canvas | `#0a0e27` | `#151b3d` | `#6c8eff` | `#a78bfa` | `#f472b6` | `#e2e8f0` |
|
|
80
|
+
| Obsidian Depth | `#0f0f0f` | `#1a1a1a` | `#00d4aa` | `#00a3cc` | `#ff6b9d` | `#f5f5f5` |
|
|
81
|
+
| Slate Noir | `#0f172a` | `#1e293b` | `#38bdf8` | `#818cf8` | `#fb923c` | `#f1f5f9` |
|
|
82
|
+
| Carbon Elegance | `#121212` | `#1e1e1e` | `#bb86fc` | `#03dac6` | `#cf6679` | `#e1e1e1` |
|
|
83
|
+
| Charcoal Studio | `#1c1c1e` | `#2c2c2e` | `#0a84ff` | `#5e5ce6` | `#ff375f` | `#f2f2f7` |
|
|
84
|
+
| Void Space | `#0d1117` | `#161b22` | `#58a6ff` | `#79c0ff` | `#f78166` | `#c9d1d9` |
|
|
85
|
+
|
|
86
|
+
### Light Palettes
|
|
87
|
+
|
|
88
|
+
| Name | Background | Surface | Primary | Secondary | Accent | Text |
|
|
89
|
+
|------|-----------|---------|---------|-----------|--------|------|
|
|
90
|
+
| Cloud Canvas | `#fafafa` | `#ffffff` | `#2563eb` | `#7c3aed` | `#dc2626` | `#0f172a` |
|
|
91
|
+
| Pearl Minimal | `#f8f9fa` | `#ffffff` | `#0066cc` | `#6610f2` | `#ff6b35` | `#212529` |
|
|
92
|
+
| Ivory Studio | `#f5f5f4` | `#fafaf9` | `#0891b2` | `#06b6d4` | `#f59e0b` | `#1c1917` |
|
|
93
|
+
| Porcelain Clean | `#f9fafb` | `#ffffff` | `#4f46e5` | `#8b5cf6` | `#ec4899` | `#111827` |
|
|
94
|
+
| Alabaster Pure | `#fcfcfc` | `#ffffff` | `#1d4ed8` | `#2563eb` | `#dc2626` | `#1e293b` |
|
|
95
|
+
| Frost Bright | `#f1f5f9` | `#f8fafc` | `#0f766e` | `#14b8a6` | `#e11d48` | `#0f172a` |
|
|
96
|
+
|
|
97
|
+
3. Do **not** invent random color combinations unless explicitly requested
|
|
98
|
+
|
|
99
|
+
## Rule
|
|
100
|
+
|
|
101
|
+
If a UI choice feels like a default AI move, ban it and pick the harder, cleaner option. Colors should stay calm, not fight. In your internal reasoning, list all the stuff you would normally do — and then don't do it.
|
package/agents/worker.md
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: worker
|
|
3
|
+
description: General-purpose subagent with full capabilities, isolated context
|
|
4
|
+
model: openai/gpt-5.4
|
|
5
|
+
thinking: medium
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
You are a worker agent with full capabilities. You operate in an isolated context window to handle delegated tasks without polluting the main conversation.
|
|
9
|
+
|
|
10
|
+
Work autonomously to complete the assigned task. Use all available tools as needed.
|
|
11
|
+
|
|
12
|
+
Output format when finished:
|
|
13
|
+
|
|
14
|
+
## Completed
|
|
15
|
+
What was done.
|
|
16
|
+
|
|
17
|
+
## Files Changed
|
|
18
|
+
- `path/to/file.ts` - what changed
|
|
19
|
+
|
|
20
|
+
## Notes (if any)
|
|
21
|
+
Anything the main agent should know.
|
|
22
|
+
|
|
23
|
+
If handing off to another agent (e.g. reviewer), include:
|
|
24
|
+
- Exact file paths changed
|
|
25
|
+
- Key functions/types touched (short list)
|
|
@@ -24,6 +24,9 @@ export interface AgentDiscoveryResult {
|
|
|
24
24
|
projectAgentsDir: string | null;
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
+
/** Bundled agents ship with the package (../../agents relative to extensions/subagent/) */
|
|
28
|
+
const bundledAgentsDir = path.resolve(import.meta.dirname, '..', '..', 'agents');
|
|
29
|
+
|
|
27
30
|
function loadAgentsFromDir(dir: string, source: 'user' | 'project'): AgentConfig[] {
|
|
28
31
|
const agents: AgentConfig[] = [];
|
|
29
32
|
|
|
@@ -100,12 +103,18 @@ export function discoverAgents(cwd: string, scope: AgentScope): AgentDiscoveryRe
|
|
|
100
103
|
const userDir = path.join(getAgentDir(), 'agents');
|
|
101
104
|
const projectAgentsDir = findNearestProjectAgentsDir(cwd);
|
|
102
105
|
|
|
106
|
+
// Bundled agents from the package itself (lowest priority)
|
|
107
|
+
const bundledAgents = loadAgentsFromDir(bundledAgentsDir, 'project');
|
|
108
|
+
|
|
103
109
|
const userAgents = scope === 'project' ? [] : loadAgentsFromDir(userDir, 'user');
|
|
104
110
|
const projectAgents =
|
|
105
111
|
scope === 'user' || !projectAgentsDir ? [] : loadAgentsFromDir(projectAgentsDir, 'project');
|
|
106
112
|
|
|
113
|
+
// Priority: bundled (lowest) → user → project (highest, overrides by name)
|
|
107
114
|
const agentMap = new Map<string, AgentConfig>();
|
|
108
115
|
|
|
116
|
+
for (const agent of bundledAgents) agentMap.set(agent.name, agent);
|
|
117
|
+
|
|
109
118
|
if (scope === 'both') {
|
|
110
119
|
for (const agent of userAgents) agentMap.set(agent.name, agent);
|
|
111
120
|
for (const agent of projectAgents) agentMap.set(agent.name, agent);
|
|
@@ -118,6 +127,8 @@ export function discoverAgents(cwd: string, scope: AgentScope): AgentDiscoveryRe
|
|
|
118
127
|
return { agents: Array.from(agentMap.values()), projectAgentsDir };
|
|
119
128
|
}
|
|
120
129
|
|
|
130
|
+
export { bundledAgentsDir };
|
|
131
|
+
|
|
121
132
|
export function formatAgentList(
|
|
122
133
|
agents: AgentConfig[],
|
|
123
134
|
maxItems: number,
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
|
+
import * as fs from 'node:fs';
|
|
3
|
+
import * as os from 'node:os';
|
|
4
|
+
import * as path from 'node:path';
|
|
5
|
+
import { withFileMutationQueue } from '@mariozechner/pi-coding-agent';
|
|
6
|
+
import type { Message } from '@mariozechner/pi-ai';
|
|
7
|
+
import { discoverAgents } from './agents';
|
|
8
|
+
import type { AgentResult, UsageStats } from './delegate-types';
|
|
9
|
+
|
|
10
|
+
function emptyUsage(): UsageStats {
|
|
11
|
+
return { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, cost: 0, contextTokens: 0, turns: 0 };
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function getPiInvocation(args: string[]): { command: string; args: string[] } {
|
|
15
|
+
const currentScript = process.argv[1];
|
|
16
|
+
if (currentScript && fs.existsSync(currentScript)) {
|
|
17
|
+
return { command: process.execPath, args: [currentScript, ...args] };
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const execName = path.basename(process.execPath).toLowerCase();
|
|
21
|
+
const isGenericRuntime = /^(node|bun)(\.exe)?$/.test(execName);
|
|
22
|
+
if (!isGenericRuntime) return { command: process.execPath, args };
|
|
23
|
+
|
|
24
|
+
return { command: 'pi', args };
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
async function writePromptToTempFile(
|
|
28
|
+
agentName: string,
|
|
29
|
+
prompt: string,
|
|
30
|
+
): Promise<{ dir: string; filePath: string }> {
|
|
31
|
+
const tmpDir = await fs.promises.mkdtemp(path.join(os.tmpdir(), 'pi-subagent-'));
|
|
32
|
+
const safeName = agentName.replace(/[^\w.-]+/g, '_');
|
|
33
|
+
const filePath = path.join(tmpDir, `prompt-${safeName}.md`);
|
|
34
|
+
await withFileMutationQueue(filePath, async () => {
|
|
35
|
+
await fs.promises.writeFile(filePath, prompt, { encoding: 'utf-8', mode: 0o600 });
|
|
36
|
+
});
|
|
37
|
+
return { dir: tmpDir, filePath };
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export type OnPhaseUpdate = (phaseName: string, agentName: string, result: AgentResult) => void;
|
|
41
|
+
|
|
42
|
+
export async function runAgent(
|
|
43
|
+
cwd: string,
|
|
44
|
+
agentName: string,
|
|
45
|
+
task: string,
|
|
46
|
+
onUpdate?: OnPhaseUpdate,
|
|
47
|
+
phaseName?: string,
|
|
48
|
+
): Promise<AgentResult> {
|
|
49
|
+
const { agents } = discoverAgents(cwd, 'user');
|
|
50
|
+
const agent = agents.find((a) => a.name === agentName);
|
|
51
|
+
|
|
52
|
+
if (!agent) {
|
|
53
|
+
const available = agents.map((a) => a.name).join(', ') || 'none';
|
|
54
|
+
return {
|
|
55
|
+
agent: agentName,
|
|
56
|
+
task,
|
|
57
|
+
exitCode: 1,
|
|
58
|
+
messages: [],
|
|
59
|
+
stderr: `Unknown agent: "${agentName}". Available: ${available}.`,
|
|
60
|
+
usage: emptyUsage(),
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const args: string[] = ['--mode', 'json', '-p', '--no-session'];
|
|
65
|
+
if (agent.model) args.push('--model', agent.model);
|
|
66
|
+
if (agent.thinking) args.push('--thinking', agent.thinking);
|
|
67
|
+
if (agent.tools && agent.tools.length > 0) args.push('--tools', agent.tools.join(','));
|
|
68
|
+
|
|
69
|
+
let tmpPromptDir: string | null = null;
|
|
70
|
+
let tmpPromptPath: string | null = null;
|
|
71
|
+
|
|
72
|
+
const result: AgentResult = {
|
|
73
|
+
agent: agentName,
|
|
74
|
+
task,
|
|
75
|
+
exitCode: 0,
|
|
76
|
+
messages: [],
|
|
77
|
+
stderr: '',
|
|
78
|
+
usage: emptyUsage(),
|
|
79
|
+
model: agent.model,
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
try {
|
|
83
|
+
if (agent.systemPrompt.trim()) {
|
|
84
|
+
const tmp = await writePromptToTempFile(agent.name, agent.systemPrompt);
|
|
85
|
+
tmpPromptDir = tmp.dir;
|
|
86
|
+
tmpPromptPath = tmp.filePath;
|
|
87
|
+
args.push('--append-system-prompt', tmpPromptPath);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
args.push(`Task: ${task}`);
|
|
91
|
+
|
|
92
|
+
const exitCode = await new Promise<number>((resolve) => {
|
|
93
|
+
const invocation = getPiInvocation(args);
|
|
94
|
+
const proc = spawn(invocation.command, invocation.args, {
|
|
95
|
+
cwd,
|
|
96
|
+
shell: false,
|
|
97
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
let buffer = '';
|
|
101
|
+
|
|
102
|
+
const processLine = (line: string) => {
|
|
103
|
+
if (!line.trim()) return;
|
|
104
|
+
let event: any;
|
|
105
|
+
try {
|
|
106
|
+
event = JSON.parse(line);
|
|
107
|
+
} catch {
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (event.type === 'message_end' && event.message) {
|
|
112
|
+
const msg = event.message as Message;
|
|
113
|
+
result.messages.push(msg);
|
|
114
|
+
|
|
115
|
+
if (msg.role === 'assistant') {
|
|
116
|
+
result.usage.turns++;
|
|
117
|
+
const usage = msg.usage;
|
|
118
|
+
if (usage) {
|
|
119
|
+
result.usage.input += usage.input || 0;
|
|
120
|
+
result.usage.output += usage.output || 0;
|
|
121
|
+
result.usage.cacheRead += usage.cacheRead || 0;
|
|
122
|
+
result.usage.cacheWrite += usage.cacheWrite || 0;
|
|
123
|
+
result.usage.cost += usage.cost?.total || 0;
|
|
124
|
+
result.usage.contextTokens = usage.totalTokens || 0;
|
|
125
|
+
}
|
|
126
|
+
if (!result.model && msg.model) result.model = msg.model;
|
|
127
|
+
if (msg.stopReason) result.stopReason = msg.stopReason;
|
|
128
|
+
if (msg.errorMessage) result.errorMessage = msg.errorMessage;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (onUpdate) onUpdate(phaseName ?? 'unknown', agentName, { ...result });
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
if (event.type === 'tool_result_end' && event.message) {
|
|
135
|
+
result.messages.push(event.message as Message);
|
|
136
|
+
if (onUpdate) onUpdate(phaseName ?? 'unknown', agentName, { ...result });
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
proc.stdout.on('data', (data: Buffer) => {
|
|
141
|
+
buffer += data.toString();
|
|
142
|
+
const lines = buffer.split('\n');
|
|
143
|
+
buffer = lines.pop() || '';
|
|
144
|
+
for (const line of lines) processLine(line);
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
proc.stderr.on('data', (data: Buffer) => {
|
|
148
|
+
result.stderr += data.toString();
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
proc.on('close', (code: number | null) => {
|
|
152
|
+
if (buffer.trim()) processLine(buffer);
|
|
153
|
+
resolve(code ?? 0);
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
proc.on('error', () => resolve(1));
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
result.exitCode = exitCode;
|
|
160
|
+
return result;
|
|
161
|
+
} finally {
|
|
162
|
+
if (tmpPromptPath)
|
|
163
|
+
try {
|
|
164
|
+
fs.unlinkSync(tmpPromptPath);
|
|
165
|
+
} catch {
|
|
166
|
+
/* ignore */
|
|
167
|
+
}
|
|
168
|
+
if (tmpPromptDir)
|
|
169
|
+
try {
|
|
170
|
+
fs.rmdirSync(tmpPromptDir);
|
|
171
|
+
} catch {
|
|
172
|
+
/* ignore */
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
export async function runParallel(
|
|
178
|
+
cwd: string,
|
|
179
|
+
agentNames: string[],
|
|
180
|
+
task: string,
|
|
181
|
+
onUpdate?: OnPhaseUpdate,
|
|
182
|
+
phaseName?: string,
|
|
183
|
+
): Promise<AgentResult[]> {
|
|
184
|
+
const MAX_CONCURRENCY = 4;
|
|
185
|
+
const results: AgentResult[] = new Array(agentNames.length);
|
|
186
|
+
let nextIndex = 0;
|
|
187
|
+
|
|
188
|
+
const workers = new Array(Math.min(MAX_CONCURRENCY, agentNames.length))
|
|
189
|
+
.fill(null)
|
|
190
|
+
.map(async () => {
|
|
191
|
+
while (true) {
|
|
192
|
+
const current = nextIndex++;
|
|
193
|
+
if (current >= agentNames.length) return;
|
|
194
|
+
results[current] = await runAgent(cwd, agentNames[current], task, onUpdate, phaseName);
|
|
195
|
+
}
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
await Promise.all(workers);
|
|
199
|
+
return results;
|
|
200
|
+
}
|