@melihmucuk/pi-crew 1.0.15 → 1.0.17

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 (39) hide show
  1. package/README.md +8 -8
  2. package/agents/code-reviewer.md +32 -102
  3. package/agents/oracle.md +23 -29
  4. package/agents/planner.md +35 -116
  5. package/agents/quality-reviewer.md +39 -124
  6. package/agents/scout.md +21 -38
  7. package/agents/worker.md +27 -72
  8. package/extension/agent-catalog.ts +369 -0
  9. package/extension/agent-config-fields.ts +359 -0
  10. package/extension/agent-discovery.ts +49 -717
  11. package/extension/bootstrap-session.ts +2 -2
  12. package/extension/index.ts +5 -3
  13. package/extension/integration/crew-tool-actions.ts +306 -0
  14. package/extension/integration/crew-tool-executor.ts +109 -0
  15. package/extension/integration/register-renderers.ts +2 -2
  16. package/extension/integration/register-tools.ts +11 -3
  17. package/extension/integration/tool-presentation.ts +3 -23
  18. package/extension/integration/tools/crew-abort.ts +14 -84
  19. package/extension/integration/tools/crew-done.ts +7 -26
  20. package/extension/integration/tools/crew-list.ts +5 -61
  21. package/extension/integration/tools/crew-respond.ts +8 -29
  22. package/extension/integration/tools/crew-spawn.ts +16 -57
  23. package/extension/message-delivery-policy.ts +22 -0
  24. package/extension/runtime/crew-runtime.ts +60 -223
  25. package/extension/runtime/overflow-recovery.ts +1 -1
  26. package/extension/runtime/{delivery-coordinator.ts → owner-session-coordinator.ts} +44 -37
  27. package/extension/runtime/subagent-lifecycle.ts +203 -0
  28. package/extension/runtime/subagent-registry.ts +50 -6
  29. package/extension/runtime/subagent-transitions.ts +100 -0
  30. package/extension/status-widget.ts +2 -2
  31. package/extension/subagent-messages.ts +9 -17
  32. package/package.json +13 -11
  33. package/prompts/pi-crew-plan.md +34 -137
  34. package/prompts/pi-crew-review.md +36 -112
  35. package/skills/pi-crew/REFERENCE.md +82 -0
  36. package/skills/pi-crew/SKILL.md +33 -104
  37. package/extension/integration/tools/tool-deps.ts +0 -16
  38. package/extension/integration.ts +0 -13
  39. package/extension/runtime/subagent-state.ts +0 -59
@@ -1,8 +1,8 @@
1
+ import type { SendMessageFn } from "../message-delivery-policy.js";
1
2
  import {
2
3
  type SteeringPayload,
3
4
  sendRemainingNote,
4
5
  sendSteeringMessage,
5
- type SendMessageFn,
6
6
  } from "../subagent-messages.js";
7
7
 
