@bacnh85/pi-subagent 0.13.0 → 0.14.1
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/CHANGELOG.md +28 -0
- package/README.md +19 -0
- package/agent-format.md +2 -1
- package/extensions/agents.ts +4 -4
- package/extensions/index.ts +1 -0
- package/extensions/render.ts +10 -0
- package/extensions/runner.ts +127 -7
- package/extensions/service.ts +1 -0
- package/package.json +9 -9
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,33 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.14.1 (2026-08-07)
|
|
4
|
+
|
|
5
|
+
### Improvements
|
|
6
|
+
|
|
7
|
+
- Widen peer dependency range to support Pi 0.84.0 (`>=0.80.0 <0.85.0`).
|
|
8
|
+
No code changes — verified compatible against the 0.84.0 SDK types.
|
|
9
|
+
|
|
10
|
+
## 0.14.0 (2026-08-05)
|
|
11
|
+
|
|
12
|
+
### Git worktree isolation (`sandbox: worktree`)
|
|
13
|
+
|
|
14
|
+
Agents can now run in an isolated **git worktree** instead of the parent's
|
|
15
|
+
working tree — the safe way to run parallel implementation agents that edit
|
|
16
|
+
files. Set `sandbox: worktree` in agent frontmatter (see `agent-format.md`).
|
|
17
|
+
|
|
18
|
+
- Child file mutations land in `.pi-worktrees/<id>` under the repo root; the
|
|
19
|
+
main checkout stays untouched, so two parallel `worker` agents can never
|
|
20
|
+
clobber each other's edits.
|
|
21
|
+
- On completion, a unified diff of the child's changes is returned as
|
|
22
|
+
`result.patch` and shown in the thread viewer as a `🌿 worktree` badge.
|
|
23
|
+
- **Merging is explicit** — the parent receives the diff and applies it via
|
|
24
|
+
`apply_patch` / cherry-pick / discard; nothing is auto-merged.
|
|
25
|
+
- The worktree is removed in a `finally` on success, error, or abort.
|
|
26
|
+
- Falls back to in-process execution with a warning when the cwd is not a git
|
|
27
|
+
repo (`ponytail`: isolation optimization, not a hard requirement).
|
|
28
|
+
- Wired through the `subagent` tool, the service path (`pi-subagent:run` for
|
|
29
|
+
pi-review), and `runner.ts`'s `runSubAgent` (new `sandbox` + `exec` options).
|
|
30
|
+
|
|
3
31
|
## 0.13.0 (2026-07-31)
|
|
4
32
|
|
|
5
33
|
### Subagents inherit parent extensions & tools by default
|
package/README.md
CHANGED
|
@@ -84,6 +84,25 @@ Child agent tools are validated against a fixed allowlist:
|
|
|
84
84
|
|
|
85
85
|
Unknown or misspelled tool names produce clear diagnostics. Duplicate tool names are deduplicated.
|
|
86
86
|
|
|
87
|
+
### Git worktree isolation (`sandbox: worktree`)
|
|
88
|
+
|
|
89
|
+
Set `sandbox: worktree` in an agent's frontmatter to run it in an isolated git
|
|
90
|
+
worktree (`.pi-worktrees/<id>` under the repo root) instead of the parent's
|
|
91
|
+
working tree. This is the safe way to run **parallel implementation** agents:
|
|
92
|
+
two `worker` agents editing the same files can no longer clobber each other —
|
|
93
|
+
each writes into its own checkout.
|
|
94
|
+
|
|
95
|
+
- All file mutations land in the worktree; the main checkout stays untouched.
|
|
96
|
+
- On completion, a unified diff of the child's changes is returned in the
|
|
97
|
+
result and shown in the thread viewer as a `🌿 worktree` badge.
|
|
98
|
+
- **Merging is explicit**: the parent receives the diff and applies it via
|
|
99
|
+
`apply_patch` / cherry-pick / discard. Nothing is auto-merged.
|
|
100
|
+
- The worktree is removed on completion (success, error, or abort).
|
|
101
|
+
- Requires git; when the cwd is not a git repo, the agent falls back to
|
|
102
|
+
in-process execution with a warning (`ponytail`: isolation optimization,
|
|
103
|
+
not a hard requirement).
|
|
104
|
+
|
|
105
|
+
|
|
87
106
|
### Timeouts
|
|
88
107
|
|
|
89
108
|
Every child execution receives a timeout:
|
package/agent-format.md
CHANGED
|
@@ -24,7 +24,7 @@ models: # Optional ordered fallbacks; comma form also accepted
|
|
|
24
24
|
- provider/fast-model
|
|
25
25
|
- provider/backup-model
|
|
26
26
|
thinking: low # Optional: off|minimal|low|medium|high|xhigh|max.
|
|
27
|
-
sandbox: read-only # Optional: read-only | workspace-write. Auto-derives tool restrictions.
|
|
27
|
+
sandbox: read-only # Optional: read-only | workspace-write | worktree. Auto-derives tool restrictions.
|
|
28
28
|
color: cyan # Optional: red|blue|green|yellow|purple|orange|pink|cyan.
|
|
29
29
|
---
|
|
30
30
|
```
|
|
@@ -33,6 +33,7 @@ color: cyan # Optional: red|blue|green|yellow|purple|orange|pink|c
|
|
|
33
33
|
|
|
34
34
|
- `read-only`: Restricts tools to `read`, `grep`, `find`, `ls`. Overrides any `tools` field.
|
|
35
35
|
- `workspace-write` (default): Uses the agent's `tools` list or defaults to all tools.
|
|
36
|
+
- `worktree`: Runs the agent in an isolated git worktree (`.pi-worktrees/<id>` under the repo root). All file mutations land in the worktree; the main checkout is untouched. On completion, a unified diff of the changes is returned in the result (visible in the thread viewer as a `🌿 worktree` badge) — the parent merges explicitly via `apply_patch`/cherry-pick; nothing is applied automatically. Falls back to in-process execution when the cwd is not a git repo (with a warning). Requires git.
|
|
36
37
|
|
|
37
38
|
### `color`
|
|
38
39
|
|
package/extensions/agents.ts
CHANGED
|
@@ -22,7 +22,7 @@ export interface AgentConfig {
|
|
|
22
22
|
model?: string;
|
|
23
23
|
models?: string[];
|
|
24
24
|
thinking?: "off" | "minimal" | "low" | "medium" | "high" | "xhigh" | "max";
|
|
25
|
-
sandbox?: "read-only" | "workspace-write";
|
|
25
|
+
sandbox?: "read-only" | "workspace-write" | "worktree";
|
|
26
26
|
color?: AgentColor;
|
|
27
27
|
systemPrompt: string;
|
|
28
28
|
source: "user" | "project" | "bundled";
|
|
@@ -203,7 +203,7 @@ function loadAgentsFromDir(
|
|
|
203
203
|
}
|
|
204
204
|
|
|
205
205
|
if (typeof frontmatter.sandbox === "string" && frontmatter.sandbox) {
|
|
206
|
-
const validSandboxes = ["read-only", "workspace-write"];
|
|
206
|
+
const validSandboxes = ["read-only", "workspace-write", "worktree"];
|
|
207
207
|
if (!validSandboxes.includes(frontmatter.sandbox)) {
|
|
208
208
|
diagnostics.push({
|
|
209
209
|
filePath,
|
|
@@ -231,8 +231,8 @@ function loadAgentsFromDir(
|
|
|
231
231
|
thinking: typeof frontmatter.thinking === "string" && ["off", "minimal", "low", "medium", "high", "xhigh", "max"].includes(frontmatter.thinking)
|
|
232
232
|
? frontmatter.thinking as AgentConfig["thinking"]
|
|
233
233
|
: undefined,
|
|
234
|
-
sandbox: typeof frontmatter.sandbox === "string" && ["read-only", "workspace-write"].includes(frontmatter.sandbox)
|
|
235
|
-
? frontmatter.sandbox as "read-only" | "workspace-write"
|
|
234
|
+
sandbox: typeof frontmatter.sandbox === "string" && ["read-only", "workspace-write", "worktree"].includes(frontmatter.sandbox)
|
|
235
|
+
? frontmatter.sandbox as "read-only" | "workspace-write" | "worktree"
|
|
236
236
|
: undefined,
|
|
237
237
|
color: typeof frontmatter.color === "string" && VALID_COLORS.includes(frontmatter.color as any)
|
|
238
238
|
? frontmatter.color as AgentColor
|
package/extensions/index.ts
CHANGED
|
@@ -647,6 +647,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
647
647
|
|
|
648
648
|
const result = await runSubAgent({
|
|
649
649
|
cwd: safeCwd,
|
|
650
|
+
sandbox: agent.sandbox === "worktree" ? "worktree" : undefined,
|
|
650
651
|
systemPrompt: params.instructions
|
|
651
652
|
? `${agent.systemPrompt}\n\n## Task Contract\n${params.instructions.slice(0, MAX_INSTRUCTIONS_LENGTH)}`
|
|
652
653
|
: agent.systemPrompt,
|
package/extensions/render.ts
CHANGED
|
@@ -236,6 +236,15 @@ export function renderSingleResult(
|
|
|
236
236
|
container.addChild(new Spacer(1));
|
|
237
237
|
container.addChild(new Text(theme.fg("dim", usageStr), 0, 0));
|
|
238
238
|
}
|
|
239
|
+
if (result.patch) {
|
|
240
|
+
container.addChild(new Spacer(1));
|
|
241
|
+
container.addChild(new Text(theme.fg("success", "🌿 worktree"), 0, 0));
|
|
242
|
+
const patchLines = result.patch.split("\n").length;
|
|
243
|
+
container.addChild(new Text(theme.fg("dim", `${patchLines} diff lines — merge explicitly via apply_patch/cherry-pick`), 0, 0));
|
|
244
|
+
if (result.patch !== "(no changes)") {
|
|
245
|
+
container.addChild(new Text(theme.fg("muted", result.patch.slice(0, 2000)), 0, 0));
|
|
246
|
+
}
|
|
247
|
+
}
|
|
239
248
|
return container;
|
|
240
249
|
}
|
|
241
250
|
|
|
@@ -258,6 +267,7 @@ export function renderSingleResult(
|
|
|
258
267
|
}
|
|
259
268
|
const usageStr = formatUsageStats(result.usage, result.model);
|
|
260
269
|
if (usageStr) text += `\n${theme.fg("dim", usageStr)}`;
|
|
270
|
+
if (result.patch) text += `\n${theme.fg("success", "🌿 worktree")} (${result.patch.split("\n").length} diff lines)`;
|
|
261
271
|
return new Text(text, 0, 0);
|
|
262
272
|
}
|
|
263
273
|
|
package/extensions/runner.ts
CHANGED
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
|
|
17
17
|
import type { Message, Model } from "@earendil-works/pi-ai";
|
|
18
18
|
import type { AgentMessage } from "@earendil-works/pi-agent-core";
|
|
19
|
+
import * as path from "node:path";
|
|
19
20
|
import {
|
|
20
21
|
createAgentSession,
|
|
21
22
|
createExtensionRuntime,
|
|
@@ -115,6 +116,8 @@ export interface SubAgentResult {
|
|
|
115
116
|
model?: string;
|
|
116
117
|
stopReason?: string;
|
|
117
118
|
errorMessage?: string;
|
|
119
|
+
/** Unified diff of changes made in an isolated worktree (sandbox: "worktree"). */
|
|
120
|
+
patch?: string;
|
|
118
121
|
/** Canonical result status (added in 0.6.0). */
|
|
119
122
|
status?: SubagentStatus;
|
|
120
123
|
}
|
|
@@ -135,6 +138,8 @@ export async function runSubAgent(options: {
|
|
|
135
138
|
task: string;
|
|
136
139
|
tools: string[];
|
|
137
140
|
model: Model<any>;
|
|
141
|
+
/** "worktree" runs the child in an isolated git worktree; the resulting diff is returned as result.patch. */
|
|
142
|
+
sandbox?: "worktree";
|
|
138
143
|
/** Pi 0.80.10's canonical credential/model runtime. */
|
|
139
144
|
modelRuntime?: unknown;
|
|
140
145
|
/** Legacy Pi SDK session options retained for 0.80.6 tests and hosts. */
|
|
@@ -147,6 +152,8 @@ export async function runSubAgent(options: {
|
|
|
147
152
|
onProgress?: (progress: SubAgentProgress) => void;
|
|
148
153
|
timeoutMs?: number;
|
|
149
154
|
hardTimeoutMs?: number;
|
|
155
|
+
/** Exec used for the git worktree lifecycle (add/remove/diff). Defaults to a child_process spawn when unset. */
|
|
156
|
+
exec?: (command: string, args: string[], options?: { cwd?: string; timeout?: number }) => Promise<{ code: number; stdout: string; stderr: string }>;
|
|
150
157
|
/**
|
|
151
158
|
* When true, build a DefaultResourceLoader so the child inherits the parent's
|
|
152
159
|
* extensions (and thus extension tools: web, serena, munin, …). When false or
|
|
@@ -164,7 +171,7 @@ export async function runSubAgent(options: {
|
|
|
164
171
|
cwd, systemPrompt, task, tools, model, modelRuntime, authStorage, modelRegistry, signal,
|
|
165
172
|
agentName = "subagent", thinkingLevel = "off", onMessage, onProgress,
|
|
166
173
|
timeoutMs = DEFAULT_INACTIVITY_TIMEOUT_MS, hardTimeoutMs = HARD_TIMEOUT_MS,
|
|
167
|
-
loadExtensions = false, projectTrusted = true,
|
|
174
|
+
loadExtensions = false, projectTrusted = true, sandbox, exec,
|
|
168
175
|
} = options;
|
|
169
176
|
const result: SubAgentResult = {
|
|
170
177
|
agent: agentName, task, exitCode: 0, messages: [], stderr: "",
|
|
@@ -210,12 +217,36 @@ export async function runSubAgent(options: {
|
|
|
210
217
|
result.status = classifyStopReason(result.stopReason, !timedOut, timedOut);
|
|
211
218
|
return result;
|
|
212
219
|
}
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
220
|
+
|
|
221
|
+
// Isolated git worktree: the child edits a sibling checkout; the resulting
|
|
222
|
+
// diff is returned as result.patch and the worktree is removed on exit.
|
|
223
|
+
// ponytail: falls back to the in-process cwd when git is unavailable — the
|
|
224
|
+
// worktree is an isolation optimization, not a hard requirement.
|
|
225
|
+
let worktreeDir: string | undefined;
|
|
226
|
+
let childCwd = cwd;
|
|
227
|
+
if (sandbox === "worktree") {
|
|
228
|
+
const wt = await createWorktree(cwd, exec);
|
|
229
|
+
if (wt.ok) {
|
|
230
|
+
worktreeDir = wt.path;
|
|
231
|
+
childCwd = wt.path!;
|
|
232
|
+
} else if (wt.error) {
|
|
233
|
+
result.stderr = `Worktree unavailable (${wt.error}); running in workspace.`;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
let session: Awaited<ReturnType<typeof createAgentSession>>["session"];
|
|
238
|
+
try {
|
|
239
|
+
const created = await createAgentSession({
|
|
240
|
+
cwd: childCwd, model, thinkingLevel, resourceLoader, tools, sessionManager: SessionManager.inMemory(childCwd), settingsManager,
|
|
241
|
+
...(modelRuntime ? { modelRuntime } : {}),
|
|
242
|
+
// Pi 0.80.10 owns credentials in ModelRuntime; older SDKs still accept these.
|
|
243
|
+
...(authStorage ? { authStorage, modelRegistry } : {}),
|
|
244
|
+
} as any);
|
|
245
|
+
session = created.session;
|
|
246
|
+
} catch (error) {
|
|
247
|
+
if (worktreeDir) await removeWorktree(cwd, worktreeDir, exec);
|
|
248
|
+
throw error;
|
|
249
|
+
}
|
|
219
250
|
let unsubscribe: (() => void) | undefined;
|
|
220
251
|
let removeAbort: (() => void) | undefined;
|
|
221
252
|
try {
|
|
@@ -257,10 +288,17 @@ export async function runSubAgent(options: {
|
|
|
257
288
|
else if (combinedSignal.aborted) { result.stopReason = "aborted"; result.errorMessage ||= "Sub-agent aborted"; }
|
|
258
289
|
result.status = classifyStopReason(result.stopReason, result.stopReason === "aborted", result.stopReason === "timeout");
|
|
259
290
|
result.exitCode = result.status === "success" || result.status === "partial" ? 0 : 1;
|
|
291
|
+
if (worktreeDir) {
|
|
292
|
+
// Capture the child's changes as a unified diff before tearing down.
|
|
293
|
+
const diff = await captureWorktreeDiff(cwd, worktreeDir, exec);
|
|
294
|
+
if (diff.ok) result.patch = diff.diff;
|
|
295
|
+
else if (diff.error) result.stderr = result.stderr ? `${result.stderr}; diff unavailable (${diff.error})` : `Diff unavailable (${diff.error})`;
|
|
296
|
+
}
|
|
260
297
|
return result;
|
|
261
298
|
} finally {
|
|
262
299
|
unsubscribe?.(); removeAbort?.();
|
|
263
300
|
try { session.dispose(); } catch { /* best effort */ }
|
|
301
|
+
if (worktreeDir) await removeWorktree(cwd, worktreeDir, exec);
|
|
264
302
|
}
|
|
265
303
|
} catch (error) {
|
|
266
304
|
result.exitCode = 1;
|
|
@@ -277,6 +315,88 @@ export async function runSubAgent(options: {
|
|
|
277
315
|
// Helpers
|
|
278
316
|
// ---------------------------------------------------------------------------
|
|
279
317
|
|
|
318
|
+
/** Minimal exec fallback (child_process spawn) used when no exec is injected. */
|
|
319
|
+
async function defaultExec(
|
|
320
|
+
command: string,
|
|
321
|
+
args: string[],
|
|
322
|
+
options?: { cwd?: string; timeout?: number },
|
|
323
|
+
): Promise<{ code: number; stdout: string; stderr: string }> {
|
|
324
|
+
const { spawn } = await import("node:child_process");
|
|
325
|
+
return new Promise((resolve) => {
|
|
326
|
+
const child = spawn(command, args, { cwd: options?.cwd, stdio: ["ignore", "pipe", "pipe"] });
|
|
327
|
+
// Decode each chunk as a complete UTF-8 stream (Buffer.toString per chunk
|
|
328
|
+
// would corrupt multi-byte sequences straddling chunk boundaries).
|
|
329
|
+
child.stdout.setEncoding("utf8");
|
|
330
|
+
child.stderr.setEncoding("utf8");
|
|
331
|
+
let stdout = ""; let stderr = "";
|
|
332
|
+
const timer = options?.timeout ? setTimeout(() => child.kill("SIGKILL"), options.timeout) : undefined;
|
|
333
|
+
child.stdout.on("data", (d) => { stdout += d; });
|
|
334
|
+
child.stderr.on("data", (d) => { stderr += d; });
|
|
335
|
+
child.on("error", (err) => { if (timer) clearTimeout(timer); resolve({ code: 1, stdout, stderr: String(err.message ?? err) }); });
|
|
336
|
+
child.on("close", (code) => { if (timer) clearTimeout(timer); resolve({ code: code ?? 1, stdout, stderr }); });
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
async function runGit(
|
|
341
|
+
cwd: string,
|
|
342
|
+
args: string[],
|
|
343
|
+
exec?: (command: string, args: string[], options?: { cwd?: string; timeout?: number }) => Promise<{ code: number; stdout: string; stderr: string }>,
|
|
344
|
+
): Promise<{ ok: boolean; stdout: string; stderr: string }> {
|
|
345
|
+
const run = exec ?? defaultExec;
|
|
346
|
+
const res = await run("git", args, { cwd, timeout: 30_000 });
|
|
347
|
+
return { ok: res.code === 0, stdout: res.stdout, stderr: res.stderr };
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
/** Create a detached git worktree at .pi-worktrees/<rand> under the repo root. */
|
|
351
|
+
export async function createWorktree(
|
|
352
|
+
cwd: string,
|
|
353
|
+
exec?: (command: string, args: string[], options?: { cwd?: string; timeout?: number }) => Promise<{ code: number; stdout: string; stderr: string }>,
|
|
354
|
+
): Promise<{ ok: boolean; path?: string; error?: string }> {
|
|
355
|
+
try {
|
|
356
|
+
const root = await runGit(cwd, ["rev-parse", "--show-toplevel"], exec);
|
|
357
|
+
if (!root.ok) return { ok: false, error: root.stderr.trim() || "not a git repo" };
|
|
358
|
+
const repoRoot = root.stdout.trim();
|
|
359
|
+
if (!repoRoot) return { ok: false, error: "empty git root" };
|
|
360
|
+
const id = `pi-subagent-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
|
|
361
|
+
const wtPath = path.join(repoRoot, ".pi-worktrees", id);
|
|
362
|
+
const add = await runGit(repoRoot, ["worktree", "add", "--detach", wtPath, "HEAD"], exec);
|
|
363
|
+
if (!add.ok) return { ok: false, error: add.stderr.trim() || "git worktree add failed" };
|
|
364
|
+
return { ok: true, path: wtPath };
|
|
365
|
+
} catch (error) {
|
|
366
|
+
return { ok: false, error: error instanceof Error ? error.message : String(error) };
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
/** Unified diff of ALL changes in the worktree vs HEAD (tracked edits, staged
|
|
371
|
+
* changes, AND new untracked files). Stages first so untracked files are
|
|
372
|
+
* captured — the worktree is removed right after, so mutating its index is
|
|
373
|
+
* safe. A single `diff --cached HEAD` avoids duplicate hunks from combining
|
|
374
|
+
* `diff HEAD` + `diff --cached`. */
|
|
375
|
+
export async function captureWorktreeDiff(
|
|
376
|
+
repoRoot: string,
|
|
377
|
+
worktreeDir: string,
|
|
378
|
+
exec?: (command: string, args: string[], options?: { cwd?: string; timeout?: number }) => Promise<{ code: number; stdout: string; stderr: string }>,
|
|
379
|
+
): Promise<{ ok: boolean; diff?: string; error?: string }> {
|
|
380
|
+
const add = await runGit(worktreeDir, ["add", "-A"], exec);
|
|
381
|
+
if (!add.ok) return { ok: false, error: add.stderr.trim() || "git add -A failed" };
|
|
382
|
+
const diff = await runGit(worktreeDir, ["diff", "--cached", "HEAD"], exec);
|
|
383
|
+
if (!diff.ok) return { ok: false, error: diff.stderr.trim() || "git diff --cached HEAD failed" };
|
|
384
|
+
const text = diff.stdout.trim();
|
|
385
|
+
return { ok: true, diff: text || "(no changes)" };
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
/** Remove a worktree and its metadata, best-effort. */
|
|
389
|
+
export async function removeWorktree(
|
|
390
|
+
repoRoot: string,
|
|
391
|
+
worktreeDir: string,
|
|
392
|
+
exec?: (command: string, args: string[], options?: { cwd?: string; timeout?: number }) => Promise<{ code: number; stdout: string; stderr: string }>,
|
|
393
|
+
): Promise<void> {
|
|
394
|
+
try {
|
|
395
|
+
await runGit(repoRoot, ["worktree", "remove", "--force", worktreeDir], exec);
|
|
396
|
+
} catch { /* best effort */ }
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
|
|
280
400
|
export function getFinalOutput(messages: Message[]): string {
|
|
281
401
|
for (let i = messages.length - 1; i >= 0; i--) {
|
|
282
402
|
const msg = messages[i];
|
package/extensions/service.ts
CHANGED
|
@@ -117,6 +117,7 @@ export async function runNamedAgent(options: {
|
|
|
117
117
|
|
|
118
118
|
const result = await runSubAgent({
|
|
119
119
|
cwd: safeCwd.path,
|
|
120
|
+
sandbox: options.agent.sandbox === "worktree" ? "worktree" : undefined,
|
|
120
121
|
systemPrompt: contract ? `${options.agent.systemPrompt}\n\n## Task Contract\n${contract}` : options.agent.systemPrompt,
|
|
121
122
|
task: options.task,
|
|
122
123
|
tools: toolValidation.tools,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bacnh85/pi-subagent",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.1",
|
|
4
4
|
"description": "In-process subagents for Pi with isolated SDK sessions, parallel and chained delegation, and inspectable threads.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -56,17 +56,17 @@
|
|
|
56
56
|
"check": "npm run typecheck && npm test"
|
|
57
57
|
},
|
|
58
58
|
"peerDependencies": {
|
|
59
|
-
"@earendil-works/pi-coding-agent": ">=0.80.0 <0.
|
|
60
|
-
"@earendil-works/pi-ai": ">=0.80.0 <0.
|
|
61
|
-
"@earendil-works/pi-agent-core": ">=0.80.0 <0.
|
|
62
|
-
"@earendil-works/pi-tui": ">=0.80.0 <0.
|
|
59
|
+
"@earendil-works/pi-coding-agent": ">=0.80.0 <0.85.0",
|
|
60
|
+
"@earendil-works/pi-ai": ">=0.80.0 <0.85.0",
|
|
61
|
+
"@earendil-works/pi-agent-core": ">=0.80.0 <0.85.0",
|
|
62
|
+
"@earendil-works/pi-tui": ">=0.80.0 <0.85.0",
|
|
63
63
|
"typebox": ">=1.3.0 <2.0.0"
|
|
64
64
|
},
|
|
65
65
|
"devDependencies": {
|
|
66
|
-
"@earendil-works/pi-agent-core": "^0.
|
|
67
|
-
"@earendil-works/pi-ai": "^0.
|
|
68
|
-
"@earendil-works/pi-coding-agent": "^0.
|
|
69
|
-
"@earendil-works/pi-tui": "^0.
|
|
66
|
+
"@earendil-works/pi-agent-core": "^0.84.0",
|
|
67
|
+
"@earendil-works/pi-ai": "^0.84.0",
|
|
68
|
+
"@earendil-works/pi-coding-agent": "^0.84.0",
|
|
69
|
+
"@earendil-works/pi-tui": "^0.84.0",
|
|
70
70
|
"@types/mocha": "^10.0.10",
|
|
71
71
|
"@types/node": "^20.19.43",
|
|
72
72
|
"mocha": "^10.8.2",
|