pi-open-agents 0.1.14 → 0.1.15

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
@@ -91,8 +91,10 @@ permission:
91
91
  "subagent": deny # no delegation
92
92
  ```
93
93
 
94
- Tool names are normalized automatically: `write` → `edit`, `task` → `subagent`,
95
- `vscode` → `read`.
94
+ Tool names are normalized automatically: `task` → `subagent`, `vscode` → `read`,
95
+ `apply_patch` → `edit` (OpenCode-only tool). In pi, `write` and `edit` are
96
+ **separate** tools — `write` creates/overwrites files, `edit` does search-and-
97
+ replace — so they have separate permission categories.
96
98
 
97
99
  ### Auto-injected delegation guidance
98
100
 
@@ -118,6 +120,11 @@ This means:
118
120
  - Each subagent runs with exactly the model and tools it declares
119
121
  - Skills load per-agent, with wildcard support (`security-*`, `git-*`)
120
122
 
123
+ The `--tools` whitelist is derived from both explicit `tools:` arrays and
124
+ permission allow-lists. An agent with `permission: { read: allow, edit: allow }`
125
+ will only get `read` and `edit` in the child process. Wildcard permissions
126
+ (`*: allow`) cannot produce a finite whitelist — the child gets all tools.
127
+
121
128
  ### OpenCode compatibility
122
129
 
123
130
  Your `.opencode/agent/` files work as-is. The `tools` map format is auto-converted
@@ -133,6 +140,10 @@ tools:
133
140
  bash: false
134
141
  ```
135
142
 
143
+ The `tools` map is converted to permission rules and **also restricts the
144
+ subagent child process** — a subagent with `tools: { read: true, bash: false }`
145
+ will only have access to the `read` tool when spawned.
146
+
136
147
  ### Mode-based visibility
137
148
 
138
149
  | `mode` | TUI selector | `subagent` tool | `set_agent` tool |
@@ -249,9 +260,12 @@ Optional cleanup:
249
260
 
250
261
  ## Development
251
262
 
263
+ **Contributing?** Please read the [Contributing Guide](./CONTRIBUTING.md) before
264
+ opening an issue or pull request.
265
+
252
266
  ```bash
253
267
  npm install
254
- npm test # 84 tests
268
+ npm test # 117 tests
255
269
  npm run typecheck # tsc --noEmit
256
270
  ```
257
271
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-open-agents",
3
- "version": "0.1.14",
3
+ "version": "0.1.15",
4
4
  "description": "Unified agent and subagent management for pi coding agent, with OpenCode-compatible agent definitions.",
5
5
  "keywords": [
6
6
  "pi-package",
@@ -64,6 +64,7 @@
64
64
  "devDependencies": {
65
65
  "@types/node": "^24.0.0",
66
66
  "tsx": "^4.19.0",
67
+ "typebox": "^1.3.10",
67
68
  "typescript": "^5.6.0"
68
69
  }
69
70
  }
package/src/tui/tools.ts CHANGED
@@ -14,6 +14,7 @@ import { Type } from "typebox";
14
14
  import type { AgentDefinition } from "../types.ts";
15
15
  import { selectableAgents } from "../discovery/loader.ts";
16
16
  import type { AgentManager } from "../primary/manager.ts";
17
+ import { isSubagentProcess } from "../subagent/env.ts";
17
18
  import { updateBanner } from "./banner.ts";
18
19
 
19
20
  /**
@@ -32,6 +33,10 @@ export function registerAgentTools(manager: AgentManager, pi: ExtensionAPI): voi
32
33
  reason: Type.Optional(Type.String({ description: "Reason for switching agents" })),
33
34
  }),
34
35
  async execute(_toolCallId, params, _signal, _onUpdate, ctx: ExtensionContext) {
36
+ if (isSubagentProcess(process.env)) {
37
+ throw new Error("set_agent is only available to the primary agent, not subagents.");
38
+ }
39
+
35
40
  const { agent: name, reason } = params;
36
41
 
37
42
  const agent = manager.getAgent(name);
@@ -40,6 +45,10 @@ export function registerAgentTools(manager: AgentManager, pi: ExtensionAPI): voi
40
45
  throw new Error(`Unknown agent "${name}". Available: ${available}`);
41
46
  }
42
47
 
48
+ if (agent.mode === "subagent") {
49
+ throw new Error(`Agent "${name}" is a subagent and cannot be set as the primary agent.`);
50
+ }
51
+
43
52
  const success = await manager.apply(name, pi, ctx);
44
53
  if (!success) {
45
54
  throw new Error(`Failed to apply agent "${name}"`);