pi-maestro-teammate 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/README.md +168 -86
- package/agents/coordinator.md +12 -7
- package/package.json +2 -2
- package/src/extension/index.ts +1357 -555
- package/src/extension/schemas.ts +217 -166
- package/src/runs/execution.ts +1177 -696
- package/src/shared/types.ts +97 -85
- package/src/tui/attach-overlay.ts +250 -0
- package/src/tui/render.ts +162 -153
package/README.md
CHANGED
|
@@ -1,52 +1,8 @@
|
|
|
1
1
|
# pi-teammate
|
|
2
2
|
|
|
3
|
-
> Teammate dispatch tool for [Pi](https://github.com/earendil-works/pi) —
|
|
3
|
+
> Teammate dispatch tool for [Pi](https://github.com/earendil-works/pi) — unified TaskSpec with DAG variable referencing
|
|
4
4
|
|
|
5
|
-
Pi extension implementing teammate dispatch with **
|
|
6
|
-
|
|
7
|
-
## Features
|
|
8
|
-
|
|
9
|
-
### Three-Axis Control
|
|
10
|
-
|
|
11
|
-
| Axis | Field | Values | Purpose |
|
|
12
|
-
|------|-------|--------|---------|
|
|
13
|
-
| Addressability | `name` | string \| omit | Cross-agent routing via name |
|
|
14
|
-
| Result Routing | `reply_to` | `"caller"` \| `"main"` | Where results go |
|
|
15
|
-
| Lifecycle | `lifecycle` | `"ephemeral"` \| `"resident"` | One-shot or persistent |
|
|
16
|
-
|
|
17
|
-
**Protocol version gate** — v2 (default) routes results to `caller`; v1 compat routes named agents to `main`. Explicit `reply_to` always wins.
|
|
18
|
-
|
|
19
|
-
### Execution Modes
|
|
20
|
-
|
|
21
|
-
- **Single** — dispatch one agent with a task
|
|
22
|
-
- **Parallel** — `tasks[]` runs multiple agents concurrently with configurable `concurrency`
|
|
23
|
-
- **Chain** — `chain[]` sequential pipeline where each step receives `{previous}` result
|
|
24
|
-
|
|
25
|
-
### Reliability
|
|
26
|
-
|
|
27
|
-
- **Model fallback chain** — primary model → `fallbackModels[]` from agent config → automatic retry on model failures
|
|
28
|
-
- **Nesting depth guard** — `PI_TEAMMATE_DEPTH` env tracking with configurable max (default: 3) prevents fork bombs
|
|
29
|
-
- **Windows-safe pi resolution** — `getPiSpawnCommand()` resolves the pi binary via env override, Windows script detection, or PATH
|
|
30
|
-
- **Abort signal** — SIGTERM → 5s grace → SIGKILL
|
|
31
|
-
|
|
32
|
-
### Output & Tracking
|
|
33
|
-
|
|
34
|
-
- **Structured output** — `outputSchema` validates child output against JSON Schema, returns parsed `structuredOutput`
|
|
35
|
-
- **Rich progress** — `AgentProgress` with `recentTools[]`, `toolCount`, `tokens`, `durationMs`, `lastActivityAt`
|
|
36
|
-
- **Session management** — derives child session directory from parent session, supports `context: "fork"`
|
|
37
|
-
- **Correlation ID** — auto-generated per dispatch for result routing
|
|
38
|
-
|
|
39
|
-
### Agent Definitions
|
|
40
|
-
|
|
41
|
-
Agents are markdown files with YAML frontmatter — discovered from project (`.pi/agents/`), user (`~/.pi/agent/extensions/teammate/agents/`), or builtin locations. Project overrides user overrides builtin.
|
|
42
|
-
|
|
43
|
-
## Install
|
|
44
|
-
|
|
45
|
-
```bash
|
|
46
|
-
pi install npm:@pi-maestro/teammate
|
|
47
|
-
# or from local path
|
|
48
|
-
pi install ./pi-teammate
|
|
49
|
-
```
|
|
5
|
+
Pi extension implementing teammate dispatch with **unified TaskSpec model**. Single agent, parallel fan-out, sequential chains, and arbitrary DAGs all use the same schema — execution order is determined by `{name}` variable references between tasks.
|
|
50
6
|
|
|
51
7
|
## Quick Start
|
|
52
8
|
|
|
@@ -56,7 +12,7 @@ pi install ./pi-teammate
|
|
|
56
12
|
{ agent: "delegate", task: "Implement the auth middleware" }
|
|
57
13
|
```
|
|
58
14
|
|
|
59
|
-
### Parallel
|
|
15
|
+
### Parallel (no references = concurrent)
|
|
60
16
|
|
|
61
17
|
```
|
|
62
18
|
{ tasks: [
|
|
@@ -68,22 +24,34 @@ pi install ./pi-teammate
|
|
|
68
24
|
}
|
|
69
25
|
```
|
|
70
26
|
|
|
71
|
-
### Chain
|
|
27
|
+
### Chain (linear references = sequential)
|
|
72
28
|
|
|
73
29
|
```
|
|
74
|
-
{
|
|
75
|
-
{ agent: "scout", task: "Find the auth module structure" },
|
|
76
|
-
{ agent: "delegate", task: "Based on this context: {
|
|
30
|
+
{ tasks: [
|
|
31
|
+
{ agent: "scout", name: "recon", task: "Find the auth module structure" },
|
|
32
|
+
{ agent: "delegate", task: "Based on this context: {recon}\n\nRefactor the auth module" }
|
|
77
33
|
]
|
|
78
34
|
}
|
|
79
35
|
```
|
|
80
36
|
|
|
81
|
-
###
|
|
37
|
+
### DAG (mixed references = auto-scheduling)
|
|
82
38
|
|
|
83
39
|
```
|
|
84
|
-
{
|
|
40
|
+
{ tasks: [
|
|
41
|
+
{ agent: "scout", name: "api", task: "List all API routes",
|
|
42
|
+
outputSchema: {
|
|
43
|
+
type: "object",
|
|
44
|
+
properties: { routes: { type: "array", items: { type: "string" } } },
|
|
45
|
+
required: ["routes"]
|
|
46
|
+
} },
|
|
47
|
+
{ agent: "scout", name: "db", task: "Map the database schema" },
|
|
48
|
+
{ agent: "reviewer", task: "Routes: {api.routes}\nDB: {db}\n\nCheck consistency" }
|
|
49
|
+
]
|
|
50
|
+
}
|
|
85
51
|
```
|
|
86
52
|
|
|
53
|
+
`api` and `db` run in parallel. `reviewer` waits for both, with `{api.routes}` resolved from structured output and `{db}` from text output.
|
|
54
|
+
|
|
87
55
|
### Structured Output
|
|
88
56
|
|
|
89
57
|
```
|
|
@@ -96,6 +64,147 @@ pi install ./pi-teammate
|
|
|
96
64
|
}
|
|
97
65
|
```
|
|
98
66
|
|
|
67
|
+
In multi-task mode, structured outputs are aggregated by task `name` in the result's `structuredOutput` field.
|
|
68
|
+
|
|
69
|
+
## Core Concepts
|
|
70
|
+
|
|
71
|
+
### Two Rules
|
|
72
|
+
|
|
73
|
+
1. **Reference = dependency**: `{name}` in a task's description means "wait for the task named `name` to complete, then inject its output here"
|
|
74
|
+
2. **No reference = parallel**: tasks with no dependencies run concurrently (bounded by `concurrency`)
|
|
75
|
+
|
|
76
|
+
No `mode` field needed — the execution engine infers parallel, chain, or graph from the reference topology.
|
|
77
|
+
|
|
78
|
+
### Variable References
|
|
79
|
+
|
|
80
|
+
| Syntax | Resolves to |
|
|
81
|
+
|--------|-------------|
|
|
82
|
+
| `{name}` | Full text output; or JSON string if the task has `outputSchema` |
|
|
83
|
+
| `{name.field}` | Field from structured output |
|
|
84
|
+
| `{name.arr[0].path}` | Nested field with array indexing |
|
|
85
|
+
|
|
86
|
+
Only tasks with a `name` field can be referenced. Non-task `{braces}` (JSON, format strings) are left untouched.
|
|
87
|
+
|
|
88
|
+
### Default Inheritance
|
|
89
|
+
|
|
90
|
+
Top-level fields serve as defaults for all tasks:
|
|
91
|
+
|
|
92
|
+
| Field | Scope | Override |
|
|
93
|
+
|-------|-------|----------|
|
|
94
|
+
| `model` | Default model for all tasks | Per-task `model` wins |
|
|
95
|
+
| `cwd` | Default working directory | Per-task `cwd` wins |
|
|
96
|
+
| `outputSchema` | Default schema for all tasks | Per-task `outputSchema` wins |
|
|
97
|
+
| `timeoutMs` | Default timeout | Per-task `timeoutMs` wins |
|
|
98
|
+
|
|
99
|
+
### Three-Axis Control
|
|
100
|
+
|
|
101
|
+
| Axis | Field | Values | Purpose |
|
|
102
|
+
|------|-------|--------|---------|
|
|
103
|
+
| Addressability | `name` | string \| omit | Variable referencing + teammate-send routing |
|
|
104
|
+
| Result Routing | `reply_to` | `"caller"` \| `"main"` | Where results go |
|
|
105
|
+
| Lifecycle | `lifecycle` | `"ephemeral"` \| `"resident"` | One-shot or persistent |
|
|
106
|
+
|
|
107
|
+
**Protocol version gate** — v2 (default) routes results to `caller`; v1 compat routes named agents to `main`. Explicit `reply_to` always wins.
|
|
108
|
+
|
|
109
|
+
## TaskSpec Schema
|
|
110
|
+
|
|
111
|
+
```typescript
|
|
112
|
+
interface TaskSpec {
|
|
113
|
+
agent: string; // Agent name (matches agents/*.md filename)
|
|
114
|
+
task?: string; // Task description with {name} variable support
|
|
115
|
+
name?: string; // Identifier for referencing and teammate-send
|
|
116
|
+
model?: string; // Model override
|
|
117
|
+
cwd?: string; // Working directory
|
|
118
|
+
outputSchema?: object; // JSON Schema for structured output
|
|
119
|
+
timeoutMs?: number; // Timeout in milliseconds
|
|
120
|
+
}
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## Full Parameters
|
|
124
|
+
|
|
125
|
+
```typescript
|
|
126
|
+
interface TeammateParams extends TaskSpec {
|
|
127
|
+
// Multi-task
|
|
128
|
+
tasks?: TaskSpec[]; // Multiple tasks with {name} references
|
|
129
|
+
concurrency?: number; // Max concurrent tasks (default: 4)
|
|
130
|
+
|
|
131
|
+
// Execution control (applies to ALL modes)
|
|
132
|
+
background?: boolean; // Run in background (default: true)
|
|
133
|
+
context?: "fresh" | "fork";
|
|
134
|
+
|
|
135
|
+
// P0 three-axis
|
|
136
|
+
reply_to?: "caller" | "main";
|
|
137
|
+
protocol_version?: number;
|
|
138
|
+
|
|
139
|
+
// Deprecated
|
|
140
|
+
chain?: Array<{ agent, task?, model? }>; // Use tasks with {name} references
|
|
141
|
+
}
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
## Validation & Error Handling
|
|
145
|
+
|
|
146
|
+
- **Duplicate names**: detected before execution, all tasks fail with error
|
|
147
|
+
- **Circular dependencies**: detected before execution via cycle detection
|
|
148
|
+
- **Missing reference**: `{unknown}` left as literal text (not a task name)
|
|
149
|
+
- **Field access without schema**: error when `{name.field}` used but task has no `outputSchema`
|
|
150
|
+
- **Upstream failure**: dependent tasks are skipped with "upstream dependency failed"
|
|
151
|
+
|
|
152
|
+
## Deprecated: chain[]
|
|
153
|
+
|
|
154
|
+
The `chain` field is preserved for backward compatibility. It normalizes internally to `tasks` with sequential `{_stepN}` references:
|
|
155
|
+
|
|
156
|
+
```
|
|
157
|
+
// This chain:
|
|
158
|
+
{ chain: [
|
|
159
|
+
{ agent: "scout", task: "Find auth code" },
|
|
160
|
+
{ agent: "delegate", task: "Fix: {previous}" }
|
|
161
|
+
]
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// Is equivalent to:
|
|
165
|
+
{ tasks: [
|
|
166
|
+
{ agent: "scout", name: "_step0", task: "Find auth code" },
|
|
167
|
+
{ agent: "delegate", name: "_step1", task: "Fix: {_step0}" }
|
|
168
|
+
]
|
|
169
|
+
}
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
## Flat Agent Model
|
|
173
|
+
|
|
174
|
+
All agents are managed by the root process in a single flat `activeRuns` pool, regardless of who requested the spawn. Child agents that call the teammate tool send a proxy request to the root, which spawns the new agent as a peer — not a nested subprocess.
|
|
175
|
+
|
|
176
|
+
### How It Works
|
|
177
|
+
|
|
178
|
+
```
|
|
179
|
+
coordinator calls teammate({ agent: "scout", name: "recon" })
|
|
180
|
+
│ stdout: teammate_proxy_request
|
|
181
|
+
▼
|
|
182
|
+
Root spawns scout → registers in root's activeRuns/namedAgents
|
|
183
|
+
│ IPC: teammate_proxy_result
|
|
184
|
+
▼
|
|
185
|
+
coordinator receives result
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
All agents are flat peers:
|
|
189
|
+
- `teammate-send({ to: "name" })` = one lookup in `namedAgents` → stdin. Direct delivery.
|
|
190
|
+
- `teammate-list` = iterate `activeRuns`. Flat, simple.
|
|
191
|
+
- `teammate-watch` = read agent's `outputLog`. Direct.
|
|
192
|
+
|
|
193
|
+
### Child Proxy Tools
|
|
194
|
+
|
|
195
|
+
Child processes register proxy versions of all teammate tools. Each proxy:
|
|
196
|
+
1. Writes a `teammate_proxy_request` JSON line to stdout
|
|
197
|
+
2. Awaits the result via Node.js IPC (`process.on("message")`)
|
|
198
|
+
|
|
199
|
+
The root's event parser intercepts these requests and executes them locally. The IPC channel is established via `stdio: ["pipe","pipe","pipe","ipc"]` at spawn time.
|
|
200
|
+
|
|
201
|
+
## Reliability
|
|
202
|
+
|
|
203
|
+
- **Model fallback chain** — primary model → `fallbackModels[]` from agent config → automatic retry
|
|
204
|
+
- **Flat agent pool** — all agents managed by root process; child proxy tools forward spawn requests to root; depth guard (`PI_TEAMMATE_DEPTH`) prevents runaway recursion
|
|
205
|
+
- **Windows-safe pi resolution** — `getPiSpawnCommand()` resolves the pi binary via env override, Windows script detection, or PATH
|
|
206
|
+
- **Abort signal** — SIGTERM → 5s grace → SIGKILL
|
|
207
|
+
|
|
99
208
|
## Agent Definition Format
|
|
100
209
|
|
|
101
210
|
Create `agents/my-agent.md`:
|
|
@@ -114,8 +223,6 @@ defaultContext: fresh
|
|
|
114
223
|
---
|
|
115
224
|
|
|
116
225
|
You are a specialized agent. Your system prompt goes here.
|
|
117
|
-
|
|
118
|
-
Use the provided tools to accomplish the task.
|
|
119
226
|
```
|
|
120
227
|
|
|
121
228
|
### Frontmatter Fields
|
|
@@ -133,37 +240,12 @@ Use the provided tools to accomplish the task.
|
|
|
133
240
|
| `inheritSkills` | bool | false | Inherit parent skills |
|
|
134
241
|
| `defaultContext` | fresh\|fork | fresh | Default context mode |
|
|
135
242
|
|
|
136
|
-
##
|
|
137
|
-
|
|
138
|
-
```
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
│ teammate tool call │
|
|
143
|
-
│ │ │
|
|
144
|
-
│ ├── resolve agent (project > user > built) │
|
|
145
|
-
│ ├── resolve reply_to (protocol gate) │
|
|
146
|
-
│ ├── check depth guard │
|
|
147
|
-
│ ├── build model candidates │
|
|
148
|
-
│ │ │
|
|
149
|
-
│ ▼ │
|
|
150
|
-
│ ┌─────────────────────────────────────┐ │
|
|
151
|
-
│ │ spawn("pi", ["--mode","json","-p"])│ │
|
|
152
|
-
│ │ env: PI_TEAMMATE_CHILD=1 │ │
|
|
153
|
-
│ │ PI_TEAMMATE_DEPTH=N │ │
|
|
154
|
-
│ │ PI_TEAMMATE_CORRELATION_ID=… │ │
|
|
155
|
-
│ │ PI_TEAMMATE_REPLY_TO=caller │ │
|
|
156
|
-
│ │ │ │
|
|
157
|
-
│ │ stdout: JSON lines ──────────────► │ parse │
|
|
158
|
-
│ │ (message_end, tool_result_end, │ events │
|
|
159
|
-
│ │ usage, error) │ │
|
|
160
|
-
│ └─────────────────────────────────────┘ │
|
|
161
|
-
│ │ │
|
|
162
|
-
│ ├── accumulate usage │
|
|
163
|
-
│ ├── track progress (AgentProgress) │
|
|
164
|
-
│ ├── model fallback on failure │
|
|
165
|
-
│ └── return SingleResult │
|
|
166
|
-
└─────────────────────────────────────────────────┘
|
|
243
|
+
## Install
|
|
244
|
+
|
|
245
|
+
```bash
|
|
246
|
+
pi install npm:@pi-maestro/teammate
|
|
247
|
+
# or from local path
|
|
248
|
+
pi install ./pi-teammate
|
|
167
249
|
```
|
|
168
250
|
|
|
169
251
|
## Environment Variables
|
package/agents/coordinator.md
CHANGED
|
@@ -1,19 +1,24 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: coordinator
|
|
3
|
-
description: Orchestration-aware teammate agent for multi-step coordination
|
|
3
|
+
description: Orchestration-aware teammate agent for multi-step task coordination with DAG variable referencing
|
|
4
4
|
systemPromptMode: replace
|
|
5
5
|
inheritProjectContext: true
|
|
6
6
|
thinking: high
|
|
7
|
-
tools: read, grep, find, ls, bash, edit, write
|
|
7
|
+
tools: read, grep, find, ls, bash, edit, write, teammate, teammate-send, teammate-list, teammate-watch
|
|
8
8
|
inheritSkills: false
|
|
9
9
|
---
|
|
10
10
|
|
|
11
|
-
You are a coordinator agent responsible for orchestrating multi-step tasks.
|
|
11
|
+
You are a coordinator agent responsible for orchestrating multi-step tasks.
|
|
12
|
+
|
|
13
|
+
When dispatching subtasks via the teammate tool, use the unified TaskSpec model:
|
|
14
|
+
- Give each task a `name` so downstream tasks can reference its output via `{name}`
|
|
15
|
+
- Use `outputSchema` when a task's output needs to be consumed as structured data by dependents via `{name.field}`
|
|
16
|
+
- Tasks with no `{name}` references run in parallel; tasks that reference others wait automatically
|
|
12
17
|
|
|
13
18
|
Your approach:
|
|
14
|
-
1. Analyze the task requirements and
|
|
15
|
-
2.
|
|
16
|
-
3.
|
|
17
|
-
4.
|
|
19
|
+
1. Analyze the task requirements and decompose into named subtasks
|
|
20
|
+
2. Define data flow between subtasks using `{name}` variable references
|
|
21
|
+
3. Let the execution engine resolve the dependency graph — no need to manually order
|
|
22
|
+
4. Verify results and synthesize a coherent output
|
|
18
23
|
|
|
19
24
|
Be methodical and thorough. Document your reasoning for key decisions. If a step fails, attempt recovery before reporting failure.
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-maestro-teammate",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Pi extension for teammate dispatch with P0 three-axis decoupling (name, reply_to
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"description": "Pi extension for teammate dispatch with P0 three-axis decoupling (name, reply_to)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"pi-package",
|