@zooid/acp-client 0.11.2 → 0.13.0

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zooid/acp-client",
3
- "version": "0.11.2",
3
+ "version": "0.13.0",
4
4
  "description": "Zooid's ACP client: spawn agent subprocesses, drive them via Agent Client Protocol, route events and permission requests through callbacks.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -67,6 +67,32 @@ describe('preset mount declarations — home / data / config', () => {
67
67
  })
68
68
  })
69
69
 
70
+ describe('pi mount declarations (ZOD073)', () => {
71
+ it('declares a single `home` mount at ${daemonHome}/.pi', () => {
72
+ const mounts = PRESETS.pi.mounts!(ctx)
73
+ expect(mounts).toHaveLength(1)
74
+ expect(mounts[0]).toMatchObject({
75
+ id: 'home',
76
+ host: '/home/zooid/.pi',
77
+ target: '/root/.pi',
78
+ mode: 'rw',
79
+ create: false,
80
+ })
81
+ })
82
+
83
+ // The adapter writes ~/.pi/pi-acp/session-map.json on every new session;
84
+ // a read-only mount would lose session/load across container restarts.
85
+ it('mounts rw so pi-acp can persist its session map', () => {
86
+ expect(PRESETS.pi.mounts!(ctx)[0].mode).toBe('rw')
87
+ })
88
+
89
+ it('does not reference ctx.agentDataDir', () => {
90
+ for (const m of PRESETS.pi.mounts!(ctx)) {
91
+ expect(m.host).not.toContain('/data/agents/alice')
92
+ }
93
+ })
94
+ })
95
+
70
96
  describe('preset default images (unchanged from cycle 1)', () => {
71
97
  it('claude, codex, opencode declare a default ghcr image', () => {
72
98
  expect(PRESETS.claude.image).toBe('ghcr.io/zooid-ai/agent-claude-code:latest')
@@ -86,6 +86,46 @@ describe('resolvePreset', () => {
86
86
  })
87
87
  })
88
88
 
89
+ describe('pi preset (ZOD073)', () => {
90
+ it('is a known preset', () => {
91
+ expect(isPreset('pi')).toBe(true)
92
+ })
93
+
94
+ it('resolves to the npx-invoked pi-acp adapter with no flags', () => {
95
+ expect(resolvePreset('pi')).toEqual({
96
+ command: 'npx',
97
+ args: ['-y', 'pi-acp'],
98
+ })
99
+ })
100
+
101
+ it('ships the first-party agent-pi image', () => {
102
+ expect(PRESETS.pi.image).toBe('ghcr.io/zooid-ai/agent-pi:latest')
103
+ })
104
+
105
+ it('returns a fresh args array each call', () => {
106
+ const a = resolvePreset('pi')
107
+ const b = resolvePreset('pi')
108
+ expect(a.args).not.toBe(b.args)
109
+ a.args.push('mutated')
110
+ expect(b.args).toEqual(['-y', 'pi-acp'])
111
+ })
112
+
113
+ // ZOD073 Design/"Model selection": pi-acp publishes no --model flag and
114
+ // whether it forwards one to the `pi --mode rpc` child is undocumented, so
115
+ // pi is omitted from MODEL_ARGS_PER_PRESET. This test pins that decision so
116
+ // wiring --model later is a visible change, not a silent one.
117
+ it('ignores opts.model — pi has no verified model flag', () => {
118
+ expect(resolvePreset('pi', { model: 'claude-sonnet-4-6' })).toEqual({
119
+ command: 'npx',
120
+ args: ['-y', 'pi-acp'],
121
+ })
122
+ })
123
+
124
+ it('is listed in the unknown-preset error message', () => {
125
+ expect(() => resolvePreset('made-up')).toThrow(/\bpi\b/)
126
+ })
127
+ })
128
+
89
129
  describe('isPreset', () => {
90
130
  it('returns true for known names', () => {
91
131
  expect(isPreset('claude')).toBe(true)
package/src/presets.ts CHANGED
@@ -102,6 +102,27 @@ const PRESETS_INTERNAL = {
102
102
  },
103
103
  ],
104
104
  },
105
+ // pi (ZOD073). Vendored-shim category: `pi-acp` is an adapter that speaks ACP
106
+ // on pi's behalf and spawns `pi --mode rpc` as a child. No flags — its
107
+ // published Zed config is `args: []`, and the only documented flag
108
+ // (--terminal-login) is an interactive auth path with no place in a daemon.
109
+ pi: {
110
+ command: 'npx',
111
+ args: ['-y', 'pi-acp'],
112
+ image: 'ghcr.io/zooid-ai/agent-pi:latest',
113
+ mounts: (ctx: PresetMountContext): PresetMount[] => [
114
+ {
115
+ // Single tree: agent/sessions, agent/prompts, and the adapter's
116
+ // pi-acp/session-map.json. Project config lives in <cwd>/.pi, which is
117
+ // already inside the workspace mount.
118
+ id: 'home',
119
+ host: `${ctx.daemonHome}/.pi`,
120
+ target: '/root/.pi',
121
+ mode: 'rw',
122
+ create: false,
123
+ },
124
+ ],
125
+ },
105
126
  } as const satisfies Record<string, PresetInternal>
106
127
 
107
128
  export type PresetName = keyof typeof PRESETS_INTERNAL