@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 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. Use before planning or implementing to gather context. | read, grep, find, ls, bash | openai-codex/gpt-5.5 |
106
- | **planner** | Analyzes requirements and produces a step-by-step implementation plan. Read-only. Does not write code. Interactive. | read, grep, find, ls, bash | openai-codex/gpt-5.5 |
107
- | **oracle** | Evaluates critical decisions, surfaces blind spots, and challenges assumptions. Read-only. Does not implement. Interactive. | read, grep, find, ls, bash | openai-codex/gpt-5.5 |
108
- | **code-reviewer** | Reviews code changes for bugs, security issues, and correctness. Read-only. Does not fix issues. | read, grep, find, ls, bash | openai-codex/gpt-5.2 |
109
- | **quality-reviewer** | Reviews code structure for maintainability, duplication, and complexity. Read-only. Does not look for bugs. | read, grep, find, ls, bash | openai-codex/gpt-5.2 |
110
- | **worker** | Implements code changes, fixes, and refactors autonomously. Has full read-write access to the codebase. | all | openai-codex/gpt-5.5 |
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
 
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: code-reviewer
3
3
  description: Reviews scoped code for actionable bugs. Read-only.
4
- model: openai-codex/gpt-5.2
4
+ model: openai-codex/gpt-5.5
5
5
  thinking: high
6
6
  tools: read, grep, find, ls, bash
7
7
  ---
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: quality-reviewer
3
3
  description: Reviews scoped code for maintainability, duplication, and complexity. Read-only.
4
- model: openai-codex/gpt-5.2
4
+ model: openai-codex/gpt-5.5
5
5
  thinking: high
6
6
  tools: read, grep, find, ls, bash
7
7
  ---
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
- export const crewRuntime = globalWithCrewRuntime[crewRuntimeKey] ??= new CrewRuntime();
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
 
@@ -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
- task: Type.String({ description: "Task to delegate to the subagent" }),
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: Include only needed context: constraints, relevant files, acceptance criteria, and expected output.",
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
- return renderCrewCall(theme, "crew_spawn", args.subagent || "...", args.task);
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 (!ctx.hasUI) {
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.19",
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.76.0",
47
- "@earendil-works/pi-ai": "^0.76.0",
48
- "@earendil-works/pi-coding-agent": "^0.76.0",
49
- "@earendil-works/pi-tui": "^0.76.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.39",
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`, ensure the brief is self-contained but not mechanically templated. Include only information that helps this specific subagent do this specific task:
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 delegation; ownership transfers after spawn.
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.
@@ -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 spawn brief 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.
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