@dreki-gg/pi-subagent 0.5.0 → 0.7.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 +31 -0
- package/README.md +99 -49
- package/agents/advisor.md +37 -0
- package/agents/bug-prover.md +42 -0
- package/agents/docs-scout.md +2 -2
- package/agents/manager.md +52 -0
- package/agents/planner.md +16 -1
- package/agents/reviewer.md +65 -8
- package/agents/scout.md +5 -1
- package/agents/validator.md +42 -0
- package/agents/worker.md +39 -3
- package/docs/orchestration-principles.md +132 -0
- package/docs/plans/01_structured-handoffs-and-synthesis.plan.md +376 -0
- package/docs/plans/02_clean-context-review-loop.plan.md +240 -0
- package/docs/plans/03_parallel-recon-single-writer-docs.plan.md +199 -0
- package/docs/plans/04_manager-workflow.plan.md +248 -0
- package/docs/plans/05_advisor-routing.plan.md +244 -0
- package/extensions/subagent/agent-result-utils.ts +12 -0
- package/extensions/subagent/agent-runner-types.ts +23 -0
- package/extensions/subagent/{delegate-executor.ts → agent-runner.ts} +10 -29
- package/extensions/subagent/agents.ts +11 -0
- package/extensions/subagent/handoffs.ts +273 -0
- package/extensions/subagent/index.ts +494 -196
- package/extensions/subagent/{delegate-args.ts → run-agent-args.ts} +35 -29
- package/package.json +3 -6
- package/skills/spawn-subagents/SKILL.md +80 -8
- package/extensions/subagent/delegate-types.ts +0 -62
- package/extensions/subagent/delegate-ui.ts +0 -132
- package/extensions/subagent/workflows.ts +0 -150
- package/prompts/implement-and-review.md +0 -10
- package/prompts/implement.md +0 -10
- package/prompts/scout-and-plan.md +0 -9
|
@@ -1,43 +1,33 @@
|
|
|
1
1
|
import type { AgentScope } from './agents';
|
|
2
|
-
import type { WorkflowId } from './delegate-types';
|
|
3
2
|
|
|
4
|
-
export interface
|
|
3
|
+
export interface RunAgentCommandOptions {
|
|
5
4
|
agentScope: AgentScope;
|
|
6
|
-
workflowId?: WorkflowId;
|
|
7
5
|
confirmProjectAgents: boolean;
|
|
6
|
+
model?: string;
|
|
7
|
+
thinking?: string;
|
|
8
|
+
agentName?: string;
|
|
8
9
|
explicitTask?: string;
|
|
9
10
|
}
|
|
10
11
|
|
|
11
|
-
const WORKFLOW_IDS = new Set<WorkflowId>([
|
|
12
|
-
'scout-only',
|
|
13
|
-
'scout-and-plan',
|
|
14
|
-
'implement',
|
|
15
|
-
'implement-and-review',
|
|
16
|
-
'quick-fix',
|
|
17
|
-
'review',
|
|
18
|
-
]);
|
|
19
|
-
|
|
20
12
|
function tokenize(input: string): string[] {
|
|
21
13
|
return input.match(/"[^"]*"|'[^']*'|\S+/g)?.map((token) => token.replace(/^['"]|['"]$/g, '')) ?? [];
|
|
22
14
|
}
|
|
23
15
|
|
|
24
|
-
export function
|
|
25
|
-
return [
|
|
26
|
-
'Usage: /delegate [--scope user|project|both] [--workflow <id>] [--yes-project-agents] [task]',
|
|
27
|
-
'',
|
|
28
|
-
'Workflows: scout-only, scout-and-plan, implement, implement-and-review, quick-fix, review',
|
|
29
|
-
].join('\n');
|
|
16
|
+
export function formatRunAgentUsage(): string {
|
|
17
|
+
return 'Usage: /run-agent [--scope user|project|both] [--model <id>] [--thinking <level>] [--yes-project-agents] <agent> [task]';
|
|
30
18
|
}
|
|
31
19
|
|
|
32
|
-
export function
|
|
33
|
-
| { ok: true; options:
|
|
20
|
+
export function parseRunAgentArgs(rawArgs?: string):
|
|
21
|
+
| { ok: true; options: RunAgentCommandOptions }
|
|
34
22
|
| { ok: false; error: string } {
|
|
35
23
|
const tokens = tokenize(rawArgs?.trim() ?? '');
|
|
36
24
|
const taskTokens: string[] = [];
|
|
37
25
|
|
|
38
26
|
let agentScope: AgentScope = 'user';
|
|
39
|
-
let workflowId: WorkflowId | undefined;
|
|
40
27
|
let confirmProjectAgents = true;
|
|
28
|
+
let model: string | undefined;
|
|
29
|
+
let thinking: string | undefined;
|
|
30
|
+
let agentName: string | undefined;
|
|
41
31
|
|
|
42
32
|
for (let i = 0; i < tokens.length; i++) {
|
|
43
33
|
const token = tokens[i];
|
|
@@ -45,18 +35,27 @@ export function parseDelegateArgs(rawArgs?: string):
|
|
|
45
35
|
if (token === '--scope') {
|
|
46
36
|
const value = tokens[++i];
|
|
47
37
|
if (!value || !['user', 'project', 'both'].includes(value)) {
|
|
48
|
-
return { ok: false, error: `Invalid --scope value.\n\n${
|
|
38
|
+
return { ok: false, error: `Invalid --scope value.\n\n${formatRunAgentUsage()}` };
|
|
49
39
|
}
|
|
50
40
|
agentScope = value as AgentScope;
|
|
51
41
|
continue;
|
|
52
42
|
}
|
|
53
43
|
|
|
54
|
-
if (token === '--
|
|
55
|
-
const value = tokens[++i]
|
|
56
|
-
if (!value
|
|
57
|
-
return { ok: false, error: `
|
|
44
|
+
if (token === '--model') {
|
|
45
|
+
const value = tokens[++i];
|
|
46
|
+
if (!value) {
|
|
47
|
+
return { ok: false, error: `Missing --model value.\n\n${formatRunAgentUsage()}` };
|
|
48
|
+
}
|
|
49
|
+
model = value;
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (token === '--thinking' || token === '--reasoning-level') {
|
|
54
|
+
const value = tokens[++i];
|
|
55
|
+
if (!value) {
|
|
56
|
+
return { ok: false, error: `Missing ${token} value.\n\n${formatRunAgentUsage()}` };
|
|
58
57
|
}
|
|
59
|
-
|
|
58
|
+
thinking = value;
|
|
60
59
|
continue;
|
|
61
60
|
}
|
|
62
61
|
|
|
@@ -66,7 +65,12 @@ export function parseDelegateArgs(rawArgs?: string):
|
|
|
66
65
|
}
|
|
67
66
|
|
|
68
67
|
if (token.startsWith('--')) {
|
|
69
|
-
return { ok: false, error: `Unknown option: ${token}\n\n${
|
|
68
|
+
return { ok: false, error: `Unknown option: ${token}\n\n${formatRunAgentUsage()}` };
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (!agentName) {
|
|
72
|
+
agentName = token;
|
|
73
|
+
continue;
|
|
70
74
|
}
|
|
71
75
|
|
|
72
76
|
taskTokens.push(token);
|
|
@@ -76,8 +80,10 @@ export function parseDelegateArgs(rawArgs?: string):
|
|
|
76
80
|
ok: true,
|
|
77
81
|
options: {
|
|
78
82
|
agentScope,
|
|
79
|
-
workflowId,
|
|
80
83
|
confirmProjectAgents,
|
|
84
|
+
model,
|
|
85
|
+
thinking,
|
|
86
|
+
agentName,
|
|
81
87
|
explicitTask: taskTokens.join(' ').trim() || undefined,
|
|
82
88
|
},
|
|
83
89
|
};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dreki-gg/pi-subagent",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Subagent tool and
|
|
3
|
+
"version": "0.7.0",
|
|
4
|
+
"description": "Subagent tool and direct agent runs for pi — isolated agents, parallel scouts, manager workflows, and bundled agents",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pi-package"
|
|
7
7
|
],
|
|
@@ -26,9 +26,6 @@
|
|
|
26
26
|
"skills": [
|
|
27
27
|
"./skills"
|
|
28
28
|
],
|
|
29
|
-
"prompts": [
|
|
30
|
-
"./prompts"
|
|
31
|
-
],
|
|
32
29
|
"agents": [
|
|
33
30
|
"./agents"
|
|
34
31
|
]
|
|
@@ -44,6 +41,6 @@
|
|
|
44
41
|
"@mariozechner/pi-agent-core": "*",
|
|
45
42
|
"@mariozechner/pi-coding-agent": "*",
|
|
46
43
|
"@mariozechner/pi-tui": "*",
|
|
47
|
-
"
|
|
44
|
+
"typebox": "*"
|
|
48
45
|
}
|
|
49
46
|
}
|
|
@@ -5,10 +5,14 @@ description: Use conversational subagent orchestration with the `subagent` tool.
|
|
|
5
5
|
|
|
6
6
|
Use this skill when the user wants agents spawned conversationally.
|
|
7
7
|
|
|
8
|
+
Core rule:
|
|
9
|
+
- Parallelize discovery and verification, not conflicting edits.
|
|
10
|
+
- Prefer one `worker` unless file ownership is clearly partitioned.
|
|
11
|
+
|
|
8
12
|
Default behavior:
|
|
9
13
|
- Prefer the `subagent` tool directly.
|
|
10
|
-
-
|
|
11
|
-
-
|
|
14
|
+
- Use `/run-agent` only when the user explicitly wants a direct named-agent run.
|
|
15
|
+
- This package is agent-first: build the needed `single` / `parallel` / `chain` orchestration directly instead of reaching for canned workflow prompts.
|
|
12
16
|
|
|
13
17
|
Strong triggers:
|
|
14
18
|
- "spawn a scout"
|
|
@@ -17,6 +21,11 @@ Strong triggers:
|
|
|
17
21
|
- "have planner make a plan first"
|
|
18
22
|
- "send docs-scout to check the docs"
|
|
19
23
|
- "parallelize discovery"
|
|
24
|
+
- "coordinate this migration"
|
|
25
|
+
- "break this feature into child workstreams"
|
|
26
|
+
- "ask advisor for a second opinion on this"
|
|
27
|
+
- "validate whether this review finding is real"
|
|
28
|
+
- "prove this bug with a minimal failing test"
|
|
20
29
|
|
|
21
30
|
Patterns:
|
|
22
31
|
|
|
@@ -27,15 +36,18 @@ Use one agent when the task is narrow.
|
|
|
27
36
|
- `planner` for a concrete plan
|
|
28
37
|
- `worker` for implementation
|
|
29
38
|
- `reviewer` for quality/security review
|
|
39
|
+
- `validator` to confirm or falsify a specific bug or behavior claim
|
|
40
|
+
- `bug-prover` to create the smallest failing repro when a claim needs proof
|
|
41
|
+
- `advisor` for a focused second opinion on a tricky or high-risk decision
|
|
30
42
|
|
|
31
43
|
## 2. Parallel recon
|
|
32
|
-
Use parallel mode for noisy discovery.
|
|
44
|
+
Use parallel mode for noisy discovery, not implementation races.
|
|
33
45
|
- Run `scout` + `docs-scout` in parallel when both code and docs matter.
|
|
34
46
|
- Keep parallel tasks non-overlapping.
|
|
35
47
|
- Return a compact synthesis to the main thread.
|
|
36
48
|
|
|
37
49
|
## 3. Plan then implement
|
|
38
|
-
Use chain mode when the user wants safe sequencing.
|
|
50
|
+
Use chain mode when the user wants safe sequencing around one implementing agent.
|
|
39
51
|
1. `scout` and optionally `docs-scout`
|
|
40
52
|
2. `planner`
|
|
41
53
|
3. `worker`
|
|
@@ -43,14 +55,74 @@ Use chain mode when the user wants safe sequencing.
|
|
|
43
55
|
|
|
44
56
|
## 4. Review loop
|
|
45
57
|
Use after implementation or when the user asks for a second opinion.
|
|
46
|
-
1. `reviewer`
|
|
47
|
-
2.
|
|
58
|
+
1. `reviewer` inspects the diff and code
|
|
59
|
+
2. if a suspected issue needs evidence, run `validator`
|
|
60
|
+
3. if proof still needs a minimal failing test or repro artifact, run `bug-prover`
|
|
61
|
+
4. only send confirmed, evidenced findings back to `worker`
|
|
62
|
+
|
|
63
|
+
## 5. Manager pattern
|
|
64
|
+
Use `manager` when the task is too large for one prompt but still needs coherent decisions.
|
|
65
|
+
1. `manager` splits the work into bounded workstreams
|
|
66
|
+
2. `manager` runs `scout`, `docs-scout`, or `planner` in parallel when discovery can be split cleanly
|
|
67
|
+
3. `manager` keeps implementation single-writer by default, handing edits to one `worker` unless ownership is clearly partitioned
|
|
68
|
+
4. `manager` synthesizes child reports before recommending the next action
|
|
69
|
+
|
|
70
|
+
Good fits:
|
|
71
|
+
- multi-package migrations
|
|
72
|
+
- larger refactors with several discovery threads
|
|
73
|
+
- features spanning backend, UI, and docs that still need shared decisions
|
|
74
|
+
|
|
75
|
+
## 6. Claim validation and proof
|
|
76
|
+
Use `validator` and `bug-prover` when review claims should be evidenced before they become fix requests.
|
|
77
|
+
|
|
78
|
+
Good fits:
|
|
79
|
+
- reviewer suspects a regression but needs command/test evidence
|
|
80
|
+
- worker wants to confirm whether an edge case is truly broken
|
|
81
|
+
- a bug claim seems plausible but not yet proven from diff/code alone
|
|
82
|
+
- you want a minimal failing test before authorizing a fix
|
|
83
|
+
|
|
84
|
+
Flow:
|
|
85
|
+
- `validator` first for read-only verification with code, tests, and focused commands
|
|
86
|
+
- `bug-prover` only when proof needs a new failing test or isolated repro artifact
|
|
87
|
+
- keep repro scope narrow; proving is not fixing
|
|
88
|
+
|
|
89
|
+
## 7. Targeted advisor consult
|
|
90
|
+
Use `advisor` when the primary owner is still clear, but a tricky question needs a strong second opinion.
|
|
91
|
+
|
|
92
|
+
Good fits:
|
|
93
|
+
- planner is choosing between multiple designs with different blast radius
|
|
94
|
+
- worker is stuck in a failing test loop or messy migration
|
|
95
|
+
- reviewer is unsure whether a suspected issue is real, intended, or severe
|
|
96
|
+
- the change is security-sensitive or otherwise high risk
|
|
97
|
+
|
|
98
|
+
Consult packet:
|
|
99
|
+
- current role (`worker`, `planner`, `reviewer`, or `main-agent`)
|
|
100
|
+
- exact question to answer
|
|
101
|
+
- smallest relevant task summary
|
|
102
|
+
- touched files or symbols, if known
|
|
103
|
+
- what has already been tried, verified, or observed
|
|
104
|
+
|
|
105
|
+
Rules:
|
|
106
|
+
- advisor use is optional, not a default step
|
|
107
|
+
- keep the primary role in charge of the final plan, implementation, or review judgment
|
|
108
|
+
- prefer one clear advisor recommendation over a long brainstorm
|
|
109
|
+
|
|
110
|
+
Avoid:
|
|
111
|
+
- arbitrary peer-to-peer negotiation loops
|
|
112
|
+
- unbounded swarms
|
|
113
|
+
- multiple workers editing overlapping files
|
|
114
|
+
- calling `advisor` when `planner` or `reviewer` already has enough signal to proceed alone
|
|
115
|
+
- sending speculative review findings back for fixes before they are validated when evidence is needed
|
|
48
116
|
|
|
49
117
|
Execution rules:
|
|
50
|
-
-
|
|
118
|
+
- Use `manager` when the task is too large for one prompt but still needs coherent decisions.
|
|
119
|
+
- Use `advisor` for targeted second opinions on tricky or high-risk cases.
|
|
120
|
+
- Use `validator` to confirm a claim before escalating it as a fix.
|
|
121
|
+
- Use `bug-prover` only when confirmation needs a minimal failing test or repro artifact.
|
|
122
|
+
- Parallelize reconnaissance and verification, not conflicting edits.
|
|
51
123
|
- Prefer one `worker` unless file ownership is clearly partitioned.
|
|
52
124
|
- Use `docs-scout` when external library/framework details matter.
|
|
53
|
-
- Pass
|
|
125
|
+
- Pass a compact handoff or structured summary via `{previous}`, not an unbounded transcript dump.
|
|
54
126
|
|
|
55
127
|
When reporting back:
|
|
56
128
|
- say which subagents ran
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import type { Message } from '@mariozechner/pi-ai';
|
|
2
|
-
|
|
3
|
-
export interface UsageStats {
|
|
4
|
-
input: number;
|
|
5
|
-
output: number;
|
|
6
|
-
cacheRead: number;
|
|
7
|
-
cacheWrite: number;
|
|
8
|
-
cost: number;
|
|
9
|
-
contextTokens: number;
|
|
10
|
-
turns: number;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export interface AgentResult {
|
|
14
|
-
agent: string;
|
|
15
|
-
task: string;
|
|
16
|
-
exitCode: number;
|
|
17
|
-
messages: Message[];
|
|
18
|
-
stderr: string;
|
|
19
|
-
usage: UsageStats;
|
|
20
|
-
model?: string;
|
|
21
|
-
stopReason?: string;
|
|
22
|
-
errorMessage?: string;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export type WorkflowId =
|
|
26
|
-
| 'scout-only'
|
|
27
|
-
| 'scout-and-plan'
|
|
28
|
-
| 'implement'
|
|
29
|
-
| 'implement-and-review'
|
|
30
|
-
| 'quick-fix'
|
|
31
|
-
| 'review';
|
|
32
|
-
|
|
33
|
-
export interface WorkflowDefinition {
|
|
34
|
-
id: WorkflowId;
|
|
35
|
-
label: string;
|
|
36
|
-
description: string;
|
|
37
|
-
phases: PhaseDefinition[];
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export type PhaseKind = 'parallel' | 'single';
|
|
41
|
-
|
|
42
|
-
export interface PhaseDefinition {
|
|
43
|
-
kind: PhaseKind;
|
|
44
|
-
name: string;
|
|
45
|
-
agents: string[];
|
|
46
|
-
requiresConfirmation?: boolean;
|
|
47
|
-
taskTemplate: string;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
export interface PhaseResult {
|
|
51
|
-
name: string;
|
|
52
|
-
kind: PhaseKind;
|
|
53
|
-
agents: AgentResult[];
|
|
54
|
-
skipped?: boolean;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
export interface DelegateState {
|
|
58
|
-
synthesis: string;
|
|
59
|
-
workflow: WorkflowDefinition;
|
|
60
|
-
phases: PhaseResult[];
|
|
61
|
-
totalUsage: UsageStats;
|
|
62
|
-
}
|
|
@@ -1,132 +0,0 @@
|
|
|
1
|
-
import type { ExtensionCommandContext } from '@mariozechner/pi-coding-agent';
|
|
2
|
-
import type {
|
|
3
|
-
AgentResult,
|
|
4
|
-
DelegateState,
|
|
5
|
-
PhaseResult,
|
|
6
|
-
UsageStats,
|
|
7
|
-
WorkflowDefinition,
|
|
8
|
-
} from './delegate-types';
|
|
9
|
-
import { WORKFLOWS, suggestWorkflow } from './workflows';
|
|
10
|
-
|
|
11
|
-
function formatTokens(count: number): string {
|
|
12
|
-
if (count < 1000) return count.toString();
|
|
13
|
-
if (count < 10000) return `${(count / 1000).toFixed(1)}k`;
|
|
14
|
-
if (count < 1000000) return `${Math.round(count / 1000)}k`;
|
|
15
|
-
return `${(count / 1000000).toFixed(1)}M`;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
function formatUsage(usage: UsageStats): string {
|
|
19
|
-
const parts: string[] = [];
|
|
20
|
-
if (usage.turns) parts.push(`${usage.turns} turns`);
|
|
21
|
-
if (usage.input) parts.push(`↑${formatTokens(usage.input)}`);
|
|
22
|
-
if (usage.output) parts.push(`↓${formatTokens(usage.output)}`);
|
|
23
|
-
if (usage.cacheRead) parts.push(`R${formatTokens(usage.cacheRead)}`);
|
|
24
|
-
if (usage.cacheWrite) parts.push(`W${formatTokens(usage.cacheWrite)}`);
|
|
25
|
-
if (usage.cost) parts.push(`$${usage.cost.toFixed(4)}`);
|
|
26
|
-
return parts.join(' ');
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
function getFinalText(result: AgentResult): string {
|
|
30
|
-
for (let i = result.messages.length - 1; i >= 0; i--) {
|
|
31
|
-
const msg = result.messages[i];
|
|
32
|
-
if (msg.role === 'assistant') {
|
|
33
|
-
for (const part of msg.content) {
|
|
34
|
-
if (part.type === 'text') return part.text;
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
return '(no output)';
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
export async function confirmSynthesis(
|
|
42
|
-
ctx: ExtensionCommandContext,
|
|
43
|
-
synthesis: string,
|
|
44
|
-
): Promise<boolean> {
|
|
45
|
-
return ctx.ui.confirm('Delegate — Task Synthesis', `${synthesis}\n\nProceed with this task?`);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
export async function pickWorkflow(
|
|
49
|
-
ctx: ExtensionCommandContext,
|
|
50
|
-
synthesis: string,
|
|
51
|
-
): Promise<WorkflowDefinition | null> {
|
|
52
|
-
const suggested = suggestWorkflow(synthesis);
|
|
53
|
-
const options = WORKFLOWS.map((wf) => {
|
|
54
|
-
const marker = wf.id === suggested ? ' ← suggested' : '';
|
|
55
|
-
return `${wf.label}${marker} — ${wf.description}`;
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
const choice = await ctx.ui.select('Delegate — Choose Workflow', options);
|
|
59
|
-
if (choice === undefined || choice === null) return null;
|
|
60
|
-
|
|
61
|
-
const selectedIndex = options.indexOf(choice as string);
|
|
62
|
-
if (selectedIndex < 0) return null;
|
|
63
|
-
|
|
64
|
-
return WORKFLOWS[selectedIndex];
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
export async function confirmPlan(
|
|
68
|
-
ctx: ExtensionCommandContext,
|
|
69
|
-
planText: string,
|
|
70
|
-
): Promise<boolean> {
|
|
71
|
-
return ctx.ui.confirm('Delegate — Review Plan', `${planText}\n\nContinue with implementation?`);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
export function formatPhaseHeader(
|
|
75
|
-
phaseName: string,
|
|
76
|
-
status: 'running' | 'done' | 'failed' | 'skipped',
|
|
77
|
-
): string {
|
|
78
|
-
const icons = { running: '⏳', done: '✓', failed: '✗', skipped: '⊘' };
|
|
79
|
-
return `${icons[status]} ${phaseName}`;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
export function formatAgentResult(result: AgentResult): string {
|
|
83
|
-
const icon = result.exitCode === 0 ? '✓' : '✗';
|
|
84
|
-
const output = getFinalText(result);
|
|
85
|
-
const preview = output.length > 200 ? `${output.slice(0, 200)}...` : output;
|
|
86
|
-
const usage = formatUsage(result.usage);
|
|
87
|
-
const model = result.model ? ` [${result.model}]` : '';
|
|
88
|
-
|
|
89
|
-
return `${icon} ${result.agent}${model}\n${preview}\n${usage}`;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
export function formatPhaseSummary(phase: PhaseResult): string {
|
|
93
|
-
if (phase.skipped) return `⊘ ${phase.name} — skipped`;
|
|
94
|
-
|
|
95
|
-
const header = `── ${phase.name} (${phase.kind}) ──`;
|
|
96
|
-
const agentSummaries = phase.agents.map(formatAgentResult).join('\n\n');
|
|
97
|
-
return `${header}\n${agentSummaries}`;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
export function formatFullSummary(state: DelegateState): string {
|
|
101
|
-
const sections = [
|
|
102
|
-
`── Synthesis ──\n${state.synthesis}`,
|
|
103
|
-
`── Workflow: ${state.workflow.label} ──`,
|
|
104
|
-
...state.phases.map(formatPhaseSummary),
|
|
105
|
-
`── Usage ──\nTotal: ${formatUsage(state.totalUsage)}`,
|
|
106
|
-
];
|
|
107
|
-
|
|
108
|
-
return sections.join('\n\n');
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
export function aggregateUsage(results: AgentResult[]): UsageStats {
|
|
112
|
-
const total: UsageStats = {
|
|
113
|
-
input: 0,
|
|
114
|
-
output: 0,
|
|
115
|
-
cacheRead: 0,
|
|
116
|
-
cacheWrite: 0,
|
|
117
|
-
cost: 0,
|
|
118
|
-
contextTokens: 0,
|
|
119
|
-
turns: 0,
|
|
120
|
-
};
|
|
121
|
-
for (const r of results) {
|
|
122
|
-
total.input += r.usage.input;
|
|
123
|
-
total.output += r.usage.output;
|
|
124
|
-
total.cacheRead += r.usage.cacheRead;
|
|
125
|
-
total.cacheWrite += r.usage.cacheWrite;
|
|
126
|
-
total.cost += r.usage.cost;
|
|
127
|
-
total.turns += r.usage.turns;
|
|
128
|
-
}
|
|
129
|
-
return total;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
export { getFinalText };
|
|
@@ -1,150 +0,0 @@
|
|
|
1
|
-
import type { WorkflowDefinition, WorkflowId } from './delegate-types';
|
|
2
|
-
|
|
3
|
-
export const WORKFLOWS: WorkflowDefinition[] = [
|
|
4
|
-
{
|
|
5
|
-
id: 'scout-only',
|
|
6
|
-
label: 'Scout only',
|
|
7
|
-
description: 'Parallel scouts for exploration — no plan, no implementation',
|
|
8
|
-
phases: [
|
|
9
|
-
{
|
|
10
|
-
kind: 'parallel',
|
|
11
|
-
name: 'Scouts',
|
|
12
|
-
agents: ['scout', 'docs-scout'],
|
|
13
|
-
taskTemplate: '{synthesis}',
|
|
14
|
-
},
|
|
15
|
-
],
|
|
16
|
-
},
|
|
17
|
-
{
|
|
18
|
-
id: 'scout-and-plan',
|
|
19
|
-
label: 'Scout and plan',
|
|
20
|
-
description: 'Parallel scouts → planner — produces a plan without implementing',
|
|
21
|
-
phases: [
|
|
22
|
-
{
|
|
23
|
-
kind: 'parallel',
|
|
24
|
-
name: 'Scouts',
|
|
25
|
-
agents: ['scout', 'docs-scout'],
|
|
26
|
-
taskTemplate: '{synthesis}',
|
|
27
|
-
},
|
|
28
|
-
{
|
|
29
|
-
kind: 'single',
|
|
30
|
-
name: 'Planner',
|
|
31
|
-
agents: ['planner'],
|
|
32
|
-
taskTemplate:
|
|
33
|
-
'Create an implementation plan based on the following context.\n\n## Task\n{synthesis}\n\n## Scout findings\n{previous}',
|
|
34
|
-
},
|
|
35
|
-
],
|
|
36
|
-
},
|
|
37
|
-
{
|
|
38
|
-
id: 'implement',
|
|
39
|
-
label: 'Implement',
|
|
40
|
-
description: 'Parallel scouts → planner → worker — full implementation',
|
|
41
|
-
phases: [
|
|
42
|
-
{
|
|
43
|
-
kind: 'parallel',
|
|
44
|
-
name: 'Scouts',
|
|
45
|
-
agents: ['scout', 'docs-scout'],
|
|
46
|
-
taskTemplate: '{synthesis}',
|
|
47
|
-
},
|
|
48
|
-
{
|
|
49
|
-
kind: 'single',
|
|
50
|
-
name: 'Planner',
|
|
51
|
-
agents: ['planner'],
|
|
52
|
-
requiresConfirmation: true,
|
|
53
|
-
taskTemplate:
|
|
54
|
-
'Create an implementation plan based on the following context.\n\n## Task\n{synthesis}\n\n## Scout findings\n{previous}',
|
|
55
|
-
},
|
|
56
|
-
{
|
|
57
|
-
kind: 'single',
|
|
58
|
-
name: 'Worker',
|
|
59
|
-
agents: ['worker'],
|
|
60
|
-
taskTemplate:
|
|
61
|
-
'Implement the following plan.\n\n## Task\n{synthesis}\n\n## Plan\n{previous}',
|
|
62
|
-
},
|
|
63
|
-
],
|
|
64
|
-
},
|
|
65
|
-
{
|
|
66
|
-
id: 'implement-and-review',
|
|
67
|
-
label: 'Implement and review',
|
|
68
|
-
description:
|
|
69
|
-
'Parallel scouts → planner → worker → reviewer — full implementation with code review',
|
|
70
|
-
phases: [
|
|
71
|
-
{
|
|
72
|
-
kind: 'parallel',
|
|
73
|
-
name: 'Scouts',
|
|
74
|
-
agents: ['scout', 'docs-scout'],
|
|
75
|
-
taskTemplate: '{synthesis}',
|
|
76
|
-
},
|
|
77
|
-
{
|
|
78
|
-
kind: 'single',
|
|
79
|
-
name: 'Planner',
|
|
80
|
-
agents: ['planner'],
|
|
81
|
-
requiresConfirmation: true,
|
|
82
|
-
taskTemplate:
|
|
83
|
-
'Create an implementation plan based on the following context.\n\n## Task\n{synthesis}\n\n## Scout findings\n{previous}',
|
|
84
|
-
},
|
|
85
|
-
{
|
|
86
|
-
kind: 'single',
|
|
87
|
-
name: 'Worker',
|
|
88
|
-
agents: ['worker'],
|
|
89
|
-
taskTemplate:
|
|
90
|
-
'Implement the following plan.\n\n## Task\n{synthesis}\n\n## Plan\n{previous}',
|
|
91
|
-
},
|
|
92
|
-
{
|
|
93
|
-
kind: 'single',
|
|
94
|
-
name: 'Reviewer',
|
|
95
|
-
agents: ['reviewer'],
|
|
96
|
-
taskTemplate:
|
|
97
|
-
'Review the implementation described below.\n\n## Task\n{synthesis}\n\n## Implementation output\n{previous}',
|
|
98
|
-
},
|
|
99
|
-
],
|
|
100
|
-
},
|
|
101
|
-
{
|
|
102
|
-
id: 'quick-fix',
|
|
103
|
-
label: 'Quick fix',
|
|
104
|
-
description: 'Worker only — fast, no scouts or planning',
|
|
105
|
-
phases: [
|
|
106
|
-
{
|
|
107
|
-
kind: 'single',
|
|
108
|
-
name: 'Worker',
|
|
109
|
-
agents: ['worker'],
|
|
110
|
-
taskTemplate: '{synthesis}',
|
|
111
|
-
},
|
|
112
|
-
],
|
|
113
|
-
},
|
|
114
|
-
{
|
|
115
|
-
id: 'review',
|
|
116
|
-
label: 'Review',
|
|
117
|
-
description: 'Reviewer only — code review of recent changes',
|
|
118
|
-
phases: [
|
|
119
|
-
{
|
|
120
|
-
kind: 'single',
|
|
121
|
-
name: 'Reviewer',
|
|
122
|
-
agents: ['reviewer'],
|
|
123
|
-
taskTemplate: '{synthesis}',
|
|
124
|
-
},
|
|
125
|
-
],
|
|
126
|
-
},
|
|
127
|
-
];
|
|
128
|
-
|
|
129
|
-
export function getWorkflow(id: WorkflowId): WorkflowDefinition {
|
|
130
|
-
const wf = WORKFLOWS.find((w) => w.id === id);
|
|
131
|
-
if (!wf) throw new Error(`Unknown workflow: ${id}`);
|
|
132
|
-
return wf;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
export function suggestWorkflow(synthesis: string): WorkflowId {
|
|
136
|
-
const lower = synthesis.toLowerCase();
|
|
137
|
-
|
|
138
|
-
const hasReview = /review|audit|check quality|security/.test(lower);
|
|
139
|
-
const hasFix = /fix|bug|patch|hotfix|quick/.test(lower);
|
|
140
|
-
const hasImplement = /implement|build|create|add|refactor|migrate/.test(lower);
|
|
141
|
-
const hasDesign = /design|plan|architect|explore|investigate|scout/.test(lower);
|
|
142
|
-
|
|
143
|
-
if (hasFix && !hasImplement && !hasDesign) return 'quick-fix';
|
|
144
|
-
if (hasReview && !hasImplement && !hasDesign) return 'review';
|
|
145
|
-
if (hasDesign && !hasImplement) return 'scout-and-plan';
|
|
146
|
-
if (hasImplement && hasReview) return 'implement-and-review';
|
|
147
|
-
if (hasImplement) return 'implement';
|
|
148
|
-
|
|
149
|
-
return 'implement';
|
|
150
|
-
}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: Worker implements, reviewer reviews, worker applies feedback
|
|
3
|
-
---
|
|
4
|
-
Use the subagent tool with the chain parameter to execute this workflow:
|
|
5
|
-
|
|
6
|
-
1. First, use the "worker" agent to implement: $@
|
|
7
|
-
2. Then, use the "reviewer" agent to review the implementation from the previous step (use {previous} placeholder)
|
|
8
|
-
3. Finally, use the "worker" agent to apply the feedback from the review (use {previous} placeholder)
|
|
9
|
-
|
|
10
|
-
Execute this as a chain, passing output between steps via {previous}.
|
package/prompts/implement.md
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: Full implementation workflow - scout gathers context, planner creates plan, worker implements
|
|
3
|
-
---
|
|
4
|
-
Use the subagent tool with the chain parameter to execute this workflow:
|
|
5
|
-
|
|
6
|
-
1. First, use the "scout" agent to find all code relevant to: $@
|
|
7
|
-
2. Then, use the "planner" agent to create an implementation plan for "$@" using the context from the previous step (use {previous} placeholder)
|
|
8
|
-
3. Finally, use the "worker" agent to implement the plan from the previous step (use {previous} placeholder)
|
|
9
|
-
|
|
10
|
-
Execute this as a chain, passing output between steps via {previous}.
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: Scout gathers context, planner creates implementation plan (no implementation)
|
|
3
|
-
---
|
|
4
|
-
Use the subagent tool with the chain parameter to execute this workflow:
|
|
5
|
-
|
|
6
|
-
1. First, use the "scout" agent to find all code relevant to: $@
|
|
7
|
-
2. Then, use the "planner" agent to create an implementation plan for "$@" using the context from the previous step (use {previous} placeholder)
|
|
8
|
-
|
|
9
|
-
Execute this as a chain, passing output between steps via {previous}. Do NOT implement - just return the plan.
|