@melihmucuk/pi-crew 1.0.7 → 1.0.9

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.
Files changed (45) hide show
  1. package/agents/code-reviewer.md +18 -6
  2. package/agents/planner.md +9 -1
  3. package/agents/quality-reviewer.md +20 -13
  4. package/agents/scout.md +33 -26
  5. package/dist/agent-discovery.d.ts +0 -5
  6. package/dist/agent-discovery.js +1 -1
  7. package/dist/bootstrap-session.d.ts +13 -4
  8. package/dist/bootstrap-session.js +25 -16
  9. package/dist/index.js +37 -7
  10. package/dist/integration/register-command.d.ts +2 -2
  11. package/dist/integration/register-command.js +5 -5
  12. package/dist/integration/register-renderers.js +3 -0
  13. package/dist/integration/register-tools.d.ts +2 -2
  14. package/dist/integration/register-tools.js +2 -2
  15. package/dist/integration/tool-presentation.d.ts +2 -3
  16. package/dist/integration/tool-presentation.js +7 -8
  17. package/dist/integration/tools/crew-abort.d.ts +1 -1
  18. package/dist/integration/tools/crew-abort.js +3 -3
  19. package/dist/integration/tools/crew-done.d.ts +1 -1
  20. package/dist/integration/tools/crew-done.js +2 -2
  21. package/dist/integration/tools/crew-list.d.ts +1 -1
  22. package/dist/integration/tools/crew-list.js +3 -3
  23. package/dist/integration/tools/crew-respond.d.ts +1 -1
  24. package/dist/integration/tools/crew-respond.js +6 -7
  25. package/dist/integration/tools/crew-spawn.d.ts +1 -1
  26. package/dist/integration/tools/crew-spawn.js +17 -14
  27. package/dist/integration/tools/tool-deps.d.ts +3 -2
  28. package/dist/integration.d.ts +2 -2
  29. package/dist/integration.js +3 -3
  30. package/dist/runtime/crew-runtime.d.ts +61 -0
  31. package/dist/{crew-manager.js → runtime/crew-runtime.js} +84 -58
  32. package/dist/runtime/delivery-coordinator.d.ts +16 -7
  33. package/dist/runtime/delivery-coordinator.js +46 -20
  34. package/dist/runtime/subagent-registry.d.ts +1 -0
  35. package/dist/runtime/subagent-registry.js +3 -0
  36. package/dist/runtime/subagent-state.d.ts +2 -0
  37. package/dist/status-widget.d.ts +2 -2
  38. package/dist/status-widget.js +3 -3
  39. package/dist/subagent-messages.d.ts +5 -2
  40. package/dist/subagent-messages.js +5 -4
  41. package/docs/architecture.md +106 -843
  42. package/package.json +1 -1
  43. package/prompts/pi-crew-plan.md +82 -123
  44. package/prompts/pi-crew-review.md +64 -115
  45. package/dist/crew-manager.d.ts +0 -44
@@ -34,7 +34,10 @@ Use best judgement when processing input.
34
34
 
35
35
  - Use the diff to identify which files changed
36
36
  - Read the full file to understand existing patterns, control flow, and error handling
37
+ - Trace the relevant entry point, call chain, and affected callers before deciding something is a bug
38
+ - Look for similar existing implementations to confirm whether the change follows established patterns
37
39
  - Check for existing style guide or conventions files (CONVENTIONS.md, AGENTS.md, .editorconfig, etc.)
40
+ - When useful, validate with available evidence such as tests, typecheck output, call-site search, git history/blame, or existing nearby code
38
41
 
39
42
  ---
40
43
 
@@ -69,6 +72,13 @@ Use best judgement when processing input.
69
72
  - Don't invent hypothetical problems - if an edge case matters, explain the realistic scenario where it breaks
70
73
  - Ask yourself: "Am I flagging this because it's genuinely wrong, or because I feel I should find something?" If you cannot articulate a concrete scenario where the code fails, do not flag it.
71
74
  - If you need more context to be sure, use your available tools to get it
75
+ - Before reporting any bug, validate these points:
76
+ 1. Which invariant, assumption, or contract is violated?
77
+ 2. Which concrete input, state, or environment triggers it?
78
+ 3. Which code path reaches the failure?
79
+ 4. What evidence supports it (existing code, caller usage, tests, typecheck, history, or direct inspection)?
80
+
81
+ If you cannot answer those questions with concrete evidence, do not report the issue.
72
82
 
73
83
  **Don't be a zealot about style.** When checking code against conventions:
74
84
 
