@melihmucuk/pi-crew 1.0.19 → 1.0.20
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 +9 -9
- package/agents/code-reviewer.md +1 -1
- package/agents/quality-reviewer.md +1 -1
- package/extension/crew.ts +17 -4
- package/extension/subagent-session.ts +11 -0
- package/extension/tools.ts +13 -5
- package/extension/ui.ts +8 -2
- package/package.json +6 -6
- package/skills/pi-crew/REFERENCE.md +7 -2
- package/skills/pi-crew/SKILL.md +6 -1
package/README.md
CHANGED
|
@@ -34,7 +34,7 @@ Lists available subagent definitions and active subagents owned by the current s
|
|
|
34
34
|
|
|
35
35
|
#### `crew_spawn`
|
|
36
36
|
|
|
37
|
-
Spawns a subagent in an isolated session. The subagent runs in the background with its own context window, tools, and skills. When it finishes, the result is delivered to the session that spawned it as a steering message that triggers a new turn. If that session is not active, the result is queued until you switch back to it.
|
|
37
|
+
Spawns a subagent in an isolated session. Each spawn includes a concise `brief` label for session lists and a full self-contained `task`. The subagent runs in the background with its own context window, tools, and skills. When it finishes, the result is delivered to the session that spawned it as a steering message that triggers a new turn. If that session is not active, the result is queued until you switch back to it.
|
|
38
38
|
|
|
39
39
|
```
|
|
40
40
|
"spawn scout and find all API endpoints and their authentication methods"
|
|
@@ -100,14 +100,14 @@ A bundled orchestration skill that provides best practices for delegating work t
|
|
|
100
100
|
|
|
101
101
|
pi-crew ships with six subagent definitions that cover common workflows:
|
|
102
102
|
|
|
103
|
-
| Subagent | Purpose | Tools | Model |
|
|
104
|
-
| -------------------- | ------------------------------------------------------------------------------------------------------------------------ | -------------------------- | --------------------------- |
|
|
105
|
-
| **scout** | Investigates codebase and returns structured findings. Read-only.
|
|
106
|
-
| **planner** |
|
|
107
|
-
| **oracle** | Evaluates critical decisions, surfaces blind spots, and challenges assumptions. Read-only.
|
|
108
|
-
| **code-reviewer** | Reviews code
|
|
109
|
-
| **quality-reviewer** | Reviews code
|
|
110
|
-
| **worker** | Implements code changes
|
|
103
|
+
| Subagent | Purpose | Tools | Model | Thinking |
|
|
104
|
+
| -------------------- | ------------------------------------------------------------------------------------------------------------------------ | -------------------------- | --------------------------- | -------- |
|
|
105
|
+
| **scout** | Investigates codebase and returns structured findings. Read-only. | read, grep, find, ls, bash | openai-codex/gpt-5.5 | off |
|
|
106
|
+
| **planner** | Produces deterministic implementation plans. Read-only. Does not write code. | read, grep, find, ls, bash | openai-codex/gpt-5.5 | high |
|
|
107
|
+
| **oracle** | Evaluates critical decisions, surfaces blind spots, and challenges assumptions. Read-only. | read, grep, find, ls, bash | openai-codex/gpt-5.5 | xhigh |
|
|
108
|
+
| **code-reviewer** | Reviews scoped code for actionable bugs. Read-only. | read, grep, find, ls, bash | openai-codex/gpt-5.5 | high |
|
|
109
|
+
| **quality-reviewer** | Reviews scoped code for maintainability, duplication, and complexity. Read-only. | read, grep, find, ls, bash | openai-codex/gpt-5.5 | high |
|
|
110
|
+
| **worker** | Implements scoped code changes safely and verifies them. | all | openai-codex/gpt-5.5 | low |
|
|
111
111
|
|
|
112
112
|
Read-only bundled subagents still keep `bash` for inspection workflows like `git` and `ast-grep`. This is an instruction-level contract, not a sandbox boundary.
|
|
113
113
|
|
package/agents/code-reviewer.md
CHANGED
package/extension/crew.ts
CHANGED
|
@@ -27,6 +27,7 @@ export interface SubagentState {
|
|
|
27
27
|
id: string;
|
|
28
28
|
agentConfig: AgentConfig;
|
|
29
29
|
task: string;
|
|
30
|
+
brief: string;
|
|
30
31
|
status: SubagentStatus;
|
|
31
32
|
ownerSessionId: string;
|
|
32
33
|
session: AgentSession | null;
|
|
@@ -63,6 +64,7 @@ export interface SpawnContext {
|
|
|
63
64
|
agentDir: string;
|
|
64
65
|
parentSessionFile?: string;
|
|
65
66
|
onWarning?: (message: string) => void;
|
|
67
|
+
brief?: string;
|
|
66
68
|
}
|
|
67
69
|
|
|
68
70
|
type SettledSubagentStatus = Extract<SubagentStatus, "done" | "waiting" | "error" | "aborted">;
|
|
@@ -149,7 +151,7 @@ export class CrewRuntime {
|
|
|
149
151
|
ctx: SpawnContext,
|
|
150
152
|
extensionResolvedPath: string,
|
|
151
153
|
): string {
|
|
152
|
-
const state = this.createAgent(agentConfig, task, ownerSessionId);
|
|
154
|
+
const state = this.createAgent(agentConfig, task, ctx.brief ?? "", ownerSessionId);
|
|
153
155
|
this.refreshWidgetFor(ownerSessionId);
|
|
154
156
|
this.runner.start(state, {
|
|
155
157
|
cwd,
|
|
@@ -226,12 +228,13 @@ export class CrewRuntime {
|
|
|
226
228
|
.map(buildActiveAgentSummary);
|
|
227
229
|
}
|
|
228
230
|
|
|
229
|
-
private createAgent(agentConfig: AgentConfig, task: string, ownerSessionId: string): SubagentState {
|
|
231
|
+
private createAgent(agentConfig: AgentConfig, task: string, brief: string, ownerSessionId: string): SubagentState {
|
|
230
232
|
const id = generateId(agentConfig.name, new Set(this.agents.keys()));
|
|
231
233
|
const state: SubagentState = {
|
|
232
234
|
id,
|
|
233
235
|
agentConfig,
|
|
234
236
|
task,
|
|
237
|
+
brief,
|
|
235
238
|
status: "running",
|
|
236
239
|
ownerSessionId,
|
|
237
240
|
session: null,
|
|
@@ -371,7 +374,17 @@ export class CrewRuntime {
|
|
|
371
374
|
}
|
|
372
375
|
}
|
|
373
376
|
|
|
377
|
+
const CREW_RUNTIME_VERSION = 2;
|
|
374
378
|
const crewRuntimeKey = Symbol.for("pi-crew.runtime");
|
|
375
|
-
const globalWithCrewRuntime = globalThis as typeof globalThis & Record<symbol, CrewRuntime | undefined>;
|
|
379
|
+
const globalWithCrewRuntime = globalThis as typeof globalThis & Record<symbol, (CrewRuntime & { __piCrewRuntimeVersion?: number }) | undefined>;
|
|
376
380
|
|
|
377
|
-
|
|
381
|
+
function createCrewRuntime(): CrewRuntime & { __piCrewRuntimeVersion?: number } {
|
|
382
|
+
const runtime = new CrewRuntime() as CrewRuntime & { __piCrewRuntimeVersion?: number };
|
|
383
|
+
runtime.__piCrewRuntimeVersion = CREW_RUNTIME_VERSION;
|
|
384
|
+
return runtime;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
const existingRuntime = globalWithCrewRuntime[crewRuntimeKey];
|
|
388
|
+
export const crewRuntime = existingRuntime?.__piCrewRuntimeVersion === CREW_RUNTIME_VERSION
|
|
389
|
+
? existingRuntime
|
|
390
|
+
: (globalWithCrewRuntime[crewRuntimeKey] = createCrewRuntime());
|
|
@@ -175,6 +175,16 @@ function isAborted(state: SubagentState): boolean {
|
|
|
175
175
|
return state.status === "aborted";
|
|
176
176
|
}
|
|
177
177
|
|
|
178
|
+
function normalizeSessionNamePart(value: string): string {
|
|
179
|
+
return value.replace(/[\u0000-\u001f\u007f]/g, " ").replace(/\s+/g, " ").trim();
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
export function formatSubagentSessionName(state: Pick<SubagentState, "agentConfig" | "brief" | "id">): string {
|
|
183
|
+
const agentName = normalizeSessionNamePart(state.agentConfig.name) || "subagent";
|
|
184
|
+
const brief = normalizeSessionNamePart(state.brief) || state.id;
|
|
185
|
+
return `crew: ${agentName} · ${brief}`;
|
|
186
|
+
}
|
|
187
|
+
|
|
178
188
|
export class SubagentSessionRunner implements SubagentRunner {
|
|
179
189
|
constructor(private readonly callbacks: SubagentRunnerCallbacks) {}
|
|
180
190
|
|
|
@@ -211,6 +221,7 @@ export class SubagentSessionRunner implements SubagentRunner {
|
|
|
211
221
|
return false;
|
|
212
222
|
}
|
|
213
223
|
state.session = session;
|
|
224
|
+
session.setSessionName(formatSubagentSessionName(state));
|
|
214
225
|
return true;
|
|
215
226
|
}
|
|
216
227
|
|
package/extension/tools.ts
CHANGED
|
@@ -175,24 +175,29 @@ export function registerCrewTools(pi: ExtensionAPI, crew: CrewRuntime, extension
|
|
|
175
175
|
},
|
|
176
176
|
});
|
|
177
177
|
|
|
178
|
-
registerActionTool<{ subagent: string; task: string }>(pi, {
|
|
178
|
+
registerActionTool<{ subagent: string; brief: string; task: string }>(pi, {
|
|
179
179
|
name: "crew_spawn",
|
|
180
180
|
label: "Spawn Crew",
|
|
181
181
|
description:
|
|
182
182
|
"Spawn a non-blocking subagent that runs in an isolated session. The subagent works independently while your session stays interactive. Results are delivered back to your session as steering messages.",
|
|
183
183
|
parameters: Type.Object({
|
|
184
184
|
subagent: Type.String({ description: "Subagent name from crew_list" }),
|
|
185
|
-
|
|
185
|
+
brief: Type.String({ description: "Concise task label for session lists, ideally under 80 characters. This is not the full task." }),
|
|
186
|
+
task: Type.String({ description: "Full self-contained task to delegate to the subagent" }),
|
|
186
187
|
}),
|
|
187
188
|
promptSnippet: "Spawn a non-blocking subagent. Use crew_list first to see available subagents.",
|
|
188
189
|
promptGuidelines: [
|
|
189
190
|
"crew_spawn: Spawn a discovered subagent for one clearly delegated, self-contained task.",
|
|
190
|
-
"crew_spawn:
|
|
191
|
+
"crew_spawn: Provide brief as a concise human-readable task label for session lists, ideally under 80 characters; do not put the full task there.",
|
|
192
|
+
"crew_spawn: Include only needed context in task: constraints, relevant files, acceptance criteria, and expected output.",
|
|
191
193
|
"crew_spawn: After spawning, ownership transfers to the subagent; do not work on that task yourself.",
|
|
192
194
|
"crew_spawn: Results arrive as steering messages; do not poll crew_list or fabricate results.",
|
|
193
195
|
"crew_spawn: Use the bundled pi-crew skill for detailed delegation patterns.",
|
|
194
196
|
],
|
|
195
197
|
action: (params, ctx) => {
|
|
198
|
+
const brief = params.brief.trim();
|
|
199
|
+
if (!brief) return toolError("brief is required and must not be empty.");
|
|
200
|
+
|
|
196
201
|
const toolCtx = getToolContext(ctx);
|
|
197
202
|
const { agents, warnings } = discoverAgents(toolCtx.cwd);
|
|
198
203
|
notifyDiscoveryWarnings(ctx, shownDiscoveryWarnings, warnings);
|
|
@@ -208,6 +213,7 @@ export function registerCrewTools(pi: ExtensionAPI, crew: CrewRuntime, extension
|
|
|
208
213
|
toolCtx.cwd,
|
|
209
214
|
toolCtx.callerSessionId,
|
|
210
215
|
{
|
|
216
|
+
brief,
|
|
211
217
|
model: ctx.model,
|
|
212
218
|
modelRegistry: ctx.modelRegistry,
|
|
213
219
|
agentDir: getAgentDir(),
|
|
@@ -218,11 +224,13 @@ export function registerCrewTools(pi: ExtensionAPI, crew: CrewRuntime, extension
|
|
|
218
224
|
);
|
|
219
225
|
return toolSuccess(
|
|
220
226
|
`Subagent '${subagent.name}' spawned as ${id}. Result will be delivered as a steering message when done.`,
|
|
221
|
-
{ id, agentName: subagent.name, task: params.task },
|
|
227
|
+
{ id, agentName: subagent.name, brief, task: params.task },
|
|
222
228
|
);
|
|
223
229
|
},
|
|
224
230
|
renderCall(args, theme, _context) {
|
|
225
|
-
|
|
231
|
+
const subagent = args.subagent || "...";
|
|
232
|
+
const title = args.brief ? `${subagent} · ${args.brief}` : subagent;
|
|
233
|
+
return renderCrewCall(theme, "crew_spawn", title, args.task);
|
|
226
234
|
},
|
|
227
235
|
});
|
|
228
236
|
|
package/extension/ui.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { pathToFileURL } from "node:url";
|
|
1
2
|
import type { AgentToolResult } from "@earendil-works/pi-agent-core";
|
|
2
3
|
import {
|
|
3
4
|
type ExtensionAPI,
|
|
@@ -144,6 +145,11 @@ function renderWarningMessage(content: unknown, theme: MessageRendererTheme): Bo
|
|
|
144
145
|
return box;
|
|
145
146
|
}
|
|
146
147
|
|
|
148
|
+
function linkFilePath(filePath: string): string {
|
|
149
|
+
const url = pathToFileURL(filePath).href;
|
|
150
|
+
return `\x1b]8;;${url}\x07${filePath}\x1b]8;;\x07`;
|
|
151
|
+
}
|
|
152
|
+
|
|
147
153
|
export function registerCrewMessageRenderers(pi: ExtensionAPI): void {
|
|
148
154
|
pi.registerMessageRenderer("crew-result", (message, { expanded }, theme) => {
|
|
149
155
|
const details = message.details as CrewResultMessageDetails | undefined;
|
|
@@ -158,7 +164,7 @@ export function registerCrewMessageRenderers(pi: ExtensionAPI): void {
|
|
|
158
164
|
box.addChild(new Text(header, 0, 0));
|
|
159
165
|
|
|
160
166
|
if (details?.sessionFile) {
|
|
161
|
-
box.addChild(new Text(theme.fg("muted", `📁 ${details.sessionFile}`), 0, 0));
|
|
167
|
+
box.addChild(new Text(theme.fg("muted", `📁 ${linkFilePath(details.sessionFile)}`), 0, 0));
|
|
162
168
|
}
|
|
163
169
|
|
|
164
170
|
if (body) {
|
|
@@ -242,7 +248,7 @@ function syncWidgetText(state: WidgetState, agents: ActiveAgentSummary[]): void
|
|
|
242
248
|
}
|
|
243
249
|
|
|
244
250
|
export function updateWidget(ctx: ExtensionContext, crew: CrewRuntime): void {
|
|
245
|
-
if (
|
|
251
|
+
if (ctx.mode !== "tui") {
|
|
246
252
|
clearWidget();
|
|
247
253
|
return;
|
|
248
254
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@melihmucuk/pi-crew",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.20",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Non-blocking subagent orchestration for pi coding agent",
|
|
6
6
|
"files": [
|
|
@@ -43,13 +43,13 @@
|
|
|
43
43
|
"typebox": "*"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
|
-
"@earendil-works/pi-agent-core": "^0.
|
|
47
|
-
"@earendil-works/pi-ai": "^0.
|
|
48
|
-
"@earendil-works/pi-coding-agent": "^0.
|
|
49
|
-
"@earendil-works/pi-tui": "^0.
|
|
46
|
+
"@earendil-works/pi-agent-core": "^0.78.1",
|
|
47
|
+
"@earendil-works/pi-ai": "^0.78.1",
|
|
48
|
+
"@earendil-works/pi-coding-agent": "^0.78.1",
|
|
49
|
+
"@earendil-works/pi-tui": "^0.78.1",
|
|
50
50
|
"@types/node": "^22.19.17",
|
|
51
51
|
"tsx": "^4.22.3",
|
|
52
|
-
"typebox": "^1.1
|
|
52
|
+
"typebox": "^1.2.1",
|
|
53
53
|
"typescript": "^5.9.3"
|
|
54
54
|
}
|
|
55
55
|
}
|
|
@@ -2,7 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
## Delegation Checklist
|
|
4
4
|
|
|
5
|
-
Before `crew_spawn`,
|
|
5
|
+
Before `crew_spawn`, provide:
|
|
6
|
+
|
|
7
|
+
- `brief`: a concise human-readable task label for session lists, ideally under 80 characters. Use a few words for intent/outcome; do not include the full task, acceptance criteria, long paths, secrets, or mechanical repo state.
|
|
8
|
+
- `task`: a self-contained delegated task body, not mechanically templated.
|
|
9
|
+
|
|
10
|
+
In `task`, include only information that helps this specific subagent do this specific task:
|
|
6
11
|
|
|
7
12
|
- Intent, expected outcome, and relevant user decisions.
|
|
8
13
|
- User-provided references, plus a concise summary after reading them when practical.
|
|
@@ -76,7 +81,7 @@ If ownership overlaps, serialize the work.
|
|
|
76
81
|
## Tool Notes
|
|
77
82
|
|
|
78
83
|
- `crew_list`: discovery before a new spawn decision or requested status snapshot; never completion polling.
|
|
79
|
-
- `crew_spawn`: self-contained
|
|
84
|
+
- `crew_spawn`: provide `brief` plus a self-contained `task`; ownership transfers after spawn.
|
|
80
85
|
- `crew_respond`: send a follow-up to a waiting interactive subagent; fire-and-forget.
|
|
81
86
|
- `crew_done`: close a waiting interactive subagent when complete.
|
|
82
87
|
- `crew_abort`: abort active owned subagents only when obsolete, wrong, or cancelled.
|
package/skills/pi-crew/SKILL.md
CHANGED
|
@@ -21,6 +21,11 @@ See [REFERENCE.md](REFERENCE.md) for examples and detailed handling patterns.
|
|
|
21
21
|
|
|
22
22
|
## Spawn Brief
|
|
23
23
|
|
|
24
|
+
Every `crew_spawn` requires both `brief` and `task`:
|
|
25
|
+
|
|
26
|
+
- `brief`: concise human-readable task label for session lists, ideally under 80 characters. Write the intent/outcome in a few words; do not include the full task, acceptance criteria, long paths, secrets, or mechanical repo state.
|
|
27
|
+
- `task`: self-contained delegated work body with the context the subagent needs.
|
|
28
|
+
|
|
24
29
|
Send a self-contained task, but do not fill a template mechanically. Use only sections that add task-specific value, for example:
|
|
25
30
|
|
|
26
31
|
```md
|
|
@@ -35,7 +40,7 @@ Omit sections that would only restate the selected subagent’s role, default sc
|
|
|
35
40
|
|
|
36
41
|
Include only information that helps this specific subagent do this specific task: intent, expected outcome, relevant decisions, exact errors/output, unusual constraints, and file paths or entry points that genuinely clarify the task. Use short Markdown sections and bullets when they improve scanability, especially for multi-part intent, constraints, observations, requirements, or acceptance criteria; avoid dense paragraphs.
|
|
37
42
|
|
|
38
|
-
For repeated workflows, make each
|
|
43
|
+
For repeated workflows, make each task independent. Do not assume a new subagent knows earlier loop results, owner-session discussion, or what another subagent saw. If prior findings, fixes, decisions, or verification matter, summarize the concrete facts or point to durable artifacts the subagent can inspect. Avoid vague references like “we fixed the first review findings” unless you also state what those findings/fixes were or define the current review target without relying on that history.
|
|
39
44
|
|
|
40
45
|
Do not restate boilerplate implied by the selected subagent’s role, name, or description. Avoid repeating default scope, output format, edit permissions, or repo guidance. Subagents run in the same cwd as the orchestrator, so do not include mechanical Git state they can inspect themselves, such as full changed-file lists, staged/unstaged/untracked inventories, branch/cwd details, or generic project constraints, unless those details define a non-default scope or prevent ambiguity.
|
|
41
46
|
|