pi-open-agents 0.1.18 → 0.1.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 +8 -2
- package/package.json +1 -1
- package/src/subagent/executor.ts +24 -7
- package/src/subagent/tool.ts +15 -1
package/README.md
CHANGED
|
@@ -94,6 +94,7 @@ here — or native in pi itself:
|
|
|
94
94
|
| `AGENTS.md` adoption — anthropics/claude-code#31005 👍336, openai/codex#12115 👍109 | ✅ Native in pi: `AGENTS.md`/`CLAUDE.md` discovery with `AGENTS.override.md` layering |
|
|
95
95
|
| Agent Skills standard (`.agents/skills/`) — agentskills/agentskills#15 👍183 | ✅ Native in pi; shared agents from `.agents/` (#7 aligns to the dotagents layout) |
|
|
96
96
|
| Tool restrictions that actually reach subagents — anthropics/claude-code#18950 👍70 | ✅ Since v0.1.14, `tools:`/`permission:` restrict the child toolset via `--tools` (full parent inheritance → #8) |
|
|
97
|
+
| Model selection per subagent / per call — sst/opencode#6651 👍71 | ✅ Per-agent `model:` + per-call `model:` override in `subagent()` (since v0.1.19) |
|
|
97
98
|
| Reasoning effort per agent — Kilo-Org/kilocode#13105 👍8 | ✅ `thinking: off…xhigh` per agent, forwarded to the child process |
|
|
98
99
|
| Delegation guards — Kilo-Org/kilocode#9985 | ✅ `allowedAgents` allowlist + `maxDepth` recursion limit |
|
|
99
100
|
| Agent management UI — openai/codex#22321 👍41 | ✅ `/agent`, `/agents`, `/agent-search`, `Ctrl+Shift+M`, programmatic `set_agent` |
|
|
@@ -153,7 +154,7 @@ If an agent has the `subagent` tool, the plugin automatically appends a
|
|
|
153
154
|
subagents and the correct call syntax:
|
|
154
155
|
|
|
155
156
|
```
|
|
156
|
-
subagent({ agent: "<name>", task: "<task>" })
|
|
157
|
+
subagent({ agent: "<name>", task: "<task>", cwd?, session?, model? })
|
|
157
158
|
```
|
|
158
159
|
|
|
159
160
|
You never need to explain delegation mechanics in agent prompts. The plugin
|
|
@@ -170,6 +171,11 @@ This means:
|
|
|
170
171
|
- Each subagent runs with exactly the model and tools it declares
|
|
171
172
|
- Skills load per-agent, with wildcard support (`security-*`, `git-*`)
|
|
172
173
|
|
|
174
|
+
**Per-call model override:** the caller can override the agent's default for a
|
|
175
|
+
single call — `subagent({ agent: "deep-research", task: "...", model: "zai/glm-5.3-flash" })`.
|
|
176
|
+
Handy for "run this one task on the cheap model" without forking an agent
|
|
177
|
+
definition. Malformed values (`no-slash`) are rejected before any spawn.
|
|
178
|
+
|
|
173
179
|
The `--tools` whitelist is derived from both explicit `tools:` arrays and
|
|
174
180
|
permission allow-lists. An agent with `permission: { read: allow, edit: allow }`
|
|
175
181
|
will only get `read` and `edit` in the child process. Wildcard permissions
|
|
@@ -321,7 +327,7 @@ six sessions, zero chaos: that's the exact workstation setup documented in
|
|
|
321
327
|
|
|
322
328
|
- **Parent permission inheritance** for subagents — #8
|
|
323
329
|
- **Agent hot-reload** (or `/reload-agents`) — #9
|
|
324
|
-
-
|
|
330
|
+
- ~~**Per-call model override** in `subagent()`~~ — ✅ shipped in [0.1.19](https://github.com/andrea-tomassi/pi-open-agents/releases/tag/v0.1.19) (#10)
|
|
325
331
|
- **Parallel subagent limit** — #11
|
|
326
332
|
|
|
327
333
|
---
|
package/package.json
CHANGED
package/src/subagent/executor.ts
CHANGED
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
withFileMutationQueue,
|
|
16
16
|
} from "@earendil-works/pi-coding-agent";
|
|
17
17
|
import { spawn } from "node:child_process";
|
|
18
|
+
import { realpathSync } from "node:fs";
|
|
18
19
|
import * as fs from "node:fs/promises";
|
|
19
20
|
import * as os from "node:os";
|
|
20
21
|
import * as path from "node:path";
|
|
@@ -113,6 +114,8 @@ export interface RunSubagentOptions {
|
|
|
113
114
|
outputArchiveDir?: string;
|
|
114
115
|
agentDir?: string;
|
|
115
116
|
session?: SubagentSessionInfo;
|
|
117
|
+
/** Per-call model override ("provider/model-id"). Takes precedence over agent.model. */
|
|
118
|
+
modelOverride?: string;
|
|
116
119
|
resolvePi?: () => Promise<PiResolution> | PiResolution;
|
|
117
120
|
runner?: ProcessRunner;
|
|
118
121
|
fs?: ExecutorFs;
|
|
@@ -193,10 +196,23 @@ export function subagentSessionDir(
|
|
|
193
196
|
return path.join(agentDir, "sessions", safeProject, "subagents");
|
|
194
197
|
}
|
|
195
198
|
|
|
196
|
-
export function resolvePiEntryPoint(
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
199
|
+
export function resolvePiEntryPoint(
|
|
200
|
+
resolveSelf: (specifier: string) => string = (specifier) => import.meta.resolve(specifier),
|
|
201
|
+
): PiResolution {
|
|
202
|
+
let packageEntryPoint: string;
|
|
203
|
+
try {
|
|
204
|
+
packageEntryPoint = fileURLToPath(resolveSelf("@earendil-works/pi-coding-agent"));
|
|
205
|
+
} catch {
|
|
206
|
+
// npm-distributed plugin + bundled pi: the loader resolves host imports
|
|
207
|
+
// through virtualModules, but import.meta.resolve falls back to native
|
|
208
|
+
// resolution which cannot see the host package from the plugin's install
|
|
209
|
+
// tree (peer dependencies are never installed next to it). Fall back to
|
|
210
|
+
// the running pi entry itself — the child must run the same pi anyway.
|
|
211
|
+
return {
|
|
212
|
+
command: process.execPath,
|
|
213
|
+
entryPoint: realpathSync(process.argv[1]),
|
|
214
|
+
};
|
|
215
|
+
}
|
|
200
216
|
const packageRoot = path.dirname(path.dirname(packageEntryPoint));
|
|
201
217
|
return {
|
|
202
218
|
command: process.execPath,
|
|
@@ -504,9 +520,10 @@ export async function runSubagent(options: RunSubagentOptions): Promise<AgentRes
|
|
|
504
520
|
args.push("--no-context-files");
|
|
505
521
|
}
|
|
506
522
|
|
|
507
|
-
// Model override
|
|
508
|
-
|
|
509
|
-
|
|
523
|
+
// Model: per-call override wins over the agent definition default
|
|
524
|
+
const modelId = options.modelOverride ?? options.agent.model;
|
|
525
|
+
if (modelId) {
|
|
526
|
+
args.push("--model", modelId);
|
|
510
527
|
}
|
|
511
528
|
|
|
512
529
|
// Thinking level
|
package/src/subagent/tool.ts
CHANGED
|
@@ -47,6 +47,7 @@ interface SubagentParams {
|
|
|
47
47
|
task: string;
|
|
48
48
|
cwd?: string;
|
|
49
49
|
session?: SubagentSessionMode;
|
|
50
|
+
model?: string;
|
|
50
51
|
}
|
|
51
52
|
|
|
52
53
|
// ─── Helpers ─────────────────────────────────────────────────────────────────
|
|
@@ -199,7 +200,7 @@ export function registerSubagentTool(
|
|
|
199
200
|
name: "subagent",
|
|
200
201
|
label: "Subagent",
|
|
201
202
|
description: "Delegate a task to a named sub-agent running in an isolated pi process.",
|
|
202
|
-
promptSnippet: "Delegate isolated tasks with subagent({ agent, task, cwd?, session? }).",
|
|
203
|
+
promptSnippet: "Delegate isolated tasks with subagent({ agent, task, cwd?, session?, model? }).",
|
|
203
204
|
promptGuidelines,
|
|
204
205
|
parameters: Type.Object({
|
|
205
206
|
agent: Type.String({ description: "Name of the agent to invoke" }),
|
|
@@ -210,6 +211,11 @@ export function registerSubagentTool(
|
|
|
210
211
|
description: 'Parent session handling: none starts a fresh subagent session, fork branches from the current session',
|
|
211
212
|
}),
|
|
212
213
|
),
|
|
214
|
+
model: Type.Optional(
|
|
215
|
+
Type.String({
|
|
216
|
+
description: 'Per-call model override in "provider/model-id" format (e.g. "anthropic/claude-sonnet-4-5"). Takes precedence over the agent definition default.',
|
|
217
|
+
}),
|
|
218
|
+
),
|
|
213
219
|
}),
|
|
214
220
|
|
|
215
221
|
async execute(
|
|
@@ -237,6 +243,13 @@ export function registerSubagentTool(
|
|
|
237
243
|
}
|
|
238
244
|
|
|
239
245
|
const childCwd = params.cwd ?? ctx.cwd;
|
|
246
|
+
|
|
247
|
+
if (params.model !== undefined && !/^[^/\s]+\/[^/\s]+$/.test(params.model)) {
|
|
248
|
+
throw new Error(
|
|
249
|
+
`Invalid model "${params.model}": expected "provider/model-id" format (e.g. "anthropic/claude-sonnet-4-5").`,
|
|
250
|
+
);
|
|
251
|
+
}
|
|
252
|
+
|
|
240
253
|
const session = resolveSubagentSession(
|
|
241
254
|
params.session,
|
|
242
255
|
childCwd,
|
|
@@ -254,6 +267,7 @@ export function registerSubagentTool(
|
|
|
254
267
|
availableAgents: availableSubagentsForAgent(agent, availableSubagents),
|
|
255
268
|
agentDir: options.agentDir,
|
|
256
269
|
session,
|
|
270
|
+
modelOverride: params.model,
|
|
257
271
|
onProgress: (progress) => onUpdate?.(toProgressResult(progress)),
|
|
258
272
|
});
|
|
259
273
|
|