@@ -77,7 +87,7 @@ Use best judgement when processing input.
77
87
  - Excessive nesting is a legitimate concern regardless of other style choices.
78
88
  - Don't flag style preferences as issues unless they clearly violate established project conventions.
79
89
 
80
- **Confidence Gate**: For every issue you report, internally rate your confidence (high/medium/low). Only report issues where your confidence is **high**. If medium, investigate further using available tools before reporting. If still medium after investigation, include it only as a **Suggestion** severity regardless of potential impact.
90
+ **Confidence Gate**: For every issue you report, internally rate your confidence (high/medium/low). Only report issues where your confidence is **high**. If confidence is medium or low, investigate further using available tools. If it still is not high confidence after investigation, do not report it as an issue.
81
91
 
82
92
  ---
83
93
 
@@ -131,15 +141,17 @@ For each issue found:
131
141
  **[SEVERITY] Category: Brief title**
132
142
  File: `path/to/file.ts:123`
133
143
  Issue: Clear description of what's wrong
134
- Context: When/how this becomes a problem
144
+ Invariant: Which assumption, contract, or expected behavior is violated
145
+ Context: Which concrete input/state/environment triggers it, and how the code reaches failure
146
+ Evidence: What you validated (call path, caller usage, tests, typecheck, similar code, or file context)
135
147
  Suggestion: How to fix (if not obvious)
136
148
 
137
- At the end of your review, include a summary in this format:
149
+ At the end of your review, include a summary:
138
150
 
139
151
  **Code Review Summary**
140
152
  Files reviewed: [count]
141
- Findings: [count by severity]
142
- Overall confidence: [high/medium]
153
+ Issues found: [count by severity]
154
+ Confidence: [overall confidence in findings: high/medium]
143
155
  Highest-risk area: [which file/module needs attention most and why]
144
156
 
145
- If overall confidence is medium, state what additional context would increase it.
157
+ If confidence is medium, state what additional context would increase it.
package/agents/planner.md CHANGED
@@ -12,7 +12,7 @@ You are an autonomous planning agent that converts messy requests into a **deter
12
12
  - Do **not** implement.
13
13
  - Do **not** modify files.
14
14
  - Gather only the **minimum** project context needed to plan correctly.
15
- - Output exactly one mode: **Blocking Questions** OR **Implementation Plan** (no mixing, no extras).
15
+ - Output exactly one mode: **Blocking Questions** OR **Implementation Plan** OR **No plan needed** (no mixing, no extras).
16
16
 
17
17
  ---
18
18
 
@@ -140,3 +140,11 @@ Output a Markdown document (no code fences), using exactly these sections and or
140
140
  - Expected end state.
141
141
  - Functional criteria (what works and how).
142
142
  - Important non-functional criteria if relevant (error handling, performance, UX).
143
+
144
+ ### 3) No plan needed
145
+
146
+ Use this only when the task is trivial enough that a competent coding agent can implement it directly without meaningful planning value.
147
+
148
+ Output exactly:
149
+
150
+ `No plan needed: <one-sentence reason>`
@@ -38,7 +38,9 @@ Before reviewing, understand the project's standards:
38
38
 
39
39
  - Read AGENTS.md (both global and project-level) for conventions
40
40
  - Look at the overall project structure to understand patterns
41
+ - Trace the relevant entry point, call chain, and affected callers so you understand whether the structure fits the surrounding code
41
42
  - Identify up to 2-3 representative, clean files in the same area/module as the code under review and use them as baseline. Compare against these, not against an abstract ideal.
43
+ - When useful, validate with available evidence such as call-site search, import usage, typecheck output, git history/blame, or existing nearby code
42
44
 
43
45
  This is critical: quality is relative to THIS project's standards, not to some platonic ideal of clean code.
44
46
 
