@zeph-to/cli 2.8.2 → 2.9.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/README.md +6 -1
- package/dist/agents.d.ts.map +1 -1
- package/dist/agents.js +2 -0
- package/dist/installer.d.ts +15 -0
- package/dist/installer.d.ts.map +1 -1
- package/dist/installer.js +79 -17
- package/dist/remote-agents.d.ts +10 -0
- package/dist/remote-agents.d.ts.map +1 -1
- package/dist/remote-agents.js +12 -0
- package/dist/remote-hook.d.ts +1 -1
- package/dist/remote-hook.d.ts.map +1 -1
- package/dist/remote-hook.js +5 -3
- package/dist/templates.d.ts +8 -0
- package/dist/templates.d.ts.map +1 -1
- package/dist/templates.js +87 -2
- package/dist/uninstall.d.ts +4 -0
- package/dist/uninstall.d.ts.map +1 -1
- package/dist/uninstall.js +18 -6
- package/dist/verify.d.ts.map +1 -1
- package/dist/verify.js +2 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -141,12 +141,13 @@ an answerable `zeph_ask`).
|
|
|
141
141
|
| Claude Code | `UserPromptSubmit` → plugin's `zeph-remote.sh` | Zeph plugin |
|
|
142
142
|
| Gemini CLI | `BeforeAgent` → `zeph remote-hook gemini` | `zeph setup` |
|
|
143
143
|
| Codex CLI | `UserPromptSubmit` → `zeph remote-hook codex` | `zeph setup` |
|
|
144
|
+
| Pi | `before_agent_start` → `zeph remote-hook pi` (via extension) | `zeph setup` |
|
|
144
145
|
| Cursor CLI | — none yet | — |
|
|
145
146
|
|
|
146
147
|
Detection is exact-match: a terminal keystroke racing a phone message
|
|
147
148
|
can never false-flag. Muted projects are never flagged.
|
|
148
149
|
|
|
149
|
-
Agents without that hook (Cursor, Windsurf, Copilot, Cline, Aider) have one
|
|
150
|
+
Agents without that hook (Cursor, Windsurf, Copilot, Cline, Aider, OpenCode) have one
|
|
150
151
|
other way in: a `zeph_ask` answer that is not a Done-like button. Their rule
|
|
151
152
|
files therefore keep the after-real-work `zeph_ask` — the "Entering REMOTE
|
|
152
153
|
without a prompt hook" preamble in `src/templates.ts` — so the phone always
|
|
@@ -218,6 +219,8 @@ block here.
|
|
|
218
219
|
zeph cursor # cursor-agent → tmux session "zeph-<project>"
|
|
219
220
|
zeph gemini # gemini → tmux session "zeph-<project>"
|
|
220
221
|
zeph hermes # hermes → tmux session "zeph-<project>"
|
|
222
|
+
zeph pi # pi → tmux session "zeph-<project>"
|
|
223
|
+
zeph opencode # opencode → tmux session "zeph-<project>"
|
|
221
224
|
```
|
|
222
225
|
|
|
223
226
|
`zeph cursor` runs **`cursor-agent`**, Cursor's terminal agent — a
|
|
@@ -712,6 +715,8 @@ try {
|
|
|
712
715
|
| Copilot CLI | Session end hook + rules |
|
|
713
716
|
| Cline | Rules file (`~/.cline/rules/zeph.md`) |
|
|
714
717
|
| Aider | Conventions file + `read:` directive in `~/.aider.conf.yml` |
|
|
718
|
+
| Pi | Extension (settle hook + remote detection) + rules — no MCP (pi has none; rules map zeph tools to the CLI) |
|
|
719
|
+
| OpenCode | MCP server + idle-notify plugin + rules |
|
|
715
720
|
|
|
716
721
|
For remote-control via `zeph listener` the per-agent setup is the same
|
|
717
722
|
across CC/Codex/Gemini — the wrapper just spawns them in a named tmux
|
package/dist/agents.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agents.d.ts","sourceRoot":"","sources":["../src/agents.ts"],"names":[],"mappings":"AASA,MAAM,WAAW,KAAK;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,OAAO,CAAC;CACrB;AAID,eAAO,MAAM,UAAU,GAAI,KAAK,MAAM,KAAG,OAOxC,CAAC;AAEF,eAAO,MAAM,YAAY,QAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"agents.d.ts","sourceRoot":"","sources":["../src/agents.ts"],"names":[],"mappings":"AASA,MAAM,WAAW,KAAK;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,OAAO,CAAC;CACrB;AAID,eAAO,MAAM,UAAU,GAAI,KAAK,MAAM,KAAG,OAOxC,CAAC;AAEF,eAAO,MAAM,YAAY,QAAO,KAAK,EAWpC,CAAC"}
|
package/dist/agents.js
CHANGED
|
@@ -25,5 +25,7 @@ const detectAgents = () => [
|
|
|
25
25
|
{ name: 'Copilot CLI', id: 'copilot', detected: (0, fs_1.existsSync)((0, path_1.join)(HOME, '.copilot')) },
|
|
26
26
|
{ name: 'Cline', id: 'cline', detected: (0, fs_1.existsSync)((0, path_1.join)(HOME, '.cline')) },
|
|
27
27
|
{ name: 'Aider', id: 'aider', detected: (0, exports.hasCommand)('aider') },
|
|
28
|
+
{ name: 'Pi', id: 'pi', detected: (0, fs_1.existsSync)((0, path_1.join)(HOME, '.pi')) || (0, exports.hasCommand)('pi') },
|
|
29
|
+
{ name: 'OpenCode', id: 'opencode', detected: (0, fs_1.existsSync)((0, path_1.join)(HOME, '.config', 'opencode')) || (0, exports.hasCommand)('opencode') },
|
|
28
30
|
];
|
|
29
31
|
exports.detectAgents = detectAgents;
|
package/dist/installer.d.ts
CHANGED
|
@@ -12,6 +12,21 @@ export declare const shouldReauth: (currentKey: string | undefined, relogin: boo
|
|
|
12
12
|
/** Exported for tests (installGemini shells out to the real `gemini` binary,
|
|
13
13
|
* so the merge semantics can't be covered through it deterministically). */
|
|
14
14
|
export declare const mergeJsonFile: (filePath: string, patch: Record<string, unknown>) => void;
|
|
15
|
+
/**
|
|
16
|
+
* opencode.json's own MCP schema — top-level `mcp` key (not `mcpServers`),
|
|
17
|
+
* `command` as ARRAY (binary + args), `type: "local"`. No `environment` —
|
|
18
|
+
* opencode is a terminal app that inherits shell env, and the MCP server
|
|
19
|
+
* falls back to ~/.zeph/config.json anyway (an unexpanded "${ZEPH_API_KEY}"
|
|
20
|
+
* literal would shadow that fallback with junk). Exported for tests (shape pin).
|
|
21
|
+
*/
|
|
22
|
+
export declare const OPENCODE_MCP_ENTRY: {
|
|
23
|
+
type: string;
|
|
24
|
+
command: string[];
|
|
25
|
+
enabled: boolean;
|
|
26
|
+
};
|
|
27
|
+
/** Add the zeph entry under `key` in an MCP registry JSON file, preserving
|
|
28
|
+
* everything else in it. Exported for tests (merge semantics). */
|
|
29
|
+
export declare const injectMcpEntry: (filePath: string, key: string, entry: Record<string, unknown>) => void;
|
|
15
30
|
/**
|
|
16
31
|
* Resolve agents from a non-interactive `--only cursor,gemini` flag.
|
|
17
32
|
* Matches on agent id; unknown ids are silently dropped. Exported for
|
package/dist/installer.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"installer.d.ts","sourceRoot":"","sources":["../src/installer.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"installer.d.ts","sourceRoot":"","sources":["../src/installer.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AA+BzC;;;GAGG;AACH;;;;GAIG;AACH,eAAO,MAAM,YAAY,GAAI,YAAY,MAAM,GAAG,SAAS,EAAE,SAAS,OAAO,KAAG,OACxD,CAAC;AAoBzB;6EAC6E;AAC7E,eAAO,MAAM,aAAa,GAAI,UAAU,MAAM,EAAE,OAAO,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAG,IAqBhF,CAAC;AAgDF;;;;;;GAMG;AACH,eAAO,MAAM,kBAAkB;;;;CAI9B,CAAC;AAEF;mEACmE;AACnE,eAAO,MAAM,cAAc,GAAI,UAAU,MAAM,EAAE,KAAK,MAAM,EAAE,OAAO,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAG,IAQ9F,CAAC;AAqPF;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,GAAI,UAAU,KAAK,EAAE,EAAE,MAAM,MAAM,KAAG,KAAK,EAKxE,CAAC;AA8EF;;;;;;;;;GASG;AACH,eAAO,MAAM,oBAAoB,GAC/B,MAAM,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,EACtC,gBAAgB,OAAO,KACtB,KAAK,GAAG,IAAI,GAAG,KAKjB,CAAC;AAgCF,eAAO,MAAM,aAAa,GAAU,MAAM,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,KAAG,OAAO,CAAC,MAAM,CAuH1F,CAAC"}
|
package/dist/installer.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.handleInstall = exports.serviceInstallChoice = exports.filterAgentsByIds = exports.mergeJsonFile = exports.shouldReauth = void 0;
|
|
3
|
+
exports.handleInstall = exports.serviceInstallChoice = exports.filterAgentsByIds = exports.injectMcpEntry = exports.OPENCODE_MCP_ENTRY = exports.mergeJsonFile = exports.shouldReauth = void 0;
|
|
4
4
|
const child_process_1 = require("child_process");
|
|
5
5
|
const fs_1 = require("fs");
|
|
6
6
|
const os_1 = require("os");
|
|
@@ -104,26 +104,41 @@ const addAiderReadDirective = (confPath, conventionsPath) => {
|
|
|
104
104
|
(0, fs_1.writeFileSync)(confPath, (base ? `${base}\n\n` : '') + line);
|
|
105
105
|
};
|
|
106
106
|
// ── Per-Agent Installers ─────────────────────────────────────────
|
|
107
|
-
|
|
107
|
+
// Pass through env explicitly so the MCP server doesn't have to rely on
|
|
108
|
+
// process-env inheritance (which behaves differently per IDE — Cursor and
|
|
109
|
+
// Windsurf spawn the MCP from a graphical context that may not inherit
|
|
110
|
+
// shell env). Mirrors plugin/.mcp.json.
|
|
111
|
+
const MCP_SERVERS_ENTRY = {
|
|
112
|
+
command: 'npx',
|
|
113
|
+
args: ['-y', '@zeph-to/mcp-server'],
|
|
114
|
+
env: { ZEPH_API_KEY: '${ZEPH_API_KEY}' },
|
|
115
|
+
};
|
|
116
|
+
/**
|
|
117
|
+
* opencode.json's own MCP schema — top-level `mcp` key (not `mcpServers`),
|
|
118
|
+
* `command` as ARRAY (binary + args), `type: "local"`. No `environment` —
|
|
119
|
+
* opencode is a terminal app that inherits shell env, and the MCP server
|
|
120
|
+
* falls back to ~/.zeph/config.json anyway (an unexpanded "${ZEPH_API_KEY}"
|
|
121
|
+
* literal would shadow that fallback with junk). Exported for tests (shape pin).
|
|
122
|
+
*/
|
|
123
|
+
exports.OPENCODE_MCP_ENTRY = {
|
|
124
|
+
type: 'local',
|
|
125
|
+
command: ['npx', '-y', '@zeph-to/mcp-server'],
|
|
126
|
+
enabled: true,
|
|
127
|
+
};
|
|
128
|
+
/** Add the zeph entry under `key` in an MCP registry JSON file, preserving
|
|
129
|
+
* everything else in it. Exported for tests (merge semantics). */
|
|
130
|
+
const injectMcpEntry = (filePath, key, entry) => {
|
|
108
131
|
let data = {};
|
|
109
132
|
try {
|
|
110
133
|
data = JSON.parse((0, fs_1.readFileSync)(filePath, 'utf-8'));
|
|
111
134
|
}
|
|
112
135
|
catch { /* new file */ }
|
|
113
|
-
if (!data
|
|
114
|
-
data
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
// Windsurf spawn the MCP from a graphical context that may not inherit
|
|
118
|
-
// shell env). Mirrors plugin/.mcp.json.
|
|
119
|
-
data.mcpServers.zeph = {
|
|
120
|
-
command: 'npx',
|
|
121
|
-
args: ['-y', '@zeph-to/mcp-server'],
|
|
122
|
-
env: { ZEPH_API_KEY: '${ZEPH_API_KEY}' },
|
|
123
|
-
};
|
|
124
|
-
(0, fs_1.mkdirSync)((0, path_1.dirname)(filePath), { recursive: true });
|
|
125
|
-
(0, fs_1.writeFileSync)(filePath, JSON.stringify(data, null, 2) + '\n');
|
|
136
|
+
if (!isPlainObject(data[key]))
|
|
137
|
+
data[key] = {};
|
|
138
|
+
data[key].zeph = entry;
|
|
139
|
+
writeFile(filePath, JSON.stringify(data, null, 2));
|
|
126
140
|
};
|
|
141
|
+
exports.injectMcpEntry = injectMcpEntry;
|
|
127
142
|
const installClaude = () => {
|
|
128
143
|
try {
|
|
129
144
|
(0, child_process_1.execSync)('claude plugin marketplace add zeph-to/plugin', { stdio: 'pipe' });
|
|
@@ -138,7 +153,7 @@ const installClaude = () => {
|
|
|
138
153
|
};
|
|
139
154
|
const installCursor = () => {
|
|
140
155
|
try {
|
|
141
|
-
|
|
156
|
+
(0, exports.injectMcpEntry)((0, path_1.join)(HOME, '.cursor', 'mcp.json'), 'mcpServers', MCP_SERVERS_ENTRY);
|
|
142
157
|
ok('MCP server added');
|
|
143
158
|
}
|
|
144
159
|
catch {
|
|
@@ -161,7 +176,7 @@ const installCursor = () => {
|
|
|
161
176
|
};
|
|
162
177
|
const installWindsurf = () => {
|
|
163
178
|
try {
|
|
164
|
-
|
|
179
|
+
(0, exports.injectMcpEntry)((0, path_1.join)(HOME, '.codeium', 'windsurf', 'mcp_config.json'), 'mcpServers', MCP_SERVERS_ENTRY);
|
|
165
180
|
ok('MCP server added');
|
|
166
181
|
}
|
|
167
182
|
catch {
|
|
@@ -283,6 +298,49 @@ const installAider = () => {
|
|
|
283
298
|
fail(`Config wiring failed. Manual: add "read: ${conventionsPath}" to ~/.aider.conf.yml`);
|
|
284
299
|
}
|
|
285
300
|
};
|
|
301
|
+
const installPi = () => {
|
|
302
|
+
try {
|
|
303
|
+
// Drop-in auto-load; full-file overwrite is the idempotency model
|
|
304
|
+
// (the header comment is the ownership marker). No MCP — pi has none;
|
|
305
|
+
// PI_RULE maps the zeph_* tools to the CLI instead.
|
|
306
|
+
writeFile((0, path_1.join)(HOME, '.pi', 'agent', 'extensions', 'zeph.ts'), templates_js_1.PI_EXTENSION);
|
|
307
|
+
ok('Extension added (settle notify + remote detection)');
|
|
308
|
+
}
|
|
309
|
+
catch {
|
|
310
|
+
fail('Extension install failed. Manual: save the zeph extension to ~/.pi/agent/extensions/zeph.ts');
|
|
311
|
+
}
|
|
312
|
+
try {
|
|
313
|
+
// Pi loads ~/.pi/agent/AGENTS.md as global context.
|
|
314
|
+
writeManagedRule((0, path_1.join)(HOME, '.pi', 'agent', 'AGENTS.md'), templates_js_1.PI_RULE);
|
|
315
|
+
ok('Rules added to AGENTS.md');
|
|
316
|
+
}
|
|
317
|
+
catch {
|
|
318
|
+
fail('Rule install failed. Manual: add zeph rules to ~/.pi/agent/AGENTS.md');
|
|
319
|
+
}
|
|
320
|
+
};
|
|
321
|
+
const installOpencode = () => {
|
|
322
|
+
try {
|
|
323
|
+
(0, exports.injectMcpEntry)((0, path_1.join)(HOME, '.config', 'opencode', 'opencode.json'), 'mcp', exports.OPENCODE_MCP_ENTRY);
|
|
324
|
+
ok('MCP server added');
|
|
325
|
+
}
|
|
326
|
+
catch {
|
|
327
|
+
fail('MCP injection failed. Manual: add zeph to ~/.config/opencode/opencode.json');
|
|
328
|
+
}
|
|
329
|
+
try {
|
|
330
|
+
writeFile((0, path_1.join)(HOME, '.config', 'opencode', 'plugins', 'zeph.ts'), templates_js_1.OPENCODE_PLUGIN);
|
|
331
|
+
ok('Idle-notify plugin added');
|
|
332
|
+
}
|
|
333
|
+
catch {
|
|
334
|
+
fail('Plugin install failed. Manual: save the zeph plugin to ~/.config/opencode/plugins/zeph.ts');
|
|
335
|
+
}
|
|
336
|
+
try {
|
|
337
|
+
writeManagedRule((0, path_1.join)(HOME, '.config', 'opencode', 'AGENTS.md'), templates_js_1.OPENCODE_RULE);
|
|
338
|
+
ok('Rules added to AGENTS.md');
|
|
339
|
+
}
|
|
340
|
+
catch {
|
|
341
|
+
fail('Rule install failed. Manual: add zeph rules to ~/.config/opencode/AGENTS.md');
|
|
342
|
+
}
|
|
343
|
+
};
|
|
286
344
|
const AGENT_INSTALLERS = {
|
|
287
345
|
claude: installClaude,
|
|
288
346
|
cursor: installCursor,
|
|
@@ -292,6 +350,8 @@ const AGENT_INSTALLERS = {
|
|
|
292
350
|
copilot: installCopilot,
|
|
293
351
|
cline: installCline,
|
|
294
352
|
aider: installAider,
|
|
353
|
+
pi: installPi,
|
|
354
|
+
opencode: installOpencode,
|
|
295
355
|
};
|
|
296
356
|
// One-line summary of what each agent's installer does — shown in the
|
|
297
357
|
// interactive plan before anything is written.
|
|
@@ -304,6 +364,8 @@ const AGENT_PLAN_LABELS = {
|
|
|
304
364
|
copilot: 'Copilot CLI — hooks + rules',
|
|
305
365
|
cline: 'Cline — rules',
|
|
306
366
|
aider: 'Aider — conventions',
|
|
367
|
+
pi: 'Pi — extension + rules',
|
|
368
|
+
opencode: 'OpenCode — MCP + plugin + rules',
|
|
307
369
|
};
|
|
308
370
|
// ── Agent selection ──────────────────────────────────────────────
|
|
309
371
|
/**
|
package/dist/remote-agents.d.ts
CHANGED
|
@@ -186,6 +186,16 @@ declare const REMOTE_AGENT_TABLE: readonly [{
|
|
|
186
186
|
readonly binary: "hermes";
|
|
187
187
|
readonly subcommands: readonly ["hermes"];
|
|
188
188
|
readonly resolveSessionName: (paneCwd: string, panePid?: number, deps?: StoreResolveDeps) => string | null;
|
|
189
|
+
}, {
|
|
190
|
+
readonly kind: "pi";
|
|
191
|
+
readonly displayName: "Pi";
|
|
192
|
+
readonly binary: "pi";
|
|
193
|
+
readonly subcommands: readonly ["pi"];
|
|
194
|
+
}, {
|
|
195
|
+
readonly kind: "opencode";
|
|
196
|
+
readonly displayName: "OpenCode";
|
|
197
|
+
readonly binary: "opencode";
|
|
198
|
+
readonly subcommands: readonly ["opencode"];
|
|
189
199
|
}];
|
|
190
200
|
/** Closed union of remote-controllable agent kinds, derived from the table above. */
|
|
191
201
|
export type AgentKind = (typeof REMOTE_AGENT_TABLE)[number]['kind'];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"remote-agents.d.ts","sourceRoot":"","sources":["../src/remote-agents.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"remote-agents.d.ts","sourceRoot":"","sources":["../src/remote-agents.ts"],"names":[],"mappings":"AAoBA,MAAM,WAAW,WAAW;IACxB,qEAAqE;IACrE,IAAI,EAAE,MAAM,CAAC;IACb,kCAAkC;IAClC,WAAW,EAAE,MAAM,CAAC;IACpB,2EAA2E;IAC3E,MAAM,EAAE,MAAM,CAAC;IACf,0DAA0D;IAC1D,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/B;;;;;;;;;OASG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,2EAA2E;IAC3E,gBAAgB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC;;;;;;OAMG;IACH,gBAAgB,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;IACxE;;;;;;;;;OASG;IACH,kBAAkB,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;CAC7E;AAgFD;;;;;;;GAOG;AACH,eAAO,MAAM,qBAAqB,GAAI,KAAK,MAAM,KAAG,MAAM,GAAG,IAI5D,CAAC;AAaF,MAAM,WAAW,gBAAgB;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,EAAE,MAAM,CAAC;IACZ;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;CACjB;AA4CD,MAAM,WAAW,SAAS;IACtB,qEAAqE;IACrE,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IAChC,6EAA6E;IAC7E,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACnC;AAED;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,cAAc,GAAI,OAAO,MAAM,KAAG,SAe9C,CAAC;AAaF,6EAA6E;AAC7E,eAAO,MAAM,YAAY,QAAO,GAAG,CAAC,MAAM,EAAE,MAAM,CAA8C,CAAC;AA6BjG,sEAAsE;AACtE,eAAO,MAAM,qBAAqB,GAAI,SAAS,MAAM,KAAG,GAAG,CAAC,MAAM,CASjE,CAAC;AAEF,4CAA4C;AAC5C,MAAM,WAAW,cAAc;IAC3B,OAAO,CAAC,EAAE,gBAAgB,EAAE,CAAC;IAC7B,WAAW,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CAC7B;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,wBAAwB,GACjC,SAAS,MAAM,EACf,SAAS,MAAM,GAAG,IAAI,EACtB,OAAM,cAAmB,KAC1B,gBAAgB,GAAG,IAMrB,CAAC;AAEF,eAAO,MAAM,0BAA0B,GACnC,SAAS,MAAM,EACf,SAAS,MAAM,GAAG,IAAI,EACtB,OAAM,cAAmB,KAC1B,MAAM,GAAG,IAA2E,CAAC;AAExF;;;;;GAKG;AACH,eAAO,MAAM,4BAA4B,GACrC,SAAS,MAAM,EACf,SAAS,MAAM,GAAG,IAAI,EACtB,OAAM,cAAmB,KAC1B,MAAM,GAAG,IAAwE,CAAC;AAerF;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,GAAI,CAAC,EAChC,MAAM,SAAS,CAAC,EAAE,EAClB,QAAQ,CAAC,GAAG,EAAE,CAAC,KAAK,MAAM,GAAG,IAAI,EACjC,YAAY,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAC/B,MAAM,GAAG,CAAC,MAAM,CAAC,KAClB,CAAC,GAAG,IAeN,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,UAAU,GAAI,QAAQ,MAAM,EAAE,KAAK,MAAM,KAAG,OAAO,EAAE,GAAG,IAepE,CAAC;AAEF,gFAAgF;AAChF,MAAM,WAAW,gBAAgB;IAC7B,IAAI,CAAC,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IACxB,UAAU,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,WAAW,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CAC7B;AA2BD,eAAO,MAAM,uBAAuB,GAChC,SAAS,MAAM,EACf,UAAU,MAAM,EAChB,OAAM,gBAAqB,KAC5B,MAAM,GAAG,IAkBX,CAAC;AAOF;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,GAAI,SAAS,SAAS,MAAM,EAAE,EAAE,SAAS,MAAM,KAAG,MAAM,GAAG,IASxF,CAAC;AAmCF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,sBAAsB,GAC/B,SAAS,MAAM,EACf,UAAU,MAAM,EAChB,OAAM,gBAAqB,KAC5B,MAAM,GAAG,IAcX,CAAC;AAIF,QAAA,MAAM,kBAAkB;;;;;;;;;;;;;2CArBX,MAAM,YACL,MAAM,SACV,gBAAgB,KACvB,MAAM,GAAG,IAAI;;;;;;;;;;;;;;;;2CA7FH,MAAM,YACL,MAAM,SACV,gBAAgB,KACvB,MAAM,GAAG,IAAI;;;;;;;;;;;EA+K2B,CAAC;AAE5C,qFAAqF;AACrF,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC;AAEpE,8FAA8F;AAC9F,MAAM,MAAM,qBAAqB,GAAG,WAAW,GAAG;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,CAAC;AAEtE,eAAO,MAAM,aAAa,EAAE,SAAS,qBAAqB,EAAuB,CAAC;AAElF,eAAO,MAAM,qBAAqB,GAAI,KAAK,MAAM,KAAG,qBAAqB,GAAG,SAClB,CAAC;AAE3D,eAAO,MAAM,uBAAuB,GAAI,MAAM,MAAM,KAAG,qBAAqB,GAAG,SAG9E,CAAC"}
|
package/dist/remote-agents.js
CHANGED
|
@@ -478,6 +478,18 @@ const REMOTE_AGENT_TABLE = [
|
|
|
478
478
|
// `<timestamp>_<hash>` string, and nothing on the wire consumes it yet.
|
|
479
479
|
resolveSessionName: exports.detectHermesSessionName,
|
|
480
480
|
},
|
|
481
|
+
{
|
|
482
|
+
kind: 'pi',
|
|
483
|
+
displayName: 'Pi',
|
|
484
|
+
binary: 'pi',
|
|
485
|
+
subcommands: ['pi'],
|
|
486
|
+
},
|
|
487
|
+
{
|
|
488
|
+
kind: 'opencode',
|
|
489
|
+
displayName: 'OpenCode',
|
|
490
|
+
binary: 'opencode',
|
|
491
|
+
subcommands: ['opencode'],
|
|
492
|
+
},
|
|
481
493
|
];
|
|
482
494
|
exports.REMOTE_AGENTS = REMOTE_AGENT_TABLE;
|
|
483
495
|
const findAgentBySubcommand = (cmd) => exports.REMOTE_AGENTS.find((a) => a.subcommands.includes(cmd));
|
package/dist/remote-hook.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/** Agents whose prompt-submit hooks this command serves. Claude Code is
|
|
2
2
|
* NOT here — its hook ships with the plugin (hooks/zeph-remote.sh). */
|
|
3
|
-
export declare const REMOTE_HOOK_AGENTS: readonly ["gemini", "codex"];
|
|
3
|
+
export declare const REMOTE_HOOK_AGENTS: readonly ["gemini", "codex", "pi"];
|
|
4
4
|
export type RemoteHookAgent = (typeof REMOTE_HOOK_AGENTS)[number];
|
|
5
5
|
export declare const isRemoteHookAgent: (raw: string) => raw is RemoteHookAgent;
|
|
6
6
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"remote-hook.d.ts","sourceRoot":"","sources":["../src/remote-hook.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"remote-hook.d.ts","sourceRoot":"","sources":["../src/remote-hook.ts"],"names":[],"mappings":"AA0CA;wEACwE;AACxE,eAAO,MAAM,kBAAkB,oCAAqC,CAAC;AACrE,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,CAAC,CAAC;AAqClE,eAAO,MAAM,iBAAiB,GAAI,KAAK,MAAM,KAAG,GAAG,IAAI,eACE,CAAC;AAE1D;;;GAGG;AACH,eAAO,MAAM,aAAa,GACxB,OAAO,eAAe,EACtB,OAAO,MAAM,EACb,MAAK,MAAM,CAAC,UAAwB,EACpC,MAAK,MAAM,MAAiB,KAC3B,MAAM,GAAG,IA0CX,CAAC"}
|
package/dist/remote-hook.js
CHANGED
|
@@ -3,8 +3,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.runRemoteHook = exports.isRemoteHookAgent = exports.REMOTE_HOOK_AGENTS = void 0;
|
|
4
4
|
/**
|
|
5
5
|
* `zeph remote-hook <agent>` — prompt-submit hook handler for agents whose
|
|
6
|
-
* hooks the cli installs directly: Gemini CLI (BeforeAgent)
|
|
7
|
-
* (UserPromptSubmit)
|
|
6
|
+
* hooks the cli installs directly: Gemini CLI (BeforeAgent), Codex CLI
|
|
7
|
+
* (UserPromptSubmit), and Pi (before_agent_start, consumed by the zeph
|
|
8
|
+
* extension itself). TS twin of the Claude Code plugin's
|
|
8
9
|
* hooks/zeph-remote.sh (ADR-0002).
|
|
9
10
|
*
|
|
10
11
|
* The listener records every phone→pane text injection as a one-shot
|
|
@@ -35,12 +36,13 @@ const config_js_1 = require("./config.js");
|
|
|
35
36
|
const gate_js_1 = require("./gate.js");
|
|
36
37
|
/** Agents whose prompt-submit hooks this command serves. Claude Code is
|
|
37
38
|
* NOT here — its hook ships with the plugin (hooks/zeph-remote.sh). */
|
|
38
|
-
exports.REMOTE_HOOK_AGENTS = ['gemini', 'codex'];
|
|
39
|
+
exports.REMOTE_HOOK_AGENTS = ['gemini', 'codex', 'pi'];
|
|
39
40
|
/** Per-agent hookEventName echoed back in hookSpecificOutput — each CLI
|
|
40
41
|
* validates it against the event that invoked the hook. */
|
|
41
42
|
const HOOK_EVENT_NAME = {
|
|
42
43
|
gemini: 'BeforeAgent',
|
|
43
44
|
codex: 'UserPromptSubmit',
|
|
45
|
+
pi: 'before_agent_start',
|
|
44
46
|
};
|
|
45
47
|
/**
|
|
46
48
|
* Freshness window (seconds), same as the bash reader: deliberately
|
package/dist/templates.d.ts
CHANGED
|
@@ -12,6 +12,10 @@ export declare const COPILOT_RULE: string;
|
|
|
12
12
|
export declare const CLINE_RULE: string;
|
|
13
13
|
/** Aider — standalone conventions file via .aider.conf.yml `read:` (no Stop hook, no prompt hook). */
|
|
14
14
|
export declare const AIDER_RULE: string;
|
|
15
|
+
/** Pi — managed block in ~/.pi/agent/AGENTS.md. Extension = Stop-equivalent + prompt hook (PI_EXTENSION). */
|
|
16
|
+
export declare const PI_RULE: string;
|
|
17
|
+
/** OpenCode — managed block in ~/.config/opencode/AGENTS.md. Stop hook via plugin, no prompt hook (v1). */
|
|
18
|
+
export declare const OPENCODE_RULE: string;
|
|
15
19
|
export declare const CURSOR_HOOKS: string;
|
|
16
20
|
export declare const WINDSURF_HOOKS: string;
|
|
17
21
|
export declare const GEMINI_HOOKS: {
|
|
@@ -65,6 +69,10 @@ export declare const CODEX_HOOKS: {
|
|
|
65
69
|
*/
|
|
66
70
|
export declare const isZephHookGroup: (group: unknown) => boolean;
|
|
67
71
|
export declare const COPILOT_HOOKS: string;
|
|
72
|
+
/** Pi extension source — written to ~/.pi/agent/extensions/zeph.ts (drop-in auto-load). */
|
|
73
|
+
export declare const PI_EXTENSION: string;
|
|
74
|
+
/** OpenCode plugin source — written to ~/.config/opencode/plugins/zeph.ts (drop-in auto-load). */
|
|
75
|
+
export declare const OPENCODE_PLUGIN: string;
|
|
68
76
|
export declare const ZEPH_MARK_START = "<!-- ZEPH:START \u2014 managed by @zeph-to/cli, do not edit between markers -->";
|
|
69
77
|
export declare const ZEPH_MARK_END = "<!-- ZEPH:END -->";
|
|
70
78
|
/**
|
package/dist/templates.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"templates.d.ts","sourceRoot":"","sources":["../src/templates.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"templates.d.ts","sourceRoot":"","sources":["../src/templates.ts"],"names":[],"mappings":"AAwJA,6FAA6F;AAC7F,eAAO,MAAM,WAAW,QAKtB,CAAC;AAEH,6FAA6F;AAC7F,eAAO,MAAM,aAAa,QAIxB,CAAC;AAEH,0FAA0F;AAC1F,eAAO,MAAM,WAAW,QAAyE,CAAC;AAElG,uFAAuF;AACvF,eAAO,MAAM,UAAU,QAAyE,CAAC;AAEjG,oGAAoG;AACpG,eAAO,MAAM,YAAY,QAIvB,CAAC;AAEH,gFAAgF;AAChF,eAAO,MAAM,UAAU,QAIrB,CAAC;AAEH,sGAAsG;AACtG,eAAO,MAAM,UAAU,QAIrB,CAAC;AAEH,6GAA6G;AAC7G,eAAO,MAAM,OAAO,QAIlB,CAAC;AAEH,2GAA2G;AAC3G,eAAO,MAAM,aAAa,QAIxB,CAAC;AAIH,eAAO,MAAM,YAAY,QAKd,CAAC;AAEZ,eAAO,MAAM,cAAc,QAOhB,CAAC;AAEZ,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;CAuBxB,CAAC;AAYF,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;CASvB,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,eAAe,GAAI,OAAO,OAAO,KAAG,OAUhD,CAAC;AAEF,eAAO,MAAM,aAAa,QASf,CAAC;AAQZ,2FAA2F;AAC3F,eAAO,MAAM,YAAY,QAmCxB,CAAC;AAEF,kGAAkG;AAClG,eAAO,MAAM,eAAe,QAgB3B,CAAC;AASF,eAAO,MAAM,eAAe,oFAA+E,CAAC;AAC5G,eAAO,MAAM,aAAa,sBAAsB,CAAC;AAQjD;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,GAAI,UAAU,MAAM,EAAE,MAAM,MAAM,KAAG,MAWnE,CAAC;AAEF,uEAAuE;AACvE,eAAO,MAAM,kBAAkB,GAAI,UAAU,MAAM,KAAG,MAOrD,CAAC"}
|
package/dist/templates.js
CHANGED
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
// Keeping this in one place means a rule change lands everywhere at once
|
|
26
26
|
// and the agents can't drift apart.
|
|
27
27
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
28
|
-
exports.removeManagedBlock = exports.upsertManagedBlock = exports.ZEPH_MARK_END = exports.ZEPH_MARK_START = exports.COPILOT_HOOKS = exports.isZephHookGroup = exports.CODEX_HOOKS = exports.GEMINI_HOOKS = exports.WINDSURF_HOOKS = exports.CURSOR_HOOKS = exports.AIDER_RULE = exports.CLINE_RULE = exports.COPILOT_RULE = exports.CODEX_RULE = exports.GEMINI_RULE = exports.WINDSURF_RULE = exports.CURSOR_RULE = void 0;
|
|
28
|
+
exports.removeManagedBlock = exports.upsertManagedBlock = exports.ZEPH_MARK_END = exports.ZEPH_MARK_START = exports.OPENCODE_PLUGIN = exports.PI_EXTENSION = exports.COPILOT_HOOKS = exports.isZephHookGroup = exports.CODEX_HOOKS = exports.GEMINI_HOOKS = exports.WINDSURF_HOOKS = exports.CURSOR_HOOKS = exports.OPENCODE_RULE = exports.PI_RULE = exports.AIDER_RULE = exports.CLINE_RULE = exports.COPILOT_RULE = exports.CODEX_RULE = exports.GEMINI_RULE = exports.WINDSURF_RULE = exports.CURSOR_RULE = void 0;
|
|
29
29
|
const gate_js_1 = require("./gate.js");
|
|
30
30
|
const zeph_core_generated_js_1 = require("./zeph-core.generated.js");
|
|
31
31
|
// Graceful resolution: prefer the installed `zeph` CLI, but fall back to
|
|
@@ -107,9 +107,22 @@ builds, tests, deploys, destructive ops, milestone completions. Skip it on
|
|
|
107
107
|
trivial turns (read-only exploration, a mid-step in an approved plan, a
|
|
108
108
|
typo-sized fix). Once the answer reports \`zephState: "REMOTE"\`, Rule 9
|
|
109
109
|
takes over.`;
|
|
110
|
+
// Tool-access preamble — pi only.
|
|
111
|
+
const PI_TOOL_ACCESS = `## Zeph tools via the CLI (no MCP)
|
|
112
|
+
|
|
113
|
+
Pi has no MCP support, so the zeph_* tools these rules name are not in your
|
|
114
|
+
tool list. Wherever a rule says to call one, run the zeph CLI with your bash
|
|
115
|
+
tool instead — same semantics:
|
|
116
|
+
|
|
117
|
+
- zeph_ask → \`zeph ask --title "…" --body "…" --actions "id:Label,id2:Label2" --timeout 300\`
|
|
118
|
+
Blocks until answered; prints one JSON line. \`answered: false\` (timeout /
|
|
119
|
+
unreachable) is a Done-like outcome — treat it as NORMAL.
|
|
120
|
+
- zeph_notify → \`zeph notify --title "…" --body "…" [--priority high]\`
|
|
121
|
+
- AskUserQuestion → pi's own terminal prompt.`;
|
|
110
122
|
/** Assemble a full rule document from optional frontmatter + preambles + core. */
|
|
111
123
|
const buildRule = (opts) => {
|
|
112
124
|
const fm = opts.frontmatter ? `${opts.frontmatter}\n\n` : '';
|
|
125
|
+
const tools = opts.toolAccess ? `${opts.toolAccess}\n\n` : '';
|
|
113
126
|
const entry = opts.remoteEntry ? `${opts.remoteEntry}\n\n` : '';
|
|
114
127
|
return `${fm}# Zeph — Remote-Control Rules
|
|
115
128
|
|
|
@@ -119,7 +132,7 @@ the user.
|
|
|
119
132
|
|
|
120
133
|
${opts.notify}
|
|
121
134
|
|
|
122
|
-
${entry}${opts.core}
|
|
135
|
+
${tools}${entry}${opts.core}
|
|
123
136
|
`;
|
|
124
137
|
};
|
|
125
138
|
// ── Per-agent rule documents ─────────────────────────────────────
|
|
@@ -162,6 +175,18 @@ exports.AIDER_RULE = buildRule({
|
|
|
162
175
|
remoteEntry: REMOTE_ENTRY_NO_HOOK,
|
|
163
176
|
core: zeph_core_generated_js_1.ZEPH_CORE_RULE_ONLY,
|
|
164
177
|
});
|
|
178
|
+
/** Pi — managed block in ~/.pi/agent/AGENTS.md. Extension = Stop-equivalent + prompt hook (PI_EXTENSION). */
|
|
179
|
+
exports.PI_RULE = buildRule({
|
|
180
|
+
notify: HOOK_DRIVEN_NOTIFY,
|
|
181
|
+
toolAccess: PI_TOOL_ACCESS,
|
|
182
|
+
core: zeph_core_generated_js_1.ZEPH_CORE_HOOK_DRIVEN,
|
|
183
|
+
});
|
|
184
|
+
/** OpenCode — managed block in ~/.config/opencode/AGENTS.md. Stop hook via plugin, no prompt hook (v1). */
|
|
185
|
+
exports.OPENCODE_RULE = buildRule({
|
|
186
|
+
notify: HOOK_DRIVEN_NOTIFY,
|
|
187
|
+
remoteEntry: REMOTE_ENTRY_NO_HOOK,
|
|
188
|
+
core: zeph_core_generated_js_1.ZEPH_CORE_HOOK_DRIVEN,
|
|
189
|
+
});
|
|
165
190
|
// ── Hook configs ─────────────────────────────────────────────────
|
|
166
191
|
exports.CURSOR_HOOKS = JSON.stringify({
|
|
167
192
|
version: 1,
|
|
@@ -250,6 +275,66 @@ exports.COPILOT_HOOKS = JSON.stringify({
|
|
|
250
275
|
}],
|
|
251
276
|
},
|
|
252
277
|
}, null, 2);
|
|
278
|
+
// ── Drop-in artifact sources (pi extension, opencode plugin) ─────
|
|
279
|
+
//
|
|
280
|
+
// Not named *_HOOKS: those exports are JSON configs that templates.test.ts
|
|
281
|
+
// JSON.parses — these are TS source, auto-collected there as *_EXTENSION /
|
|
282
|
+
// *_PLUGIN for the same quiet-default guard, at the string level.
|
|
283
|
+
/** Pi extension source — written to ~/.pi/agent/extensions/zeph.ts (drop-in auto-load). */
|
|
284
|
+
exports.PI_EXTENSION = `// Generated by @zeph-to/cli — reinstall overwrites; \`zeph uninstall\` removes.
|
|
285
|
+
import { spawn } from "node:child_process";
|
|
286
|
+
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
287
|
+
|
|
288
|
+
const sh = (cmd: string, cwd: string, stdin?: string): Promise<string> =>
|
|
289
|
+
new Promise((resolve) => {
|
|
290
|
+
const child = spawn("sh", ["-c", cmd], { cwd, stdio: ["pipe", "pipe", "ignore"] });
|
|
291
|
+
let out = "";
|
|
292
|
+
child.stdout.on("data", (d) => (out += d.toString()));
|
|
293
|
+
child.on("error", () => resolve(""));
|
|
294
|
+
child.on("close", () => resolve(out));
|
|
295
|
+
child.stdin.end(stdin ?? "");
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
export default function (pi: ExtensionAPI) {
|
|
299
|
+
// Stop-equivalent: agent_settled fires once per user turn, after retries/compaction.
|
|
300
|
+
// Fire-and-forget: never block pi's turn-end on the notify network call.
|
|
301
|
+
pi.on("agent_settled", (_event, ctx) => {
|
|
302
|
+
const child = spawn("sh", ["-c", ${JSON.stringify(NOTIFY_CMD)}], { cwd: ctx.cwd, stdio: "ignore", detached: true });
|
|
303
|
+
child.on("error", () => {});
|
|
304
|
+
child.unref();
|
|
305
|
+
});
|
|
306
|
+
// Prompt-submit: remote-origin detection (ADR-0002) — additionalContext comes
|
|
307
|
+
// back as a persistent injected message (this extension is the consumer).
|
|
308
|
+
pi.on("before_agent_start", async (event, ctx) => {
|
|
309
|
+
const out = await sh(${JSON.stringify(remoteHookCmd('pi'))}, ctx.cwd,
|
|
310
|
+
JSON.stringify({ prompt: event.prompt, cwd: ctx.cwd }));
|
|
311
|
+
try {
|
|
312
|
+
const context = JSON.parse(out)?.hookSpecificOutput?.additionalContext;
|
|
313
|
+
if (typeof context === "string" && context) {
|
|
314
|
+
return { message: { customType: "zeph-remote", content: context, display: false } };
|
|
315
|
+
}
|
|
316
|
+
} catch { /* silent no-op — the hook only ever adds context */ }
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
`;
|
|
320
|
+
/** OpenCode plugin source — written to ~/.config/opencode/plugins/zeph.ts (drop-in auto-load). */
|
|
321
|
+
exports.OPENCODE_PLUGIN = `// Generated by @zeph-to/cli — reinstall overwrites; \`zeph uninstall\` removes.
|
|
322
|
+
import { spawn } from "node:child_process";
|
|
323
|
+
|
|
324
|
+
const NOTIFY = ${JSON.stringify(NOTIFY_CMD)};
|
|
325
|
+
|
|
326
|
+
export const ZephPlugin = async ({ directory }) => ({
|
|
327
|
+
// Stop-equivalent: the installed plugin API exposes one generic event hook
|
|
328
|
+
// (no per-event keys) — filter for "session.idle", the end-of-turn signal.
|
|
329
|
+
event: async ({ event }) => {
|
|
330
|
+
if (event.type !== "session.idle") return;
|
|
331
|
+
// Fire-and-forget: never block opencode's event pipeline on the notify call.
|
|
332
|
+
const child = spawn("sh", ["-c", NOTIFY], { cwd: directory, stdio: "ignore", detached: true });
|
|
333
|
+
child.on("error", () => {});
|
|
334
|
+
child.unref();
|
|
335
|
+
},
|
|
336
|
+
});
|
|
337
|
+
`;
|
|
253
338
|
// ── Marker-section helpers for shared global rule files ──────────
|
|
254
339
|
//
|
|
255
340
|
// Windsurf / Gemini / Codex all use a single shared global rule file
|
package/dist/uninstall.d.ts
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
/** Remove just the `zeph` entry from an MCP registry JSON file. `key` is the
|
|
2
|
+
* container: `mcpServers` for Cursor/Windsurf, top-level `mcp` for
|
|
3
|
+
* opencode.json (opencode's own schema). Exported for tests. */
|
|
4
|
+
export declare const rmMcpEntry: (filePath: string, dry: boolean, key?: string) => string | null;
|
|
1
5
|
/** Remove just the zeph-written entries from Gemini's settings.json.
|
|
2
6
|
* Exported for tests (gemini is PATH-detected, so the full-uninstall
|
|
3
7
|
* suite can't reach this deterministically). */
|
package/dist/uninstall.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"uninstall.d.ts","sourceRoot":"","sources":["../src/uninstall.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"uninstall.d.ts","sourceRoot":"","sources":["../src/uninstall.ts"],"names":[],"mappings":"AA4BA;;iEAEiE;AACjE,eAAO,MAAM,UAAU,GAAI,UAAU,MAAM,EAAE,KAAK,OAAO,EAAE,YAAkB,KAAG,MAAM,GAAG,IAexF,CAAC;AA4DF;;iDAEiD;AACjD,eAAO,MAAM,YAAY,GAAI,UAAU,MAAM,EAAE,KAAK,OAAO,KAAG,MAAM,GAAG,IAWtE,CAAC;AAEF;;;gDAGgD;AAChD,eAAO,MAAM,WAAW,GAAI,UAAU,MAAM,EAAE,KAAK,OAAO,KAAG,MAAM,GAAG,IAerE,CAAC;AA8EF;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB,GAAU,KAAK,OAAO,KAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAM3E,CAAC;AAIF,eAAO,MAAM,eAAe,GAAU,MAAM,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,KAAG,OAAO,CAAC,MAAM,CAoC5F,CAAC"}
|
package/dist/uninstall.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.handleUninstall = exports.removeServiceStep = exports.rmCodexHook = exports.rmGeminiHook = void 0;
|
|
3
|
+
exports.handleUninstall = exports.removeServiceStep = exports.rmCodexHook = exports.rmGeminiHook = exports.rmMcpEntry = void 0;
|
|
4
4
|
const child_process_1 = require("child_process");
|
|
5
5
|
const fs_1 = require("fs");
|
|
6
6
|
const os_1 = require("os");
|
|
@@ -25,8 +25,10 @@ const rmFile = (filePath, dry) => {
|
|
|
25
25
|
(0, fs_1.rmSync)(filePath, { force: true });
|
|
26
26
|
return `${verb(dry)} ${filePath}`;
|
|
27
27
|
};
|
|
28
|
-
/** Remove just the `zeph` entry from an
|
|
29
|
-
|
|
28
|
+
/** Remove just the `zeph` entry from an MCP registry JSON file. `key` is the
|
|
29
|
+
* container: `mcpServers` for Cursor/Windsurf, top-level `mcp` for
|
|
30
|
+
* opencode.json (opencode's own schema). Exported for tests. */
|
|
31
|
+
const rmMcpEntry = (filePath, dry, key = 'mcpServers') => {
|
|
30
32
|
if (!(0, fs_1.existsSync)(filePath))
|
|
31
33
|
return null;
|
|
32
34
|
let data;
|
|
@@ -36,7 +38,7 @@ const rmMcpEntry = (filePath, dry) => {
|
|
|
36
38
|
catch {
|
|
37
39
|
return null;
|
|
38
40
|
}
|
|
39
|
-
const servers = data
|
|
41
|
+
const servers = data[key];
|
|
40
42
|
if (!servers || !('zeph' in servers))
|
|
41
43
|
return null;
|
|
42
44
|
if (!dry) {
|
|
@@ -45,6 +47,7 @@ const rmMcpEntry = (filePath, dry) => {
|
|
|
45
47
|
}
|
|
46
48
|
return `${verb(dry)} zeph from ${filePath}`;
|
|
47
49
|
};
|
|
50
|
+
exports.rmMcpEntry = rmMcpEntry;
|
|
48
51
|
/** Strip the <!-- ZEPH:START/END --> block from a shared rule file. */
|
|
49
52
|
const stripManagedRule = (filePath, dry) => {
|
|
50
53
|
if (!(0, fs_1.existsSync)(filePath))
|
|
@@ -185,12 +188,12 @@ const AGENT_UNINSTALLERS = {
|
|
|
185
188
|
}
|
|
186
189
|
},
|
|
187
190
|
cursor: (dry) => runSteps([
|
|
188
|
-
() => rmMcpEntry((0, path_1.join)(HOME, '.cursor', 'mcp.json'), dry),
|
|
191
|
+
() => (0, exports.rmMcpEntry)((0, path_1.join)(HOME, '.cursor', 'mcp.json'), dry),
|
|
189
192
|
() => rmFile((0, path_1.join)(HOME, '.cursor', 'hooks.json'), dry),
|
|
190
193
|
() => rmFile((0, path_1.join)(HOME, '.cursor', 'rules', 'zeph.mdc'), dry),
|
|
191
194
|
]),
|
|
192
195
|
windsurf: (dry) => runSteps([
|
|
193
|
-
() => rmMcpEntry((0, path_1.join)(HOME, '.codeium', 'windsurf', 'mcp_config.json'), dry),
|
|
196
|
+
() => (0, exports.rmMcpEntry)((0, path_1.join)(HOME, '.codeium', 'windsurf', 'mcp_config.json'), dry),
|
|
194
197
|
() => rmFile((0, path_1.join)(HOME, '.codeium', 'windsurf', 'hooks.json'), dry),
|
|
195
198
|
() => stripManagedRule((0, path_1.join)(HOME, '.codeium', 'windsurf', 'memories', 'global_rules.md'), dry),
|
|
196
199
|
]),
|
|
@@ -235,6 +238,15 @@ const AGENT_UNINSTALLERS = {
|
|
|
235
238
|
() => rmFile((0, path_1.join)(HOME, '.zeph', 'aider-conventions.md'), dry),
|
|
236
239
|
() => rmAiderReadDirective((0, path_1.join)(HOME, '.aider.conf.yml'), dry),
|
|
237
240
|
]),
|
|
241
|
+
pi: (dry) => runSteps([
|
|
242
|
+
() => rmFile((0, path_1.join)(HOME, '.pi', 'agent', 'extensions', 'zeph.ts'), dry),
|
|
243
|
+
() => stripManagedRule((0, path_1.join)(HOME, '.pi', 'agent', 'AGENTS.md'), dry),
|
|
244
|
+
]),
|
|
245
|
+
opencode: (dry) => runSteps([
|
|
246
|
+
() => (0, exports.rmMcpEntry)((0, path_1.join)(HOME, '.config', 'opencode', 'opencode.json'), dry, 'mcp'),
|
|
247
|
+
() => rmFile((0, path_1.join)(HOME, '.config', 'opencode', 'plugins', 'zeph.ts'), dry),
|
|
248
|
+
() => stripManagedRule((0, path_1.join)(HOME, '.config', 'opencode', 'AGENTS.md'), dry),
|
|
249
|
+
]),
|
|
238
250
|
};
|
|
239
251
|
/**
|
|
240
252
|
* Remove the login-time LaunchAgent, if one is installed.
|
package/dist/verify.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"verify.d.ts","sourceRoot":"","sources":["../src/verify.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"verify.d.ts","sourceRoot":"","sources":["../src/verify.ts"],"names":[],"mappings":"AA4CA,eAAO,MAAM,YAAY,GAAU,MAAM,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,KAAG,OAAO,CAAC,MAAM,CAiFzF,CAAC"}
|
package/dist/verify.js
CHANGED
|
@@ -38,6 +38,8 @@ const AGENT_RULE_PRESENT = {
|
|
|
38
38
|
copilot: () => (0, fs_1.existsSync)((0, path_1.join)(HOME, '.copilot', 'instructions', 'zeph.instructions.md')),
|
|
39
39
|
cline: () => (0, fs_1.existsSync)((0, path_1.join)(HOME, '.cline', 'rules', 'zeph.md')),
|
|
40
40
|
aider: () => (0, fs_1.existsSync)((0, path_1.join)(HOME, '.zeph', 'aider-conventions.md')),
|
|
41
|
+
pi: () => hasManagedBlock((0, path_1.join)(HOME, '.pi', 'agent', 'AGENTS.md')),
|
|
42
|
+
opencode: () => hasManagedBlock((0, path_1.join)(HOME, '.config', 'opencode', 'AGENTS.md')),
|
|
41
43
|
};
|
|
42
44
|
const handleVerify = async (args) => {
|
|
43
45
|
const doPing = args.ping === true;
|