@skelm/pi 0.3.4 → 0.3.5

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
@@ -1,12 +1,21 @@
1
1
  # @skelm/pi
2
2
 
3
- > Pi coding-agent backend for [skelm](https://github.com/scottgl9/skelm) — drives [`@mariozechner/pi-coding-agent`](https://www.npmjs.com/package/@mariozechner/pi-coding-agent) over its JSONL RPC protocol with full permission enforcement.
3
+ > Pi coding-agent backend for [skelm](https://github.com/scottgl9/skelm) — integrates [`@mariozechner/pi-coding-agent`](https://www.npmjs.com/package/@mariozechner/pi-coding-agent) with full permission enforcement.
4
4
 
5
5
  [![npm](https://img.shields.io/npm/v/@skelm/pi)](https://www.npmjs.com/package/@skelm/pi)
6
6
 
7
7
  Part of [skelm](https://github.com/scottgl9/skelm).
8
8
 
9
- Spawns `pi --mode rpc` per call and streams the response back over the documented JSONL protocol. Maps skelm's `AgentPermissions` onto Pi's permission flags so denied tools / hosts / filesystem writes fail at step start.
9
+ Two backends are available:
10
+
11
+ | | `createPiBackend` (RPC) | `createPiSdkBackend` (SDK) |
12
+ |---|---|---|
13
+ | **How it works** | Spawns `pi --mode rpc` per call | Uses `@mariozechner/pi-coding-agent` SDK directly |
14
+ | **Tool enforcement** | Advisory (skelm intercepts after the fact) | Native (pi hard-enforces the allowlist) |
15
+ | **System prompt** | Not controllable | Pi's default; `req.system` appended; optional full replace |
16
+ | **Peer dependency** | `pi` CLI on `$PATH` | `@mariozechner/pi-coding-agent` installed |
17
+
18
+ Use the **SDK backend** for new work — it gives you hard tool enforcement and real system prompt control. The RPC backend exists for environments where the SDK peer dependency can't be installed.
10
19
 
11
20
  ## Install
12
21
 
@@ -14,18 +23,29 @@ Spawns `pi --mode rpc` per call and streams the response back over the documente
14
23
  npm install @skelm/pi
15
24
  ```
16
25
 
17
- You need the `pi` CLI on `$PATH` (or set `command` in the backend options).
26
+ **RPC backend** additionally requires the `pi` CLI on `$PATH`:
27
+
28
+ ```bash
29
+ npm install -g @mariozechner/pi-coding-agent # installs the `pi` binary
30
+ ```
31
+
32
+ **SDK backend** additionally requires the SDK as a peer dependency:
18
33
 
19
- ## Quick Start
34
+ ```bash
35
+ npm install @mariozechner/pi-coding-agent
36
+ ```
37
+
38
+ ## SDK backend (recommended)
20
39
 
21
40
  ```ts
22
41
  import { agent, pipeline } from 'skelm'
23
- import { createPiBackend } from '@skelm/pi'
42
+ import { createPiSdkBackend } from '@skelm/pi'
24
43
 
25
- const pi = createPiBackend({
26
- command: 'pi',
27
- model: 'qwen-3-coder-32b',
28
- // ...
44
+ const pi = createPiSdkBackend({
45
+ // All options are optional
46
+ cwd: './workspace', // working directory; defaults to process.cwd()
47
+ timeout: 300_000, // ms; default 5 min
48
+ maxConcurrent: 4, // queued beyond this; 0 = unlimited
29
49
  })
30
50
 
31
51
  export default pipeline({
@@ -34,35 +54,118 @@ export default pipeline({
34
54
  agent({
35
55
  id: 'pi-step',
36
56
  backend: pi,
37
- agentDef: './agents/coder',
57
+ prompt: 'Refactor the auth module to use async/await throughout.',
38
58
  permissions: {
39
- allowedTools: ['edit', 'bash'],
40
- fsRead: ['./src'],
41
- fsWrite: ['./src'],
59
+ allowedExecutables: ['bash'],
60
+ fsRead: ['./src'],
61
+ fsWrite: ['./src'],
42
62
  },
43
- maxTurns: 8,
44
63
  }),
45
64
  ],
46
65
  })
47
66
  ```
48
67
 
49
- ## What's exported
68
+ ### System prompt
69
+
70
+ By default pi's coding-agent system prompt is kept active. `req.system` and skill blocks are appended after it.
71
+
72
+ ```ts
73
+ // append step-level system context to pi's default prompt (default)
74
+ agent({ system: 'Follow the project style guide.', ... })
75
+
76
+ // replace pi's base prompt entirely (use sparingly)
77
+ createPiSdkBackend({ systemPrompt: 'You are a TypeScript refactoring specialist.' })
78
+ ```
79
+
80
+ ### Sandbox defaults
81
+
82
+ The SDK backend enables predictable sandboxing out of the box:
83
+
84
+ | Option | Default | Reason |
85
+ |---|---|---|
86
+ | `noExtensions` | `true` | `.pi/extensions/` can register tools and intercept messages in ways skelm cannot audit |
87
+ | `noSkills` | `true` | skelm injects skills itself; loading `.pi/skills/` would cause duplicates |
88
+ | `noContextFiles` | `false` | `AGENTS.md` and `.pi/context/` are useful project context |
89
+
90
+ Opt back in at the backend level:
91
+
92
+ ```ts
93
+ createPiSdkBackend({
94
+ noExtensions: false, // allow project extensions
95
+ noSkills: false, // also load .pi/skills/ from cwd
96
+ noContextFiles: true, // suppress cwd context files
97
+ })
98
+ ```
99
+
100
+ ### Permission → tool mapping
101
+
102
+ `derivePiToolAllowlist(policy)` translates a skelm `ResolvedPolicy` into pi's native tool names:
103
+
104
+ | skelm permission | pi tools enabled |
105
+ |---|---|
106
+ | `allowedExecutables` has `bash` or `sh` | `bash` |
107
+ | `fsRead.size > 0` | `read`, `grep`, `find`, `ls` |
108
+ | `fsWrite.size > 0` | `write`, `edit` (+ read tools) |
109
+ | policy `undefined` | no override — pi uses its defaults |
110
+ | policy present, nothing granted | `noTools: 'all'` — all built-ins suppressed |
111
+
112
+ ### ⚠ Permission semantics differ from MCP-host backends
113
+
114
+ The SDK backend trades skelm's per-call MCP enforcement for pi's process-level enforcement. Two consequences worth knowing:
115
+
116
+ - **`bash` is all-or-nothing.** Pi has a single `bash` tool, not per-binary tools. If `allowedExecutables` contains `bash` or `sh`, the agent can run *any* binary. Per-binary filtering (e.g. allow `git` but not `rm`) is not enforced — pi has no hook for it. With backends that route through `@skelm/core`'s MCP host, `requestedExecutable()` does enforce per-binary at the call site.
117
+ - **Filesystem paths are advisory.** `fsRead`/`fsWrite` paths unlock the *category* of filesystem tools, but pi's `read`/`write`/`grep`/`find`/`ls` tools can access anywhere the pi process has filesystem permission. They do not honour skelm's path allowlist.
118
+
119
+ If you need per-binary or per-path enforcement, use the MCP-host backends (claude-code, opencode) and route privileged operations through MCP servers that skelm can intercept. Use the pi SDK backend when you accept process-level sandboxing — typically when running pi inside an isolated workspace (ephemeral cwd, OS sandbox, container) where pi's full filesystem and shell access is already bounded.
120
+
121
+ ## RPC backend
122
+
123
+ ```ts
124
+ import { createPiBackend } from '@skelm/pi'
125
+
126
+ const pi = createPiBackend({
127
+ command: 'pi', // path to binary; default: 'pi' on $PATH
128
+ provider: 'anthropic', // pi provider name; omit for pi's default
129
+ model: 'claude-opus-4-5', // model id; omit for pi's default
130
+ cwd: './workspace',
131
+ timeout: 300_000,
132
+ maxConcurrent: 4,
133
+ })
134
+ ```
135
+
136
+ The RPC backend spawns one `pi --mode rpc` process per call and streams the response over the JSONL protocol. Tool enforcement is advisory — skelm maps `AgentPermissions` to pi's permission flags but cannot intercept individual tool calls after dispatch.
137
+
138
+ ## Skills
139
+
140
+ Both backends support skelm skills. Declare them on the `agent()` step:
141
+
142
+ ```ts
143
+ agent({
144
+ id: 'implement',
145
+ backend: pi,
146
+ skills: ['code-review', 'style-guide'],
147
+ prompt: 'Implement the feature.',
148
+ })
149
+ ```
150
+
151
+ Skills are injected into the system prompt via `formatSkillBlock` (includes the skill's description, compatibility, and allowed-tools metadata before the body).
152
+
153
+ ## Exports
50
154
 
51
155
  ```ts
52
- export {
53
- createPiBackend,
54
- PiBackendError,
55
- PiBackendAuthenticationError,
56
- PiBackendRateLimitError,
57
- PiBackendTimeoutError,
58
- } from './backend.js'
59
- export { createPiBackendFromConfig } from './factory.js'
60
- export { PiProvider, createPiProvider } from './provider.js'
61
- export { PiRpcClient } from './rpc-client.js'
62
-
63
- export type { PiBackendOptions } from './types.js'
64
- export type { PiBackendConfig } from './factory.js'
65
- export type { PiRpcClientOptions, PiRpcResponse } from './rpc-client.js'
156
+ // RPC backend
157
+ export { createPiBackend, PiBackendError, PiBackendAuthenticationError,
158
+ PiBackendRateLimitError, PiBackendTimeoutError } from '@skelm/pi'
159
+ export { createPiBackendFromConfig } from '@skelm/pi'
160
+ export { PiProvider, createPiProvider } from '@skelm/pi'
161
+ export { PiRpcClient } from '@skelm/pi'
162
+ export type { PiBackendOptions, PiBackendConfig, PiRpcClientOptions, PiRpcResponse } from '@skelm/pi'
163
+
164
+ // SDK backend
165
+ export { createPiSdkBackend, derivePiToolAllowlist, PiSdkBackendError,
166
+ PiSdkBackendAuthenticationError, PiSdkBackendTimeoutError } from '@skelm/pi'
167
+ export { PiSdkClient } from '@skelm/pi'
168
+ export type { PiSdkBackendOptions, PiSdkClientOptions, PiSdkResponse } from '@skelm/pi'
66
169
  ```
67
170
 
68
171
  ## Stability
@@ -1 +1 @@
1
- {"version":3,"file":"backend.d.ts","sourceRoot":"","sources":["../src/backend.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAKV,YAAY,EACb,MAAM,aAAa,CAAA;AAEpB,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAElD,gDAAgD;AAChD,qBAAa,cAAe,SAAQ,KAAK;aAInB,KAAK,CAAC,EAAE,OAAO;IAHnC,SAAkB,IAAI,oBAAmB;gBAEvC,OAAO,EAAE,MAAM,EACG,KAAK,CAAC,EAAE,OAAO,YAAA;CAIpC;AAED,qBAAa,4BAA6B,SAAQ,cAAc;CAAG;AACnE,qBAAa,uBAAwB,SAAQ,cAAc;CAAG;AAC9D,qBAAa,qBAAsB,SAAQ,cAAc;CAAG;AAE5D;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,OAAO,GAAE,gBAAqB,GAAG,YAAY,CAqF5E"}
1
+ {"version":3,"file":"backend.d.ts","sourceRoot":"","sources":["../src/backend.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAKV,YAAY,EACb,MAAM,aAAa,CAAA;AAEpB,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAElD,gDAAgD;AAChD,qBAAa,cAAe,SAAQ,KAAK;aAInB,KAAK,CAAC,EAAE,OAAO;IAHnC,SAAkB,IAAI,oBAAmB;gBAEvC,OAAO,EAAE,MAAM,EACG,KAAK,CAAC,EAAE,OAAO,YAAA;CAIpC;AAED,qBAAa,4BAA6B,SAAQ,cAAc;CAAG;AACnE,qBAAa,uBAAwB,SAAQ,cAAc;CAAG;AAC9D,qBAAa,qBAAsB,SAAQ,cAAc;CAAG;AAE5D;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,OAAO,GAAE,gBAAqB,GAAG,YAAY,CAsF5E"}
package/dist/backend.js CHANGED
@@ -6,6 +6,7 @@
6
6
  //
7
7
  // Pi does NOT speak ACP; this backend uses the native pi RPC protocol
8
8
  // documented in @mariozechner/pi-coding-agent/docs/rpc.md.
9
+ import { formatSkillBlock } from '@skelm/core';
9
10
  import { PiRpcClient } from './rpc-client.js';
10
11
  /** Custom error types exposed from @skelm/pi */
11
12
  export class PiBackendError extends Error {
@@ -36,7 +37,7 @@ export function createPiBackend(options = {}) {
36
37
  streaming: true,
37
38
  sessionLifecycle: true,
38
39
  mcp: false, // pi manages its own tools; no external MCP wiring
39
- skills: false,
40
+ skills: true,
40
41
  modelSelection: options.model !== undefined,
41
42
  toolPermissions: 'native', // pi enforces its own tool permissions
42
43
  };
@@ -75,7 +76,8 @@ export function createPiBackend(options = {}) {
75
76
  context.signal.addEventListener('abort', onAbort, { once: true });
76
77
  try {
77
78
  await client.start();
78
- const prompt = buildPrompt(request);
79
+ const skillBodies = await loadSkillBodies(request, context);
80
+ const prompt = buildPrompt(request, skillBodies);
79
81
  const result = await client.prompt(prompt, options.timeout ?? 300_000);
80
82
  return {
81
83
  text: result.text,
@@ -111,10 +113,26 @@ export function createPiBackend(options = {}) {
111
113
  * Build the prompt string sent to pi, incorporating system prompt and
112
114
  * any multi-turn context from the request.
113
115
  */
114
- function buildPrompt(req) {
116
+ async function loadSkillBodies(req, ctx) {
117
+ if (!req.skills || req.skills.length === 0 || !ctx.loadSkill)
118
+ return [];
119
+ const bodies = [];
120
+ for (const skillId of req.skills) {
121
+ const skill = await ctx.loadSkill(skillId);
122
+ if (skill !== null)
123
+ bodies.push(formatSkillBlock(skill));
124
+ }
125
+ return bodies;
126
+ }
127
+ function buildPrompt(req, skillBodies = []) {
115
128
  const parts = [];
129
+ const systemParts = [];
116
130
  if (req.system)
117
- parts.push(`[System: ${req.system}]`);
131
+ systemParts.push(req.system);
132
+ for (const body of skillBodies)
133
+ systemParts.push(body);
134
+ if (systemParts.length > 0)
135
+ parts.push(`[System: ${systemParts.join('\n\n---\n\n')}]`);
118
136
  parts.push(req.prompt);
119
137
  return parts.join('\n\n');
120
138
  }
@@ -1 +1 @@
1
- {"version":3,"file":"backend.js","sourceRoot":"","sources":["../src/backend.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"backend.js","sourceRoot":"","sources":["../src/backend.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -9,7 +9,10 @@ export { createPiBackend, PiBackendError, PiBackendAuthenticationError, PiBacken
9
9
  export { createPiBackendFromConfig } from './factory.js';
10
10
  export { PiProvider, createPiProvider } from './provider.js';
11
11
  export { PiRpcClient } from './rpc-client.js';
12
- export type { PiBackendOptions } from './types.js';
12
+ export { createPiSdkBackend, derivePiToolAllowlist, PiSdkBackendError, PiSdkBackendAuthenticationError, PiSdkBackendTimeoutError, } from './sdk-backend.js';
13
+ export { PiSdkClient } from './sdk-client.js';
14
+ export type { PiBackendOptions, PiSdkBackendOptions } from './types.js';
13
15
  export type { PiBackendConfig } from './factory.js';
14
16
  export type { PiRpcClientOptions, PiRpcResponse } from './rpc-client.js';
17
+ export type { PiSdkClientOptions, PiSdkResponse } from './sdk-client.js';
15
18
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EACL,eAAe,EACf,cAAc,EACd,4BAA4B,EAC5B,uBAAuB,EACvB,qBAAqB,GACtB,MAAM,cAAc,CAAA;AACrB,OAAO,EAAE,yBAAyB,EAAE,MAAM,cAAc,CAAA;AACxD,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AAC5D,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAC7C,YAAY,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAClD,YAAY,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AACnD,YAAY,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EACL,eAAe,EACf,cAAc,EACd,4BAA4B,EAC5B,uBAAuB,EACvB,qBAAqB,GACtB,MAAM,cAAc,CAAA;AACrB,OAAO,EAAE,yBAAyB,EAAE,MAAM,cAAc,CAAA;AACxD,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AAC5D,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAC7C,OAAO,EACL,kBAAkB,EAClB,qBAAqB,EACrB,iBAAiB,EACjB,+BAA+B,EAC/B,wBAAwB,GACzB,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAC7C,YAAY,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAA;AACvE,YAAY,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AACnD,YAAY,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AACxE,YAAY,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA"}
package/dist/index.js CHANGED
@@ -9,4 +9,6 @@ export { createPiBackend, PiBackendError, PiBackendAuthenticationError, PiBacken
9
9
  export { createPiBackendFromConfig } from './factory.js';
10
10
  export { PiProvider, createPiProvider } from './provider.js';
11
11
  export { PiRpcClient } from './rpc-client.js';
12
+ export { createPiSdkBackend, derivePiToolAllowlist, PiSdkBackendError, PiSdkBackendAuthenticationError, PiSdkBackendTimeoutError, } from './sdk-backend.js';
13
+ export { PiSdkClient } from './sdk-client.js';
12
14
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EACL,eAAe,EACf,cAAc,EACd,4BAA4B,EAC5B,uBAAuB,EACvB,qBAAqB,GACtB,MAAM,cAAc,CAAA;AACrB,OAAO,EAAE,yBAAyB,EAAE,MAAM,cAAc,CAAA;AACxD,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AAC5D,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EACL,eAAe,EACf,cAAc,EACd,4BAA4B,EAC5B,uBAAuB,EACvB,qBAAqB,GACtB,MAAM,cAAc,CAAA;AACrB,OAAO,EAAE,yBAAyB,EAAE,MAAM,cAAc,CAAA;AACxD,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AAC5D,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAC7C,OAAO,EACL,kBAAkB,EAClB,qBAAqB,EACrB,iBAAiB,EACjB,+BAA+B,EAC/B,wBAAwB,GACzB,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Pi coding agent SDK backend for skelm.
3
+ *
4
+ * Unlike the RPC backend (which spawns `pi --mode rpc` and cannot intercept
5
+ * individual tool calls), this backend uses the pi SDK directly, allowing
6
+ * skelm to pass a hard tool allowlist that pi enforces natively.
7
+ *
8
+ * System prompt strategy:
9
+ * By default pi's coding-agent system prompt is kept active. req.system
10
+ * and skill blocks are appended after it so the agent has full context.
11
+ * Set options.systemPrompt to replace pi's base prompt entirely.
12
+ *
13
+ * Permission → tool mapping:
14
+ * allowedExecutables contains 'bash' or 'sh' → 'bash'
15
+ * fsRead.size > 0 → 'read', 'grep', 'find', 'ls'
16
+ * fsWrite.size > 0 → 'write', 'edit'
17
+ * undefined policy → no override (pi defaults)
18
+ */
19
+ import type { ResolvedPolicy, SkelmBackend } from '@skelm/core';
20
+ import type { PiSdkBackendOptions } from './types.js';
21
+ export declare class PiSdkBackendError extends Error {
22
+ readonly cause?: unknown | undefined;
23
+ readonly name = "PiSdkBackendError";
24
+ constructor(message: string, cause?: unknown | undefined);
25
+ }
26
+ export declare class PiSdkBackendAuthenticationError extends PiSdkBackendError {
27
+ }
28
+ export declare class PiSdkBackendTimeoutError extends PiSdkBackendError {
29
+ }
30
+ /**
31
+ * Create a pi coding agent backend using the pi SDK.
32
+ *
33
+ * This backend builds an explicit tool allowlist from the skelm permission
34
+ * policy so pi itself enforces which tools the agent may use. This provides
35
+ * native enforcement rather than the advisory enforcement of the RPC backend.
36
+ */
37
+ export declare function createPiSdkBackend(options?: PiSdkBackendOptions): SkelmBackend;
38
+ /**
39
+ * Derive a pi tool allowlist from a skelm permission policy.
40
+ *
41
+ * Returns `undefined` when no policy is set (pi uses its defaults).
42
+ * Returns a string[] (possibly empty) when a policy is present.
43
+ */
44
+ export declare function derivePiToolAllowlist(policy: ResolvedPolicy | undefined): string[] | undefined;
45
+ //# sourceMappingURL=sdk-backend.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sdk-backend.d.ts","sourceRoot":"","sources":["../src/sdk-backend.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAGH,OAAO,KAAK,EAKV,cAAc,EACd,YAAY,EACb,MAAM,aAAa,CAAA;AAEpB,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAA;AAErD,qBAAa,iBAAkB,SAAQ,KAAK;aAItB,KAAK,CAAC,EAAE,OAAO;IAHnC,SAAkB,IAAI,uBAAsB;gBAE1C,OAAO,EAAE,MAAM,EACG,KAAK,CAAC,EAAE,OAAO,YAAA;CAIpC;AAED,qBAAa,+BAAgC,SAAQ,iBAAiB;CAAG;AACzE,qBAAa,wBAAyB,SAAQ,iBAAiB;CAAG;AAElE;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,GAAE,mBAAwB,GAAG,YAAY,CA6FlF;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,cAAc,GAAG,SAAS,GAAG,MAAM,EAAE,GAAG,SAAS,CAsB9F"}
@@ -0,0 +1,174 @@
1
+ /**
2
+ * Pi coding agent SDK backend for skelm.
3
+ *
4
+ * Unlike the RPC backend (which spawns `pi --mode rpc` and cannot intercept
5
+ * individual tool calls), this backend uses the pi SDK directly, allowing
6
+ * skelm to pass a hard tool allowlist that pi enforces natively.
7
+ *
8
+ * System prompt strategy:
9
+ * By default pi's coding-agent system prompt is kept active. req.system
10
+ * and skill blocks are appended after it so the agent has full context.
11
+ * Set options.systemPrompt to replace pi's base prompt entirely.
12
+ *
13
+ * Permission → tool mapping:
14
+ * allowedExecutables contains 'bash' or 'sh' → 'bash'
15
+ * fsRead.size > 0 → 'read', 'grep', 'find', 'ls'
16
+ * fsWrite.size > 0 → 'write', 'edit'
17
+ * undefined policy → no override (pi defaults)
18
+ */
19
+ import { formatSkillBlock } from '@skelm/core';
20
+ import { PiSdkClient } from './sdk-client.js';
21
+ export class PiSdkBackendError extends Error {
22
+ cause;
23
+ name = 'PiSdkBackendError';
24
+ constructor(message, cause) {
25
+ super(message);
26
+ this.cause = cause;
27
+ }
28
+ }
29
+ export class PiSdkBackendAuthenticationError extends PiSdkBackendError {
30
+ }
31
+ export class PiSdkBackendTimeoutError extends PiSdkBackendError {
32
+ }
33
+ /**
34
+ * Create a pi coding agent backend using the pi SDK.
35
+ *
36
+ * This backend builds an explicit tool allowlist from the skelm permission
37
+ * policy so pi itself enforces which tools the agent may use. This provides
38
+ * native enforcement rather than the advisory enforcement of the RPC backend.
39
+ */
40
+ export function createPiSdkBackend(options = {}) {
41
+ const capabilities = {
42
+ prompt: false,
43
+ streaming: true,
44
+ sessionLifecycle: true,
45
+ mcp: false,
46
+ skills: true,
47
+ modelSelection: false,
48
+ toolPermissions: 'native',
49
+ };
50
+ const maxConcurrent = options.maxConcurrent ?? 4;
51
+ let active = 0;
52
+ const queue = [];
53
+ const acquire = () => {
54
+ if (maxConcurrent === 0 || active < maxConcurrent) {
55
+ active++;
56
+ return Promise.resolve();
57
+ }
58
+ return new Promise((resolve) => queue.push(resolve));
59
+ };
60
+ const release = () => {
61
+ const next = queue.shift();
62
+ if (next)
63
+ next();
64
+ else
65
+ active--;
66
+ };
67
+ return {
68
+ id: options.id ?? 'pi-sdk',
69
+ label: options.label ?? 'Pi Coding Agent (SDK)',
70
+ capabilities,
71
+ async run(request, context) {
72
+ await acquire();
73
+ try {
74
+ const policy = context.permissions ?? request.permissions;
75
+ const toolAllowlist = derivePiToolAllowlist(policy);
76
+ const skillBodies = await loadSkillBodies(request, context);
77
+ const systemContent = buildSystemContent(options.systemPrompt, request, skillBodies);
78
+ const cwd = request.cwd ?? options.cwd;
79
+ const client = new PiSdkClient({
80
+ ...(cwd !== undefined && { cwd }),
81
+ ...(toolAllowlist !== undefined && { tools: toolAllowlist }),
82
+ ...(policy !== undefined && toolAllowlist?.length === 0 && { noTools: 'all' }),
83
+ ...(options.noExtensions !== undefined && { noExtensions: options.noExtensions }),
84
+ ...(options.noSkills !== undefined && { noSkills: options.noSkills }),
85
+ ...(options.noContextFiles !== undefined && { noContextFiles: options.noContextFiles }),
86
+ // System prompt: inject content and indicate whether to replace pi's base
87
+ ...(systemContent !== undefined && {
88
+ system: systemContent,
89
+ replaceSystemPrompt: options.systemPrompt !== undefined,
90
+ }),
91
+ });
92
+ const result = await client.prompt(request.prompt, context.signal, options.timeout ?? 300_000);
93
+ return {
94
+ text: result.text,
95
+ stopReason: result.stopReason,
96
+ ...(result.usage !== undefined && {
97
+ usage: {
98
+ inputTokens: result.usage.inputTokens,
99
+ outputTokens: result.usage.outputTokens,
100
+ },
101
+ }),
102
+ };
103
+ }
104
+ catch (err) {
105
+ if (err instanceof Error) {
106
+ if (err.message.includes('ENOENT') || err.message.includes('not installed')) {
107
+ throw new PiSdkBackendAuthenticationError('pi SDK not available. Install it: npm install @mariozechner/pi-coding-agent', err);
108
+ }
109
+ if (err.message.includes('timed out')) {
110
+ throw new PiSdkBackendTimeoutError(err.message, err);
111
+ }
112
+ }
113
+ throw new PiSdkBackendError(`pi SDK agent execution failed: ${err.message}`, err);
114
+ }
115
+ finally {
116
+ release();
117
+ }
118
+ },
119
+ };
120
+ }
121
+ /**
122
+ * Derive a pi tool allowlist from a skelm permission policy.
123
+ *
124
+ * Returns `undefined` when no policy is set (pi uses its defaults).
125
+ * Returns a string[] (possibly empty) when a policy is present.
126
+ */
127
+ export function derivePiToolAllowlist(policy) {
128
+ if (policy === undefined)
129
+ return undefined;
130
+ const allowed = [];
131
+ const execs = policy.allowedExecutables;
132
+ if (execs.has('bash') || execs.has('sh')) {
133
+ allowed.push('bash');
134
+ }
135
+ const fsRead = policy.fsRead;
136
+ if (fsRead instanceof Set ? fsRead.size > 0 : Array.isArray(fsRead) && fsRead.length > 0) {
137
+ allowed.push('read', 'grep', 'find', 'ls');
138
+ }
139
+ const fsWrite = policy.fsWrite;
140
+ if (fsWrite instanceof Set ? fsWrite.size > 0 : Array.isArray(fsWrite) && fsWrite.length > 0) {
141
+ if (!allowed.includes('read'))
142
+ allowed.push('read', 'grep', 'find', 'ls');
143
+ allowed.push('write', 'edit');
144
+ }
145
+ return allowed;
146
+ }
147
+ /**
148
+ * Assemble the system content to inject into pi's system prompt.
149
+ *
150
+ * When systemBase is set it replaces pi's prompt; req.system and skills are
151
+ * always appended so the agent has the step's context regardless of mode.
152
+ */
153
+ function buildSystemContent(systemBase, req, skillBodies) {
154
+ const parts = [];
155
+ if (systemBase !== undefined)
156
+ parts.push(systemBase);
157
+ if (req.system)
158
+ parts.push(req.system);
159
+ for (const body of skillBodies)
160
+ parts.push(body);
161
+ return parts.length > 0 ? parts.join('\n\n---\n\n') : undefined;
162
+ }
163
+ async function loadSkillBodies(req, ctx) {
164
+ if (!req.skills || req.skills.length === 0 || !ctx.loadSkill)
165
+ return [];
166
+ const bodies = [];
167
+ for (const skillId of req.skills) {
168
+ const skill = await ctx.loadSkill(skillId);
169
+ if (skill !== null)
170
+ bodies.push(formatSkillBlock(skill));
171
+ }
172
+ return bodies;
173
+ }
174
+ //# sourceMappingURL=sdk-backend.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sdk-backend.js","sourceRoot":"","sources":["../src/sdk-backend.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Thin wrapper around the pi coding agent SDK for programmatic use.
3
+ *
4
+ * Uses createAgentSessionServices + createAgentSessionFromServices so we can
5
+ * pass resource-loader options (system prompt, skill/extension suppression)
6
+ * that createAgentSession does not expose directly.
7
+ */
8
+ export interface PiSdkClientOptions {
9
+ /** Working directory for pi's project-local discovery. Default: process.cwd() */
10
+ cwd?: string;
11
+ /**
12
+ * Allowlist of tool names enabled for this session.
13
+ * When omitted pi enables its default built-in tools (bash, read, edit, write).
14
+ * When provided, only the listed names are active.
15
+ */
16
+ tools?: string[];
17
+ /** Suppress built-in tools when no allowlist covers them. */
18
+ noTools?: 'all' | 'builtin';
19
+ /**
20
+ * Content injected into pi's system prompt.
21
+ * When replaceSystemPrompt is false (default), appended after pi's base prompt.
22
+ * When replaceSystemPrompt is true, replaces pi's base prompt entirely.
23
+ */
24
+ system?: string;
25
+ /**
26
+ * When true, system replaces pi's base system prompt instead of appending.
27
+ * Default: false — pi's coding-agent prompt stays active; system is appended.
28
+ */
29
+ replaceSystemPrompt?: boolean;
30
+ /**
31
+ * Disable pi's built-in skill loading from .pi/skills/ directories.
32
+ * Default: true — skelm injects skills itself via formatSkillBlock; loading
33
+ * pi's own skills would cause duplicates.
34
+ */
35
+ noSkills?: boolean;
36
+ /**
37
+ * Disable pi's extension loading from .pi/extensions/.
38
+ * Default: true — extensions can register additional tools and modify behaviour
39
+ * in ways skelm cannot audit; disable by default for predictable sandboxing.
40
+ */
41
+ noExtensions?: boolean;
42
+ /**
43
+ * Disable pi's cwd context file discovery (AGENTS.md, .pi/context/).
44
+ * Default: false — project context files are useful and safe.
45
+ */
46
+ noContextFiles?: boolean;
47
+ }
48
+ export interface PiSdkResponse {
49
+ text: string;
50
+ stopReason: 'stop' | 'length' | 'toolUse' | 'error' | 'aborted';
51
+ usage?: {
52
+ inputTokens: number;
53
+ outputTokens: number;
54
+ };
55
+ }
56
+ export declare class PiSdkClient {
57
+ private readonly opts;
58
+ constructor(opts?: PiSdkClientOptions);
59
+ prompt(text: string, signal?: AbortSignal, timeoutMs?: number): Promise<PiSdkResponse>;
60
+ private _run;
61
+ }
62
+ //# sourceMappingURL=sdk-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sdk-client.d.ts","sourceRoot":"","sources":["../src/sdk-client.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,WAAW,kBAAkB;IACjC,iFAAiF;IACjF,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;IAChB,6DAA6D;IAC7D,OAAO,CAAC,EAAE,KAAK,GAAG,SAAS,CAAA;IAC3B;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAA;IACf;;;OAGG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAA;IAC7B;;;;OAIG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB;;;;OAIG;IACH,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB;;;OAGG;IACH,cAAc,CAAC,EAAE,OAAO,CAAA;CACzB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,CAAA;IAC/D,KAAK,CAAC,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE,CAAA;CACtD;AAED,qBAAa,WAAW;IACV,OAAO,CAAC,QAAQ,CAAC,IAAI;gBAAJ,IAAI,GAAE,kBAAuB;IAEpD,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,EAAE,SAAS,SAAU,GAAG,OAAO,CAAC,aAAa,CAAC;IA4C7F,OAAO,CAAC,IAAI;CAuEb"}
@@ -0,0 +1,107 @@
1
+ /**
2
+ * Thin wrapper around the pi coding agent SDK for programmatic use.
3
+ *
4
+ * Uses createAgentSessionServices + createAgentSessionFromServices so we can
5
+ * pass resource-loader options (system prompt, skill/extension suppression)
6
+ * that createAgentSession does not expose directly.
7
+ */
8
+ export class PiSdkClient {
9
+ opts;
10
+ constructor(opts = {}) {
11
+ this.opts = opts;
12
+ }
13
+ async prompt(text, signal, timeoutMs = 300_000) {
14
+ // Dynamic import keeps @mariozechner/pi-coding-agent optional at runtime
15
+ const pi = await import('@mariozechner/pi-coding-agent').catch(() => {
16
+ throw new Error('pi SDK not installed. Add @mariozechner/pi-coding-agent to your project: npm install @mariozechner/pi-coding-agent');
17
+ });
18
+ const { createAgentSessionServices, createAgentSessionFromServices, SessionManager } = pi;
19
+ const cwd = this.opts.cwd ?? process.cwd();
20
+ const systemPromptOverride = this.opts.system !== undefined
21
+ ? (base) => this.opts.replaceSystemPrompt
22
+ ? this.opts.system
23
+ : [base, this.opts.system].filter(Boolean).join('\n\n')
24
+ : undefined;
25
+ const services = await createAgentSessionServices({
26
+ cwd,
27
+ resourceLoaderOptions: {
28
+ noSkills: this.opts.noSkills ?? true,
29
+ noExtensions: this.opts.noExtensions ?? true,
30
+ ...(this.opts.noContextFiles && { noContextFiles: true }),
31
+ ...(systemPromptOverride !== undefined && { systemPromptOverride }),
32
+ },
33
+ });
34
+ const { session } = await createAgentSessionFromServices({
35
+ services,
36
+ sessionManager: SessionManager.inMemory(),
37
+ ...(this.opts.tools !== undefined && { tools: this.opts.tools }),
38
+ ...(this.opts.noTools !== undefined && { noTools: this.opts.noTools }),
39
+ });
40
+ try {
41
+ return await this._run(session, text, signal, timeoutMs);
42
+ }
43
+ finally {
44
+ session.dispose();
45
+ }
46
+ }
47
+ _run(session, text, signal, timeoutMs) {
48
+ return new Promise((resolve, reject) => {
49
+ let settled = false;
50
+ const settle = (fn) => {
51
+ if (settled)
52
+ return;
53
+ settled = true;
54
+ clearTimeout(timer);
55
+ signal?.removeEventListener('abort', onAbort);
56
+ fn();
57
+ };
58
+ const timer = setTimeout(() => {
59
+ settle(() => {
60
+ session.abort().catch(() => { });
61
+ reject(new Error(`pi agent timed out after ${timeoutMs}ms`));
62
+ });
63
+ }, timeoutMs);
64
+ const onAbort = () => {
65
+ settle(() => {
66
+ session.abort().catch(() => { });
67
+ reject(new Error('pi agent aborted'));
68
+ });
69
+ };
70
+ if (signal?.aborted) {
71
+ clearTimeout(timer);
72
+ reject(new Error('pi agent aborted'));
73
+ return;
74
+ }
75
+ signal?.addEventListener('abort', onAbort, { once: true });
76
+ const unsub = session.subscribe((event) => {
77
+ if (event.type === 'agent_end') {
78
+ unsub();
79
+ settle(() => {
80
+ const assistantMsg = [...event.messages].reverse().find((m) => m.role === 'assistant');
81
+ if (!assistantMsg || assistantMsg.role !== 'assistant') {
82
+ resolve({ text: '', stopReason: 'stop' });
83
+ return;
84
+ }
85
+ const text = assistantMsg.content
86
+ .filter((c) => c.type === 'text')
87
+ .map((c) => c.text)
88
+ .join('');
89
+ resolve({
90
+ text,
91
+ stopReason: assistantMsg.stopReason,
92
+ usage: {
93
+ inputTokens: assistantMsg.usage.input,
94
+ outputTokens: assistantMsg.usage.output,
95
+ },
96
+ });
97
+ });
98
+ }
99
+ });
100
+ session.prompt(text).catch((err) => {
101
+ unsub();
102
+ settle(() => reject(err));
103
+ });
104
+ });
105
+ }
106
+ }
107
+ //# sourceMappingURL=sdk-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sdk-client.js","sourceRoot":"","sources":["../src/sdk-client.ts"],"names":[],"mappings":"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"}
package/dist/types.d.ts CHANGED
@@ -1,6 +1,44 @@
1
1
  /**
2
2
  * Types for @skelm/pi - Pi coding agent backend
3
3
  */
4
+ export interface PiSdkBackendOptions {
5
+ /** Backend id (default: 'pi-sdk') */
6
+ id?: string;
7
+ /** Human-readable label */
8
+ label?: string;
9
+ /** Working directory for pi's project-local discovery */
10
+ cwd?: string;
11
+ /** Request timeout in ms (default: 300_000 = 5 min) */
12
+ timeout?: number;
13
+ /**
14
+ * Maximum simultaneous pi sessions. Defaults to 4. Set to 0 for unlimited.
15
+ * Excess calls are queued until a slot opens.
16
+ */
17
+ maxConcurrent?: number;
18
+ /**
19
+ * Replace pi's coding-agent system prompt with a custom base.
20
+ * When omitted, pi's default prompt is kept and req.system / skills are
21
+ * appended after it.
22
+ */
23
+ systemPrompt?: string;
24
+ /**
25
+ * Disable pi's extension loading from .pi/extensions/.
26
+ * Default: true — extensions can expand the tool surface in ways skelm
27
+ * cannot audit; disabled by default for predictable sandboxing.
28
+ */
29
+ noExtensions?: boolean;
30
+ /**
31
+ * Disable pi's built-in skill loading from .pi/skills/.
32
+ * Default: true — skelm injects skills itself; loading pi's own skills
33
+ * would cause duplicates.
34
+ */
35
+ noSkills?: boolean;
36
+ /**
37
+ * Disable pi's cwd context file discovery (AGENTS.md, .pi/context/).
38
+ * Default: false — project context files are useful and safe.
39
+ */
40
+ noContextFiles?: boolean;
41
+ }
4
42
  export interface PiBackendOptions {
5
43
  /** Backend id (default: 'pi') */
6
44
  id?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,gBAAgB;IAC/B,iCAAiC;IACjC,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,2BAA2B;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,oDAAoD;IACpD,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,8EAA8E;IAC9E,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,0DAA0D;IAC1D,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,2CAA2C;IAC3C,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,uDAAuD;IACvD,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,mBAAmB;IAClC,qCAAqC;IACrC,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,2BAA2B;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,yDAAyD;IACzD,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,uDAAuD;IACvD,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB;;;;OAIG;IACH,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB;;;OAGG;IACH,cAAc,CAAC,EAAE,OAAO,CAAA;CACzB;AAED,MAAM,WAAW,gBAAgB;IAC/B,iCAAiC;IACjC,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,2BAA2B;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,oDAAoD;IACpD,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,8EAA8E;IAC9E,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,0DAA0D;IAC1D,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,2CAA2C;IAC3C,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,uDAAuD;IACvD,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@skelm/pi",
3
- "version": "0.3.4",
3
+ "version": "0.3.5",
4
4
  "description": "Pi coding-agent backend for skelm with full permission enforcement",
5
5
  "license": "MIT",
6
6
  "author": "Scott Glover <scottgl@gmail.com>",
@@ -44,12 +44,18 @@
44
44
  "test:watch": "vitest",
45
45
  "clean": "rm -rf dist"
46
46
  },
47
- "dependencies": {},
48
47
  "peerDependencies": {
49
- "@skelm/core": "^0.3.4"
48
+ "@mariozechner/pi-coding-agent": ">=0.73.0",
49
+ "@skelm/core": "^0.3.5"
50
+ },
51
+ "peerDependenciesMeta": {
52
+ "@mariozechner/pi-coding-agent": {
53
+ "optional": true
54
+ }
50
55
  },
51
56
  "devDependencies": {
52
- "@skelm/core": "^0.3.4",
57
+ "@mariozechner/pi-coding-agent": "^0.73.0",
58
+ "@skelm/core": "^0.3.5",
53
59
  "@types/node": "^20.10.0",
54
60
  "typescript": "^5.3.0",
55
61
  "vitest": "^1.0.0"