@@ -118,8 +120,15 @@ Apply the **6-month test**: Will this actually cause a problem when someone (hum
118
120
  - Don't recommend abstractions for code that isn't duplicated yet. "Extract this to a util" is only valid if there are already 2+ copies or a very obvious reuse case.
119
121
  - Don't flag complexity in code that is inherently complex. Some business logic IS complicated. The question is whether the code makes it more complicated than it needs to be.
120
122
  - Ask yourself: "Am I suggesting this because it genuinely helps maintainability, or because I'd write it differently?" If the latter, skip it.
123
+ - Before reporting any finding, validate these points:
124
+ 1. Which maintainability invariant or project convention is being violated?
125
+ 2. Which concrete future change, extension, or debugging task becomes harder because of it?
126
+ 3. Which code path, dependency relationship, or file boundary demonstrates the problem?
127
+ 4. What evidence supports it (similar code, caller/import usage, typecheck, history, or direct inspection)?
121
128
 
122
- **Confidence Gate**: For every finding, internally rate your confidence (high/medium/low). Only report findings where your confidence is **high**. If medium, investigate further using available tools. If still medium after investigation, include it only as a **Low** severity regardless of structural impact.
129
+ If you cannot answer those questions with concrete evidence, do not report the finding.
130
+
131
+ **Confidence Gate**: For every finding, internally rate your confidence (high/medium/low). Only report findings where your confidence is **high**. If confidence is medium or low, investigate further using available tools. If it still is not high confidence after investigation, do not report it.
123
132
 
124
133
  ---
125
134
 
@@ -128,10 +137,11 @@ Apply the **6-month test**: Will this actually cause a problem when someone (hum
128
137
  For each finding:
129
138
 
130
139
  **[SEVERITY] Category: Brief title**
131
- File: `path/to/file.ts:123` (or functionName/section if line is not identifiable)
140
+ File: `path/to/file.ts:123` (functionName or section, line range if identifiable)
132
141
  Issue: What the structural problem is
133
- Context: Where this structural problem lives in the code
134
- Impact: Concretely, how this hurts maintainability
142
+ Invariant: Which maintainability rule, convention, or boundary is violated
143
+ Impact: Which concrete future change, extension, or debugging task becomes harder
144
+ Evidence: What you validated (call path, import/caller usage, similar code, typecheck, history, or file context)
135
145
  Suggestion: Specific refactoring approach (not vague "clean this up")
136
146
 
137
147
  ## Severity Levels
@@ -142,23 +152,20 @@ Suggestion: Specific refactoring approach (not vague "clean this up")
142
152
 
143
153
  ---
144
154
 
145
- ## Output Format
155
+ ## Output Summary
146
156
 
147
- At the end of your review, include a summary in this format:
157
+ At the end of your review, include a summary:
148
158
 
149
159
  **Quality Review Summary**
150
160
  Files reviewed: [count]
151
161
  Findings: [count by severity]
152
- Overall confidence: [high/medium]
153
- Highest-risk area: [which file/module needs attention most and why]
154
162
  Overall health: [one sentence assessment]
163
+ Highest-risk area: [which file/module needs attention most and why]
155
164
 
156
- If overall confidence is medium, state what additional context would increase it.
157
-
158
- If no issues found, output exactly:
165
+ If no issues found:
159
166
 
160
167
  **No issues found.**
161
- Reviewed: [list of files reviewed]
162
- Overall confidence: [high/medium]
168
+ Reviewed: [list of files]
169
+ Overall health: [brief assessment]
163
170
 
164
171
  Do not pad this with compliments or hedging language.
package/agents/scout.md CHANGED
@@ -6,53 +6,60 @@ thinking: minimal
6
6
  tools: read, grep, find, ls, bash
7
7
  ---
8
8
 
9
- You are a scout. Quickly investigate a codebase and return structured findings that another agent can use without re-reading everything. Your output will be passed to an agent who has NOT seen the files you explored. Deliver your output in the same language as the user's request.
9
+ You are a scout. Quickly investigate a codebase and return structured findings that another agent can use without repeating your exploration. Deliver your output in the same language as the user's request.
10
10
 
11
11
  Do NOT modify any files. Bash is for read-only commands only. Do not run builds, tests, or any command that mutates state.
12
12
 
13
- ---
13
+ ## Goal
14
+
15
+ Find only the context needed for the assigned question or area. Stop as soon as you can hand off clear, actionable findings.
16
+
17
+ Do not implement.
18
+ Do not propose a plan unless explicitly asked.
19
+ Do not dump large code snippets.
14
20
 
15
21
  ## Gathering Context
16
22
 
17
23
  Before diving into the task:
18
24
 
19
- - Check for project conventions files (CONVENTIONS.md, .editorconfig, etc.)
20
- - Look at the overall project structure to understand patterns
21
- - Note the language, framework, and key dependencies
22
-
23
- ---
25
+ - Check project convention files (`AGENTS.md`, `CONVENTIONS.md`, `.editorconfig`, etc.) if relevant
26
+ - Identify the language, framework, and main structure only if it helps the assigned investigation
27
+ - Prefer narrow search first; widen only if needed
24
28
 
25
29
  ## Strategy
26
30
 
27
- 1. Search the codebase to locate relevant code
28
- 2. Read the files you need to understand the problem
29
- 3. Identify types, interfaces, key functions
30
- 4. Note dependencies between files
31
- 5. Stop as soon as you have enough context for the requesting agent to act
32
-
33
- ---
31
+ 1. Locate the relevant files, symbols, and ownership area
32
+ 2. Read only the files and sections needed to answer the assigned question
33
+ 3. Trace only the necessary relationships: callers, callees, imports, types, config, or data flow
34
+ 4. Extract concrete findings another agent can act on
35
+ 5. Stop once the task is answerable
34
36
 
35
37
  ## Output Format
36
38
 
37
- ## Files Retrieved
39
+ ## Scope Investigated
40
+
41
+ - What you investigated
42
+ - What you did not investigate
38
43
 
39
- List with exact line ranges:
44
+ ## Findings
40
45
 
41
- 1. `path/to/file` (lines 10-50) - Description of what's here
42
- 2. `path/to/other` (lines 100-150) - Description
46
+ For each finding, use this format:
43
47
 
44
- ## Key Code
48
+ - `path/to/file.ts#L10-L40` or ``symbolName` in `path/to/file.ts``
49
+ - Finding: what exists here
50
+ - Relevance: why this matters for the assigned task
45
51
 
46
- Critical types, interfaces, or functions (actual code from the files):
52
+ ## Relationships
47
53
 
48
- ```
49
- // paste relevant code here
50
- ```
54
+ - Key file-to-file, type, or call relationships that matter
55
+ - Keep this concrete and brief
51
56
 
52
- ## Architecture
57
+ ## Open Questions / Gaps
53
58
 
54
- Brief explanation of how the pieces connect.
59
+ - Missing context, ambiguity, or areas not fully verified
60
+ - Only include if they materially affect planning or implementation
55
61
 
56
62
  ## Start Here
57
63
 
58
- Which file to look at first and why.
64
+ - First file or symbol to inspect next
65
+ - Second file or symbol if needed
@@ -25,10 +25,5 @@ interface AgentDiscoveryResult {
25
25
  agents: AgentConfig[];
26
26
  warnings: AgentDiscoveryWarning[];
27
27
  }
28
- interface ParseResult {
29
- agent: AgentConfig | null;
30
- warnings: AgentDiscoveryWarning[];
31
- }
32
- export declare function parseAgentDefinition(content: string, filePath: string): ParseResult;
33
28
  export declare function discoverAgents(cwd?: string): AgentDiscoveryResult;
34
29
  export {};
@@ -202,7 +202,7 @@ function parseSharedFields(record, options) {
202
202
  ],
203
203
  };
204
204
  }