8
8
  export interface ActiveRuntimeBinding {
@@ -17,25 +17,43 @@ interface PendingMessage {
17
17
  queuedAt: number;
18
18
  }
19
19
 
20
- export class DeliveryCoordinator {
20
+ interface OwnerSessionCoordinatorDeps {
21
+ countRunningForOwner: (ownerSessionId: string, excludeId: string) => number;
22
+ onRefreshOwnerSession: (ownerSessionId: string) => void;
23
+ now?: () => number;
24
+ scheduleFlush?: (callback: () => void) => void;
25
+ }
26
+
27
+ const PENDING_MESSAGE_TTL_MS = 86_400_000;
28
+
29
+ export class OwnerSessionCoordinator {
21
30
  private binding: ActiveRuntimeBinding | undefined;
22
31
  private pendingMessages: PendingMessage[] = [];
23
32
  private flushScheduled = false;
33
+ private readonly countRunningForOwner: (ownerSessionId: string, excludeId: string) => number;
34
+ private readonly onRefreshOwnerSession: (ownerSessionId: string) => void;
35
+ private readonly now: () => number;
36
+ private readonly scheduleFlush: (callback: () => void) => void;
37
+
38
+ constructor(deps: OwnerSessionCoordinatorDeps) {
39
+ this.countRunningForOwner = deps.countRunningForOwner;
40
+ this.onRefreshOwnerSession = deps.onRefreshOwnerSession;
41
+ this.now = deps.now ?? Date.now;
42
+ this.scheduleFlush = deps.scheduleFlush ?? ((callback) => setTimeout(callback, 0));
43
+ }
24
44
 
25
- activateSession(
26
- binding: ActiveRuntimeBinding,
27
- countRunningForOwner: (ownerSessionId: string, excludeId: string) => number,
28
- ): void {
45
+ activateSession(binding: ActiveRuntimeBinding): void {
29
46
  this.binding = binding;
47
+
30
48
  // Delay flush to next macrotask. session_start fires before pi-core
31
49
  // calls _reconnectToAgent(), so synchronous delivery would emit agent
32
50
  // events while the session listener is disconnected, losing JSONL persistence.
33
51
  if (this.pendingMessages.some((entry) => entry.ownerSessionId === binding.sessionId)) {
34
52
  this.flushScheduled = true;
35
- setTimeout(() => {
53
+ this.scheduleFlush(() => {
36
54
  this.flushScheduled = false;
37
- this.flushPending(countRunningForOwner);
38
- }, 0);
55
+ this.flushPending();
56
+ });
39
57
  }
40
58
  }
41
59
 
@@ -45,38 +63,34 @@ export class DeliveryCoordinator {
45
63
  }
46
64
  }
47
65
 
48
- deliver(
49
- ownerSessionId: string,
50
- payload: SteeringPayload,
51
- countRunningForOwner: (ownerSessionId: string, excludeId: string) => number,
52
- ): void {
66
+ refresh(ownerSessionId: string): void {
67
+ this.onRefreshOwnerSession(ownerSessionId);
68
+ }
69
+
70
+ deliver(ownerSessionId: string, payload: SteeringPayload): void {
53
71
  if (!this.binding || ownerSessionId !== this.binding.sessionId || this.flushScheduled) {
54
- this.pendingMessages.push({ ownerSessionId, payload, queuedAt: Date.now() });
72
+ this.queue(ownerSessionId, payload);
55
73
  return;
56
74
  }
57
75
 
58
- this.send(ownerSessionId, payload, countRunningForOwner);
76
+ this.send(ownerSessionId, payload);
77
+ }
78
+
79
+ private queue(ownerSessionId: string, payload: SteeringPayload): void {
80
+ this.pendingMessages.push({ ownerSessionId, payload, queuedAt: this.now() });
59
81
  }
60
82
 
61
- /**
62
- * Remove pending messages older than the TTL.
63
- * Called during activateSession to prevent unbounded memory growth.
64
- */
65
83
  private cleanStaleMessages(): void {
66
- const maxAgeMs = 86_400_000; // 24 hours
67
- const cutoff = Date.now() - maxAgeMs;
84
+ const cutoff = this.now() - PENDING_MESSAGE_TTL_MS;
68
85
  this.pendingMessages = this.pendingMessages.filter(
69
86
  (entry) => entry.queuedAt >= cutoff,
70
87
  );
71
88
  }
72
89
 
73
- private flushPending(
74
- countRunningForOwner: (ownerSessionId: string, excludeId: string) => number,
75
- ): void {
90
+ private flushPending(): void {
76
91
  if (!this.binding) return;
77
92
  const targetSessionId = this.binding.sessionId;
78
93
 
79
- // Clean up stale messages first (older than TTL)
80
94
  this.cleanStaleMessages();
81
95
 
82
96
  const toDeliver: PendingMessage[] = [];
@@ -86,17 +100,14 @@ export class DeliveryCoordinator {
86
100
  if (entry.ownerSessionId === targetSessionId) {
87
101
  toDeliver.push(entry);
88
102
  } else {
89
- // Keep all other messages - they may be for sessions that will be reactivated later
90
103
  remaining.push(entry);
91
104
  }
92
105
  }
93
106
 
94
- // Keep messages for other sessions
95
107
  this.pendingMessages = remaining;
96
108
 
97
- // Deliver messages for the active session
98
109
  for (const entry of toDeliver) {
99
- this.send(entry.ownerSessionId, entry.payload, countRunningForOwner);
110
+ this.send(entry.ownerSessionId, entry.payload);
100
111
  }
101
112
  }
102
113
 
@@ -105,17 +116,13 @@ export class DeliveryCoordinator {
105
116
  * owner is idle, queue the result without triggering, then queue the separate
106
117
  * remaining note with triggerTurn so the next turn sees both in order.
107
118
  */
108
- private send(
109
- ownerSessionId: string,
110
- payload: SteeringPayload,
111
- countRunningForOwner: (ownerSessionId: string, excludeId: string) => number,
112
- ): void {
119
+ private send(ownerSessionId: string, payload: SteeringPayload): void {
113
120
  if (!this.binding || this.binding.sessionId !== ownerSessionId) {
114
- this.pendingMessages.push({ ownerSessionId, payload, queuedAt: Date.now() });
121
+ this.queue(ownerSessionId, payload);
115
122
  return;
116
123
  }
117
124
 
118
- const remaining = countRunningForOwner(ownerSessionId, payload.id);
125
+ const remaining = this.countRunningForOwner(ownerSessionId, payload.id);
119
126
  const isIdle = this.binding.isIdle();
120
127
  const triggerResultTurn = !(isIdle && remaining > 0);
121
128
 
@@ -0,0 +1,203 @@
1
+ import type { AgentMessage } from "@earendil-works/pi-agent-core";
2
+ import type { AssistantMessage } from "@earendil-works/pi-ai";
3
+ import type { AgentSession } from "@earendil-works/pi-coding-agent";
4
+ import type { BootstrapContext } from "../bootstrap-session.js";
5
+ import { bootstrapSession } from "../bootstrap-session.js";
6
+ import type { SubagentStatus } from "../subagent-messages.js";
7
+ import { runPromptWithOverflowRecovery } from "./overflow-recovery.js";
8
+ import type { SubagentState } from "./subagent-registry.js";
9
+ import { isAborted } from "./subagent-transitions.js";
10
+
11
+ interface PromptOutcome {
12
+ status: Extract<SubagentStatus, "done" | "waiting" | "error" | "aborted">;
13
+ result?: string;
14
+ error?: string;
15
+ }
16
+
17
+ interface StartOptions {
18
+ cwd: string;
19
+ ctx: BootstrapContext;
20
+ extensionResolvedPath: string;
21
+ onWarning?: (message: string) => void;
22
+ }
23
+
24
+ interface SubagentLifecycleCallbacks {
25
+ isCurrent: (state: SubagentState) => boolean;
26
+ onProgress: (ownerSessionId: string) => void;
27
+ onSettled: (
28
+ state: SubagentState,
29
+ status: Extract<SubagentStatus, "done" | "waiting" | "error" | "aborted">,
30
+ outcome: { result?: string; error?: string },
31
+ ) => void;
32
+ }
33
+
34
+ function getLastAssistantMessage(
35
+ messages: AgentMessage[],
36
+ ): AssistantMessage | undefined {
37
+ for (let i = messages.length - 1; i >= 0; i--) {
38
+ const msg = messages[i];
39
+ if (msg.role === "assistant") {
40
+ return msg as AssistantMessage;
41
+ }
42
+ }
43
+ return undefined;
44
+ }
45
+
46
+ function getAssistantText(
47
+ message: AssistantMessage | undefined,
48
+ ): string | undefined {
49
+ if (!message) return undefined;
50
+
51
+ const texts: string[] = [];
52
+ for (const part of message.content) {
53
+ if (part.type === "text") {
54
+ texts.push(part.text);
55
+ }
56
+ }
57
+
58
+ return texts.length > 0 ? texts.join("\n") : undefined;
59
+ }
60
+
61
+ function getPromptOutcome(state: SubagentState): PromptOutcome {
62
+ const lastAssistant = getLastAssistantMessage(state.session!.messages);
63
+ const text = getAssistantText(lastAssistant);
64
+
65
+ if (lastAssistant?.stopReason === "error") {
66
+ return {
67
+ status: "error",
68
+ error: lastAssistant.errorMessage ?? text ?? "(no output)",
69
+ };
70
+ }
71
+
72
+ if (lastAssistant?.stopReason === "aborted") {
73
+ return {
74
+ status: "aborted",
75
+ error: lastAssistant.errorMessage ?? text ?? "(no output)",
76
+ };
77
+ }
78
+
79
+ return {
80
+ status: state.agentConfig.interactive ? "waiting" : "done",
81
+ result: text ?? "(no output)",
82
+ };
83
+ }
84
+
85
+ export class SubagentLifecycle {
86
+ constructor(private readonly callbacks: SubagentLifecycleCallbacks) {}
87
+
88
+ start(state: SubagentState, opts: StartOptions): void {
89
+ void this.spawnSession(state, opts);
90
+ }
91
+
92
+ respond(state: SubagentState, message: string): void {
93
+ void this.runPromptCycle(state, message);
94
+ }
95
+
96
+ abortPrompt(state: SubagentState): void {
97
+ state.promptAbortController?.abort();
98
+ state.promptAbortController = undefined;
99
+ state.session?.abortCompaction();
100
+ state.session?.abortRetry();
101
+ state.session?.abort().catch(() => {});
102
+ }
103
+
104
+ private attachSessionListeners(
105
+ state: SubagentState,
106
+ session: AgentSession,
107
+ ): void {
108
+ state.unsubscribe = session.subscribe((event) => {
109
+ if (event.type !== "turn_end") return;
110
+
111
+ state.turns++;
112
+ const msg = event.message;
113
+ if (msg.role === "assistant") {
114
+ const assistantMsg = msg as AssistantMessage;
115
+ state.contextTokens = assistantMsg.usage.totalTokens;
116
+ state.model = assistantMsg.model;
117
+ }
118
+ this.callbacks.onProgress(state.ownerSessionId);
119
+ });
120
+ }
121
+
122
+ private attachSpawnedSession(
123
+ state: SubagentState,
124
+ session: AgentSession,
125
+ ): boolean {
126
+ if (!this.callbacks.isCurrent(state)) {
127
+ session.dispose();
128
+ return false;
129
+ }
130
+
131
+ state.session = session;
132
+ return true;
133
+ }
134
+
135
+ private async runPromptCycle(
136
+ state: SubagentState,
137
+ prompt: string,
138
+ ): Promise<void> {
139
+ if (isAborted(state)) return;
140
+
141
+ const abortController = new AbortController();
142
+ state.promptAbortController = abortController;
143
+
144
+ try {
145
+ const recovery = await runPromptWithOverflowRecovery(
146
+ state.session!,
147
+ prompt,
148
+ abortController.signal,
149
+ );
150
+ if (isAborted(state)) return;
151
+
152
+ const outcome = getPromptOutcome(state);
153
+
154
+ if (recovery === "failed" && outcome.status !== "error") {
155
+ this.callbacks.onSettled(state, "error", {
156
+ error: "Context overflow recovery failed",
157
+ });
158
+ return;
159
+ }
160
+
161
+ this.callbacks.onSettled(state, outcome.status, outcome);
162
+ } catch (err) {
163
+ if (isAborted(state)) return;
164
+
165
+ const error = err instanceof Error ? err.message : String(err);
166
+ this.callbacks.onSettled(state, "error", { error });
167
+ } finally {
168
+ state.promptAbortController = undefined;
169
+ }
170
+ }
171
+
172
+ private async spawnSession(
173
+ state: SubagentState,
174
+ opts: StartOptions,
175
+ ): Promise<void> {
176
+ try {
177
+ if (isAborted(state)) return;
178
+
179
+ const { session, warnings } = await bootstrapSession({
180
+ agentConfig: state.agentConfig,
181
+ cwd: opts.cwd,
182
+ ctx: opts.ctx,
183
+ extensionResolvedPath: opts.extensionResolvedPath,
184
+ });
185
+
186
+ for (const warning of warnings) {
187
+ opts.onWarning?.(warning);
188
+ }
189
+
190
+ if (!this.attachSpawnedSession(state, session)) return;
191
+
192
+ this.attachSessionListeners(state, session);
193
+ await this.runPromptCycle(state, state.task);
194
+ } catch (err) {
195
+ if (isAborted(state)) return;
196
+
197
+ if (state.status === "running") {
198
+ const error = err instanceof Error ? err.message : String(err);
199
+ this.callbacks.onSettled(state, "error", { error });
200
+ }
201
+ }
202
+ }
203
+ }
@@ -1,10 +1,54 @@
1
+ import { randomBytes } from "node:crypto";
2
+ import type { AgentSession } from "@earendil-works/pi-coding-agent";
1
3
  import type { AgentConfig } from "../agent-discovery.js";
2
- import type { ActiveAgentSummary, SubagentState } from "./subagent-state.js";
3
- import {
4
- buildActiveAgentSummary,
5
- generateId,
6
- isAbortableStatus,
7
- } from "./subagent-state.js";
4
+ import type { SubagentStatus } from "../subagent-messages.js";
5
+ import { isAbortableStatus } from "./subagent-transitions.js";
6
+
7
+ export interface SubagentState {
8
+ id: string;
9
+ agentConfig: AgentConfig;
10
+ task: string;
11
+ status: SubagentStatus;
12
+ ownerSessionId: string;
13
+ session: AgentSession | null;
14
+ turns: number;
15
+ contextTokens: number;
16
+ model: string | undefined;
17
+ error?: string;
18
+ result?: string;
19
+ promptAbortController?: AbortController;
20
+ unsubscribe?: () => void;
21
+ }
22
+
23
+ export interface ActiveAgentSummary {
24
+ id: string;
25
+ agentName: string;
26
+ status: SubagentStatus;
27
+ turns: number;
28
+ contextTokens: number;
29
+ model: string | undefined;
30
+ }
31
+
32
+ function generateId(name: string, existingIds: Set<string>): string {
33
+ for (let i = 0; i < 10; i++) {
34
+ const id = `${name}-${randomBytes(4).toString("hex")}`;
35
+ if (!existingIds.has(id)) return id;
36
+ }
37
+ return `${name}-${randomBytes(8).toString("hex")}`;
38
+ }
39
+
40
+ function buildActiveAgentSummary(
41
+ state: SubagentState,
42
+ ): ActiveAgentSummary {
43
+ return {
44
+ id: state.id,
45
+ agentName: state.agentConfig.name,
46
+ status: state.status,
47
+ turns: state.turns,
48
+ contextTokens: state.contextTokens,
49
+ model: state.model,
50
+ };
51
+ }
8
52
 
9
53
  export class SubagentRegistry {
10
54
  private activeAgents = new Map<string, SubagentState>();
@@ -0,0 +1,100 @@
1
+ import type { SubagentStatus } from "../subagent-messages.js";
2
+ import type { SubagentState } from "./subagent-registry.js";
3
+
4
+ export type SettledSubagentStatus = Extract<
5
+ SubagentStatus,
6
+ "done" | "waiting" | "error" | "aborted"
7
+ >;
8
+
9
+ export interface SubagentTransitionOutcome {
10
+ result?: string;
11
+ error?: string;
12
+ }
13
+
14
+ type SubagentTransitionResult =
15
+ | { ok: true; state: SubagentState }
16
+ | { ok: false; error: string };
17
+
18
+ export function isAborted(state: SubagentState): boolean {
19
+ return state.status === "aborted";
20
+ }
21
+
22
+ export function isAbortableStatus(status: SubagentStatus): boolean {
23
+ return status === "running" || status === "waiting";
24
+ }
25
+
26
+ export function canAbortSubagent(
27
+ state: SubagentState | undefined,
28
+ ): state is SubagentState {
29
+ return Boolean(state && isAbortableStatus(state.status));
30
+ }
31
+
32
+ function validateOwnedSubagent(
33
+ state: SubagentState | undefined,
34
+ id: string,
35
+ callerSessionId: string,
36
+ missingMessage: string,
37
+ ): SubagentTransitionResult {
38
+ if (!state) return { ok: false, error: missingMessage };
39
+ if (state.ownerSessionId !== callerSessionId) {
40
+ return { ok: false, error: `Subagent "${id}" belongs to a different session` };
41
+ }
42
+ return { ok: true, state };
43
+ }
44
+
45
+ export function startSubagentResponse(
46
+ state: SubagentState | undefined,
47
+ id: string,
48
+ callerSessionId: string,
49
+ ): SubagentTransitionResult {
50
+ const owned = validateOwnedSubagent(
51
+ state,
52
+ id,
53
+ callerSessionId,
54
+ `No subagent with id "${id}"`,
55
+ );
56
+ if (!owned.ok) return owned;
57
+
58
+ if (owned.state.status !== "waiting") {
59
+ return {
60
+ ok: false,
61
+ error: `Subagent "${id}" is not waiting for a response (status: ${owned.state.status})`,
62
+ };
63
+ }
64
+ if (!owned.state.session) {
65
+ return { ok: false, error: `Subagent "${id}" has no active session` };
66
+ }
67
+
68
+ owned.state.status = "running";
69
+ return owned;
70
+ }
71
+
72
+ export function validateSubagentDone(
73
+ state: SubagentState | undefined,
74
+ id: string,
75
+ callerSessionId: string,
76
+ ): SubagentTransitionResult {
77
+ const owned = validateOwnedSubagent(
78
+ state,
79
+ id,
80
+ callerSessionId,
81
+ `No active subagent with id "${id}"`,
82
+ );
83
+ if (!owned.ok) return owned;
84
+
85
+ if (owned.state.status !== "waiting") {
86
+ return { ok: false, error: `Subagent "${id}" is not in waiting state` };
87
+ }
88
+
89
+ return owned;
90
+ }
91
+
92
+ export function settleSubagent(
93
+ state: SubagentState,
94
+ status: SettledSubagentStatus,
95
+ outcome: SubagentTransitionOutcome,
96
+ ): void {
97
+ state.status = status;
98
+ state.result = outcome.result;
99
+ state.error = outcome.error;
100
+ }
@@ -1,5 +1,5 @@
1
- import type { ExtensionContext } from "@mariozechner/pi-coding-agent";
2
- import { Text } from "@mariozechner/pi-tui";
1
+ import type { ExtensionContext } from "@earendil-works/pi-coding-agent";
2
+ import { Text } from "@earendil-works/pi-tui";
3
3
  import type { ActiveAgentSummary } from "./runtime/crew-runtime.js";
4
4
  import type { CrewRuntime } from "./runtime/crew-runtime.js";
5
5
 
@@ -1,9 +1,8 @@
1
- import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
1
+ import { sendWithDeliveryPolicy, type SendMessageFn } from "./message-delivery-policy.js";
2
2
 
3
+ export type { SendMessageFn } from "./message-delivery-policy.js";
3
4
  export type SubagentStatus = "running" | "waiting" | "done" | "error" | "aborted";
4
5
 
5
- export type SendMessageFn = ExtensionAPI["sendMessage"];
6
-
7
6
  export const STATUS_ICON: Record<SubagentStatus, string> = {
8
7
  running: "⏳",
9
8
  waiting: "⏳",
@@ -79,12 +78,7 @@ export function sendSteeringMessage(
79
78
  } satisfies CrewResultMessageDetails,
80
79
  };
81
80
 
82
- sendMessage(
83
- message,
84
- opts.isIdle
85
- ? { triggerTurn: opts.triggerTurn }
86
- : { deliverAs: "steer", triggerTurn: opts.triggerTurn },
87
- );
81
+ sendWithDeliveryPolicy(message, sendMessage, opts);
88
82
  }
89
83
 
90
84
  export function sendRemainingNote(
@@ -94,15 +88,14 @@ export function sendRemainingNote(
94
88
  ): void {
95
89
  if (remainingCount <= 0) return;
96
90
 
97
- sendMessage(
91
+ sendWithDeliveryPolicy(
98
92
  {
99
93
  customType: "crew-remaining",
100
94
  content: `⏳ ${remainingCount} subagent(s) still running`,
101
95
  display: true,
102
96
  },
103
- opts.isIdle
104
- ? { triggerTurn: opts.triggerTurn }
105
- : { deliverAs: "steer", triggerTurn: opts.triggerTurn },
97
+ sendMessage,
98
+ opts,
106
99
  );
107
100
  }
108
101
 
@@ -110,15 +103,14 @@ export function sendCrewListActiveWarning(
110
103
  sendMessage: SendMessageFn,
111
104
  opts: { isIdle: boolean; triggerTurn: boolean },
112
105
  ): void {
113
- sendMessage(
106
+ sendWithDeliveryPolicy(
114
107
  {
115
108
  customType: "crew-list-warning",
116
109
  content:
117
110
  "⚠ Active subagents detected. Do not poll crew_list for completion — results arrive as steering messages. Continue with unrelated work or end your turn and wait for the steering messages.",
118
111
  display: true,
119
112
  },
120
- opts.isIdle
121
- ? { triggerTurn: opts.triggerTurn }
122
- : { deliverAs: "steer", triggerTurn: opts.triggerTurn },
113
+ sendMessage,
114
+ opts,
123
115
  );
124
116
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@melihmucuk/pi-crew",
3
- "version": "1.0.15",
3
+ "version": "1.0.17",
4
4
  "type": "module",
5
5
  "description": "Non-blocking subagent orchestration for pi coding agent",
6
6
  "files": [
@@ -32,22 +32,24 @@
32
32
  "video": "https://monkeys-team.ams3.cdn.digitaloceanspaces.com/pi-crew-demo.mp4"
33
33
  },
34
34
  "scripts": {
35
- "typecheck": "tsc --noEmit"
35
+ "typecheck": "tsc --noEmit",
36
+ "test": "node --import tsx --test tests/**/*.test.ts"
36
37
  },
37
38
  "peerDependencies": {
38
- "@mariozechner/pi-agent-core": "*",
39
- "@mariozechner/pi-ai": "*",
40
- "@mariozechner/pi-coding-agent": "*",
41
- "@mariozechner/pi-tui": "*",
39
+ "@earendil-works/pi-agent-core": "*",
40
+ "@earendil-works/pi-ai": "*",
41
+ "@earendil-works/pi-coding-agent": "*",
42
+ "@earendil-works/pi-tui": "*",
42
43
  "typebox": "*"
43
44
  },
44
45
  "devDependencies": {
45
- "@mariozechner/pi-agent-core": "^0.73.0",
46
- "@mariozechner/pi-ai": "^0.73.0",
47
- "@mariozechner/pi-coding-agent": "^0.73.0",
48
- "@mariozechner/pi-tui": "^0.73.0",
46
+ "@earendil-works/pi-agent-core": "^0.75.4",
47
+ "@earendil-works/pi-ai": "^0.75.4",
48
+ "@earendil-works/pi-coding-agent": "^0.75.4",
49
+ "@earendil-works/pi-tui": "^0.75.4",
49
50
  "@types/node": "^22.19.17",
50
- "typebox": "^1.1.37",
51
+ "tsx": "^4.22.3",
52
+ "typebox": "^1.1.38",
51
53
  "typescript": "^5.9.3"
52
54
  }
53
55
  }