205
- export function parseAgentDefinition(content, filePath) {
205
+ function parseAgentDefinition(content, filePath) {
206
206
  const warnings = [];
207
207
  let frontmatter;
208
208
  let body;
@@ -1,11 +1,20 @@
1
- import { type CreateAgentSessionResult, type ExtensionContext } from "@mariozechner/pi-coding-agent";
1
+ import { type AgentSession, type ModelRegistry } from "@mariozechner/pi-coding-agent";
2
+ import type { Api, Model } from "@mariozechner/pi-ai";
2
3
  import type { AgentConfig } from "./agent-discovery.js";
4
+ export interface BootstrapContext {
5
+ model: Model<Api> | undefined;
6
+ modelRegistry: ModelRegistry;
7
+ parentSessionFile?: string;
8
+ }
3
9
  interface BootstrapOptions {
4
10
  agentConfig: AgentConfig;
5
11
  cwd: string;
6
- ctx: ExtensionContext;
12
+ ctx: BootstrapContext;
7
13
  extensionResolvedPath: string;
8
- parentSessionFile?: string;
9
14
  }
10
- export declare function bootstrapSession(opts: BootstrapOptions): Promise<CreateAgentSessionResult>;
15
+ export interface BootstrapResult {
16
+ session: AgentSession;
17
+ warnings: string[];
18
+ }
19
+ export declare function bootstrapSession(opts: BootstrapOptions): Promise<BootstrapResult>;
11
20
  export {};
@@ -4,29 +4,35 @@ function resolveTools(agentConfig, cwd) {
4
4
  return createSupportedTools(agentConfig.tools ?? SUPPORTED_TOOL_NAMES, cwd);
5
5
  }
6
6
  function resolveModel(agentConfig, ctx) {
7
+ const warnings = [];
7
8
  const model = ctx.model;
8
9
  if (!agentConfig.parsedModel)
9
- return model;
10
+ return { model, warnings };
10
11
  const found = ctx.modelRegistry.find(agentConfig.parsedModel.provider, agentConfig.parsedModel.modelId);
11
12
  if (found)
12
- return found;
13
- console.warn(`[pi-crew] Subagent "${agentConfig.name}": model "${agentConfig.model}" not found in registry, using default`);
14
- return model;
13
+ return { model: found, warnings };
14
+ warnings.push(`Model "${agentConfig.model}" not found, using current session model`);
15
+ return { model, warnings };
15
16
  }
16
- function warnUnknownSkills(agentConfig, resourceLoader) {
17
+ function getSkillWarnings(agentConfig, resourceLoader) {
18
+ const warnings = [];
17
19
  if (!agentConfig.skills)
18
- return;
20
+ return warnings;
19
21
  const availableSkillNames = new Set(resourceLoader.getSkills().skills.map((skill) => skill.name));
20
- const unknownSkills = agentConfig.skills.filter((skillName) => !availableSkillNames.has(skillName));
21
- if (unknownSkills.length === 0)
22
- return;
23
- console.warn(`[pi-crew] Subagent "${agentConfig.name}": unknown skills ${unknownSkills.map((skillName) => `"${skillName}"`).join(", ")}, ignoring`);
22
+ for (const skillName of agentConfig.skills) {
23
+ if (!availableSkillNames.has(skillName)) {
24
+ warnings.push(`Unknown skill "${skillName}" in subagent config, skipping`);
25
+ }
26
+ }
27
+ return warnings;
24
28
  }
25
29
  export async function bootstrapSession(opts) {
26
- const { agentConfig, cwd, ctx, extensionResolvedPath, parentSessionFile } = opts;
30
+ const warnings = [];
31
+ const { agentConfig, cwd, ctx, extensionResolvedPath } = opts;
27
32
  const authStorage = ctx.modelRegistry.authStorage;
28
33
  const modelRegistry = ctx.modelRegistry;
29
- const model = resolveModel(agentConfig, ctx);
34
+ const { model, warnings: modelWarnings } = resolveModel(agentConfig, ctx);
35
+ warnings.push(...modelWarnings);
30
36
  const tools = resolveTools(agentConfig, cwd);
31
37
  const resourceLoader = new DefaultResourceLoader({
32
38
  cwd,
@@ -40,16 +46,18 @@ export async function bootstrapSession(opts) {
40
46
  diagnostics: base.diagnostics,
41
47
  })
42
48
  : undefined,
43
- appendSystemPromptOverride: (base) => agentConfig.systemPrompt.trim() ? [...base, agentConfig.systemPrompt] : base,
49
+ appendSystemPromptOverride: (base) => agentConfig.systemPrompt.trim()
50
+ ? [...base, agentConfig.systemPrompt]
51
+ : base,
44
52
  });
45
53
  await resourceLoader.reload();
46
- warnUnknownSkills(agentConfig, resourceLoader);
54
+ warnings.push(...getSkillWarnings(agentConfig, resourceLoader));
47
55
  const settingsManager = SettingsManager.inMemory({
48
56
  compaction: { enabled: agentConfig.compaction ?? true },
49
57
  });
50
58
  const sessionManager = SessionManager.create(cwd);
51
- sessionManager.newSession({ parentSession: parentSessionFile });
52
- return createAgentSession({
59
+ sessionManager.newSession({ parentSession: ctx.parentSessionFile });
60
+ const result = await createAgentSession({
53
61
  cwd,
54
62
  model,
55
63
  thinkingLevel: agentConfig.thinking,
@@ -60,4 +68,5 @@ export async function bootstrapSession(opts) {
60
68
  authStorage,
61
69
  modelRegistry,
62
70
  });
71
+ return { session: result.session, warnings };
63
72
  }
package/dist/index.js CHANGED
@@ -1,18 +1,33 @@
1
1
  import { dirname } from "node:path";
2
2
  import { fileURLToPath } from "node:url";
3
3
  import { discoverAgents } from "./agent-discovery.js";
4
- import { CrewManager } from "./crew-manager.js";
4
+ import { crewRuntime, } from "./runtime/crew-runtime.js";
5
5
  import { registerCrewIntegration } from "./integration.js";
6
6
  import { formatAgentsForPrompt } from "./prompt-injection.js";
7
7
  import { updateWidget } from "./status-widget.js";
8
8
  const extensionDir = dirname(fileURLToPath(import.meta.url));
9
+ // Process-level cleanup for subagents on exit
10
+ let processHooksSetup = false;
11
+ function setupProcessHooks() {
12
+ if (processHooksSetup)
13
+ return;
14
+ processHooksSetup = true;
15
+ const abortAndExit = (signal) => {
16
+ crewRuntime.abortAll();
17
+ // Re-raise to restore default Node termination behavior
18
+ process.exit(128 + (signal === 'SIGINT' ? 2 : 15));
19
+ };
20
+ process.once('SIGINT', () => abortAndExit('SIGINT'));
21
+ process.once('SIGTERM', () => abortAndExit('SIGTERM'));
22
+ process.on('beforeExit', () => crewRuntime.abortAll());
23
+ }
9
24
  export default function (pi) {
10
- const crewManager = new CrewManager(extensionDir);
11
25
  let currentCtx;
12
26
  let cachedPromptSuffix = "";
27
+ setupProcessHooks();
13
28
  const refreshWidget = () => {
14
29
  if (currentCtx)
15
- updateWidget(currentCtx, crewManager);
30
+ updateWidget(currentCtx, crewRuntime);
16
31
  };
17
32
  const rebuildPromptCache = (cwd) => {
18
33
  const { agents } = discoverAgents(cwd);
@@ -20,16 +35,31 @@ export default function (pi) {
20
35
  };
21
36
  const activateSession = (ctx) => {
22
37
  currentCtx = ctx;
23
- crewManager.activateSession(ctx.sessionManager.getSessionId(), () => ctx.isIdle(), pi);
38
+ crewRuntime.activateSession({
39
+ sessionId: ctx.sessionManager.getSessionId(),
40
+ isIdle: () => ctx.isIdle(),
41
+ sendMessage: pi.sendMessage.bind(pi),
42
+ }, refreshWidget);
24
43
  refreshWidget();
25
44
  };
26
- crewManager.onWidgetUpdate = refreshWidget;
27
45
  pi.on("session_start", (_event, ctx) => {
28
46
  rebuildPromptCache(ctx.cwd);
29
47
  activateSession(ctx);
30
48
  });
49
+ pi.on("session_before_switch", () => {
50
+ // Session is about to switch - no action needed here.
51
+ // Subagent cleanup is handled by process hooks, not session_shutdown.
52
+ });
53
+ pi.on("session_before_fork", () => {
54
+ // Session is about to fork - no action needed here.
55
+ // Subagent cleanup is handled by process hooks, not session_shutdown.
56
+ });
31
57
  pi.on("session_shutdown", (_event, ctx) => {
32
- crewManager.abortForOwner(ctx.sessionManager.getSessionId(), pi);
58
+ const sessionId = ctx.sessionManager.getSessionId();
59
+ // Deactivate delivery to this session, but don't abort subagents.
60
+ // Subagents continue running and will complete normally.
61
+ // Real cleanup happens in process exit hooks.
62
+ crewRuntime.deactivateSession(sessionId);
33
63
  });
34
64
  pi.on("before_agent_start", (event) => {
35
65
  if (!cachedPromptSuffix)
@@ -43,5 +73,5 @@ export default function (pi) {
43
73
  const after = event.systemPrompt.slice(idx);
44
74
  return { systemPrompt: before + cachedPromptSuffix + after };
45
75
  });
46
- registerCrewIntegration(pi, crewManager);
76
+ registerCrewIntegration(pi, crewRuntime, extensionDir);
47
77
  }
@@ -1,3 +1,3 @@
1
1
  import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
2
- import type { CrewManager } from "../crew-manager.js";
3
- export declare function registerCrewCommand(pi: ExtensionAPI, crewManager: CrewManager): void;
2
+ import type { CrewRuntime } from "../runtime/crew-runtime.js";
3
+ export declare function registerCrewCommand(pi: ExtensionAPI, crew: CrewRuntime): void;
@@ -1,8 +1,8 @@
1
- export function registerCrewCommand(pi, crewManager) {
1
+ export function registerCrewCommand(pi, crew) {
2
2
  pi.registerCommand("pi-crew-abort", {
3
3
  description: "Abort an active subagent",
4
4
  getArgumentCompletions(argumentPrefix) {
5
- const activeAgents = crewManager.getAbortableAgents();
5
+ const activeAgents = crew.getAbortableAgents();
6
6
  if (activeAgents.length === 0)
7
7
  return null;
8
8
  return activeAgents
@@ -15,7 +15,7 @@ export function registerCrewCommand(pi, crewManager) {
15
15
  async handler(args, ctx) {
16
16
  const trimmed = args.trim();
17
17
  if (trimmed) {
18
- const success = crewManager.abort(trimmed, pi, { reason: "Aborted by user command" });
18
+ const success = crew.abort(trimmed, { reason: "Aborted by user command" });
19
19
  if (!success) {
20
20
  ctx.ui.notify(`No active subagent with id "${trimmed}"`, "error");
21
21
  }
@@ -24,7 +24,7 @@ export function registerCrewCommand(pi, crewManager) {
24
24
  }
25
25
  return;
26
26
  }
27
- const activeAgents = crewManager.getAbortableAgents();
27
+ const activeAgents = crew.getAbortableAgents();
28
28
  if (activeAgents.length === 0) {
29
29
  ctx.ui.notify("No active subagents", "info");
30
30
  return;
@@ -39,7 +39,7 @@ export function registerCrewCommand(pi, crewManager) {
39
39
  const selectedOption = options.find((option) => option.label === selected);
40
40
  if (!selectedOption)
41
41
  return;
42
- const success = crewManager.abort(selectedOption.id, pi, { reason: "Aborted by user command" });
42
+ const success = crew.abort(selectedOption.id, { reason: "Aborted by user command" });
43
43
  if (success) {
44
44
  ctx.ui.notify(`Subagent ${selectedOption.id} aborted`, "info");
45
45
  }
@@ -26,6 +26,9 @@ export function registerCrewMessageRenderers(pi) {
26
26
  const body = details?.body ?? (!details && message.content ? String(message.content) : undefined);
27
27
  const box = new Box(1, 1, (text) => theme.bg("customMessageBg", text));
28
28
  box.addChild(new Text(header, 0, 0));
29
+ if (details?.sessionFile) {
30
+ box.addChild(new Text(theme.fg("muted", `📁 ${details.sessionFile}`), 0, 0));
31
+ }
29
32
  if (body) {
30
33
  if (expanded) {
31
34
  box.addChild(new Text("", 0, 0));
@@ -1,3 +1,3 @@
1
1
  import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
2
- import type { CrewManager } from "../crew-manager.js";
3
- export declare function registerCrewTools(pi: ExtensionAPI, crewManager: CrewManager): void;
2
+ import type { CrewRuntime } from "../runtime/crew-runtime.js";
3
+ export declare function registerCrewTools(pi: ExtensionAPI, crew: CrewRuntime, extensionDir: string): void;
@@ -3,7 +3,7 @@ import { registerCrewDoneTool } from "./tools/crew-done.js";
3
3
  import { registerCrewListTool } from "./tools/crew-list.js";
4
4
  import { registerCrewRespondTool } from "./tools/crew-respond.js";
5
5
  import { registerCrewSpawnTool } from "./tools/crew-spawn.js";
6
- export function registerCrewTools(pi, crewManager) {
6
+ export function registerCrewTools(pi, crew, extensionDir) {
7
7
  const shownDiscoveryWarnings = new Set();
8
8
  const notifyDiscoveryWarnings = (ctx, warnings) => {
9
9
  if (!ctx.hasUI)
@@ -16,7 +16,7 @@ export function registerCrewTools(pi, crewManager) {
16
16
  ctx.ui.notify(`${warning.message} (${warning.filePath})`, "error");
17
17
  }
18
18
  };
19
- const deps = { pi, crewManager, notifyDiscoveryWarnings };
19
+ const deps = { pi, crew, extensionDir, notifyDiscoveryWarnings };
20
20
  registerCrewListTool(deps);
21
21
  registerCrewSpawnTool(deps);
22
22
  registerCrewAbortTool(deps);
@@ -1,5 +1,5 @@
1
1
  import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
2
- import { Text } from "@mariozechner/pi-tui";
2
+ import { Box, Text } from "@mariozechner/pi-tui";
3
3
  export type ToolTheme = Parameters<Exclude<Parameters<ExtensionAPI["registerTool"]>[0]["renderCall"], undefined>>[1];
4
4
  export type ToolResult = {
5
5
  content: {
@@ -25,6 +25,5 @@ export declare function toolSuccess(text: string, details?: Record<string, unkno
25
25
  }[];
26
26
  details: Record<string, unknown>;
27
27
  };
28
- export declare function truncatePreview(text: string, max: number): string;
29
- export declare function renderCrewCall(theme: ToolTheme, name: string, id: string, preview?: string): Text;
28
+ export declare function renderCrewCall(theme: ToolTheme, name: string, id: string, preview?: string): Box;
30
29
  export declare function renderCrewResult(result: ToolResult, theme: ToolTheme): Text;
@@ -1,4 +1,4 @@
1
- import { Text } from "@mariozechner/pi-tui";
1
+ import { Box, Text } from "@mariozechner/pi-tui";
2
2
  export function toolError(text) {
3
3
  return {
4
4
  content: [{ type: "text", text }],
@@ -12,14 +12,13 @@ export function toolSuccess(text, details = {}) {
12
12
  details,
13
13
  };
14
14
  }
15
- export function truncatePreview(text, max) {
16
- return text.length > max ? `${text.slice(0, max)}...` : text;
17
- }
18
15
  export function renderCrewCall(theme, name, id, preview) {
19
- let text = theme.fg("toolTitle", theme.bold(`${name} `)) + theme.fg("accent", id);
20
- if (preview)
21
- text += theme.fg("dim", ` "${preview}"`);
22
- return new Text(text, 0, 0);
16
+ const box = new Box(1, 1);
17
+ box.addChild(new Text(theme.fg("toolTitle", theme.bold(`${name} `)) + theme.fg("accent", id), 0, 0));
18
+ if (preview) {
19
+ box.addChild(new Text(theme.fg("dim", preview), 0, 0));
20
+ }
21
+ return box;
23
22
  }
24
23
  export function renderCrewResult(result, theme) {
25
24
  const text = result.content[0];
@@ -1,2 +1,2 @@
1
1
  import type { CrewToolDeps } from "./tool-deps.js";
2
- export declare function registerCrewAbortTool({ pi, crewManager }: CrewToolDeps): void;
2
+ export declare function registerCrewAbortTool({ pi, crew }: CrewToolDeps): void;
@@ -13,7 +13,7 @@ function formatAbortToolMessage(result) {
13
13
  }
14
14
  return parts.join("\n");
15
15
  }
16
- export function registerCrewAbortTool({ pi, crewManager }) {
16
+ export function registerCrewAbortTool({ pi, crew }) {
17
17
  pi.registerTool({
18
18
  name: "crew_abort",
19
19
  label: "Abort Crew",
@@ -38,7 +38,7 @@ export function registerCrewAbortTool({ pi, crewManager }) {
38
38
  return toolError("Provide exactly one of: subagent_id, subagent_ids, or all=true.");
39
39
  }
40
40
  if (params.all) {
41
- const abortedIds = crewManager.abortAllOwned(callerSessionId, pi, {
41
+ const abortedIds = crew.abortAllOwned(callerSessionId, {
42
42
  reason: "Aborted by tool request",
43
43
  });
44
44
  if (abortedIds.length === 0) {
@@ -49,7 +49,7 @@ export function registerCrewAbortTool({ pi, crewManager }) {
49
49
  const ids = params.subagent_id
50
50
  ? [params.subagent_id]
51
51
  : (params.subagent_ids ?? []);
52
- const result = crewManager.abortOwned(ids, callerSessionId, pi, {
52
+ const result = crew.abortOwned(ids, callerSessionId, {
53
53
  reason: "Aborted by tool request",
54
54
  });
55
55
  const message = formatAbortToolMessage(result);
@@ -1,2 +1,2 @@
1
1
  import type { CrewToolDeps } from "./tool-deps.js";
2
- export declare function registerCrewDoneTool({ pi, crewManager }: CrewToolDeps): void;
2
+ export declare function registerCrewDoneTool({ pi, crew }: CrewToolDeps): void;
@@ -1,6 +1,6 @@
1
1
  import { Type } from "@sinclair/typebox";
2
2
  import { renderCrewCall, renderCrewResult, toolError, toolSuccess, } from "../tool-presentation.js";
3
- export function registerCrewDoneTool({ pi, crewManager }) {
3
+ export function registerCrewDoneTool({ pi, crew }) {
4
4
  pi.registerTool({
5
5
  name: "crew_done",
6
6
  label: "Done with Crew",
@@ -11,7 +11,7 @@ export function registerCrewDoneTool({ pi, crewManager }) {
11
11
  promptSnippet: "Close an interactive subagent session when done.",
12
12
  async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
13
13
  const callerSessionId = ctx.sessionManager.getSessionId();
14
- const { error } = crewManager.done(params.subagent_id, callerSessionId);
14
+ const { error } = crew.done(params.subagent_id, callerSessionId);
15
15
  if (error)
16
16
  return toolError(error);
17
17
  return toolSuccess(`Subagent ${params.subagent_id} closed.`, {
@@ -1,2 +1,2 @@
1
1
  import type { CrewToolDeps } from "./tool-deps.js";
2
- export declare function registerCrewListTool({ pi, crewManager, notifyDiscoveryWarnings, }: CrewToolDeps): void;
2
+ export declare function registerCrewListTool({ pi, crew, notifyDiscoveryWarnings, }: CrewToolDeps): void;