@zeph-to/cli 2.17.1 → 2.19.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 +8 -0
- package/dist/listener.d.ts +39 -1
- package/dist/listener.d.ts.map +1 -1
- package/dist/listener.js +283 -49
- package/dist/remote-agents.d.ts +32 -0
- package/dist/remote-agents.d.ts.map +1 -1
- package/dist/remote-agents.js +66 -11
- package/dist/templates.d.ts.map +1 -1
- package/dist/templates.js +27 -2
- package/dist/zeph-hook.d.ts.map +1 -1
- package/dist/zeph-hook.js +6 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -146,6 +146,14 @@ an answerable `zeph_ask`).
|
|
|
146
146
|
| Pi | `before_agent_start` → `zeph remote-hook pi` (via extension) | `zeph setup` |
|
|
147
147
|
| Cursor CLI | — none yet | — |
|
|
148
148
|
|
|
149
|
+
**Subagents (view-only).** A pi subagent spawned into an extra pane of the
|
|
150
|
+
same tmux window shows up on your phone as a child of its parent card, named
|
|
151
|
+
`<session>.<pane>` — its terminal mirror streams live, but input, keys, exit,
|
|
152
|
+
resume and forget are all refused: you watch from the phone and answer at the
|
|
153
|
+
terminal, where the parent owns the conversation. The pane is labelled from
|
|
154
|
+
`@zeph_pane_label` (the pi extension sets it from `PI_SUBAGENT_NAME`), and a
|
|
155
|
+
prompt push from a subagent names it and opens its stream directly.
|
|
156
|
+
|
|
149
157
|
Detection is exact-match: a terminal keystroke racing a phone message
|
|
150
158
|
can never false-flag. Muted projects are never flagged.
|
|
151
159
|
|
package/dist/listener.d.ts
CHANGED
|
@@ -29,6 +29,11 @@ interface AgentSession {
|
|
|
29
29
|
name: string;
|
|
30
30
|
attached: boolean;
|
|
31
31
|
agentKind: AgentKind;
|
|
32
|
+
/** Set when this session is a SUBAGENT — an extra pane of the parent
|
|
33
|
+
* session `parentName` (`zeph-zeph.48` belongs to `zeph-zeph`). Subagent
|
|
34
|
+
* sessions are view-only: input, keys, exit, resume and forget are
|
|
35
|
+
* refused, and the server never pushes agent.state transitions for them. */
|
|
36
|
+
parentName?: string;
|
|
32
37
|
agentSessionId?: string | null;
|
|
33
38
|
project: string;
|
|
34
39
|
label?: string | null;
|
|
@@ -105,7 +110,15 @@ export declare const sessionsFingerprint: (sessions: AgentSession[]) => string;
|
|
|
105
110
|
export declare const sessionsReportDue: (fingerprint: string, lastSentFingerprint: string | null, lastSentAtMs: number, nowMs: number) => boolean;
|
|
106
111
|
export declare const AUTH_FAILURE_CODES: ReadonlySet<number>;
|
|
107
112
|
export declare const checkRateLimit: (session: string, now?: number, cost?: number) => boolean;
|
|
108
|
-
/**
|
|
113
|
+
/**
|
|
114
|
+
* Read the foreground command on the named session's PINNED pane, verifying
|
|
115
|
+
* the pane still belongs to that session. A pane id is stable across restarts
|
|
116
|
+
* only within one tmux server: after a restart the same `%N` can name a pane
|
|
117
|
+
* in a different session, and typing into that pane would be RCE into someone
|
|
118
|
+
* else's shell. The owning session rides along in the same display-message —
|
|
119
|
+
* one spawn, no second probe — and a mismatch answers null ("no such
|
|
120
|
+
* session"), which refuses the inject until the next sweep re-pins.
|
|
121
|
+
*/
|
|
109
122
|
export declare const paneCurrentCommand: (session: string) => string | null;
|
|
110
123
|
/**
|
|
111
124
|
* Translate a phone-supplied key list to tmux tokens. Returns null if ANY
|
|
@@ -140,6 +153,27 @@ interface PaneInfo {
|
|
|
140
153
|
currentPath: string | null;
|
|
141
154
|
panePid: number | null;
|
|
142
155
|
}
|
|
156
|
+
/**
|
|
157
|
+
* A subagent session name: `<session>.<pane id digits>` (`zeph-zeph.48`).
|
|
158
|
+
* tmux forbids `.` in session names, so the shape cannot collide; `#` would
|
|
159
|
+
* break the server's stream-sub keys and `:` is the web key separator.
|
|
160
|
+
*/
|
|
161
|
+
export declare const isSubagentSessionName: (name: string) => boolean;
|
|
162
|
+
/** Store the latest sweep's name → pane-id map (see `CollectResult.targets`). */
|
|
163
|
+
export declare const recordTargets: (targets: Record<string, string> | null | undefined) => void;
|
|
164
|
+
/**
|
|
165
|
+
* The tmux target for a wire session name: its pinned pane id when the last
|
|
166
|
+
* sweep saw the session, else the name itself (a session younger than one
|
|
167
|
+
* sweep, or tmux unreachable at startup — today's resolution, active pane).
|
|
168
|
+
*
|
|
169
|
+
* A SUBAGENT name is the one exception: it resolves ONLY through the map, and
|
|
170
|
+
* an unknown one is null — because tmux parses `zeph-zeph.48` as session
|
|
171
|
+
* `zeph-zeph`, pane INDEX 48, and silently falls back to the active pane when
|
|
172
|
+
* that index is missing (measured: `display -t zeph-zeph.99` → main pane,
|
|
173
|
+
* exit 0). Every caller treats null as "gone": no spawn, refusal, or capture
|
|
174
|
+
* failure — never a write to whichever pane happens to be focused.
|
|
175
|
+
*/
|
|
176
|
+
export declare const tmuxTargetFor: (name: string) => string | null;
|
|
143
177
|
/**
|
|
144
178
|
* Identify the agent from the tmux pane. Prefer `pane_start_command`
|
|
145
179
|
* because the foreground process is usually `node`/`python3` (the
|
|
@@ -690,6 +724,10 @@ export interface CollectResult {
|
|
|
690
724
|
name: string;
|
|
691
725
|
reason: string;
|
|
692
726
|
}>;
|
|
727
|
+
/** Local knowledge, NOT on the wire: every live session/subagent name →
|
|
728
|
+
* the pane id every `-t` call for it must use (`tmuxTargetFor`). The main
|
|
729
|
+
* thread stores it beside the snapshot (`recordTargets`). */
|
|
730
|
+
targets: Record<string, string>;
|
|
693
731
|
}
|
|
694
732
|
/**
|
|
695
733
|
* Inventory pass that also records *why* each `zeph-*` session was
|
package/dist/listener.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"listener.d.ts","sourceRoot":"","sources":["../src/listener.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"listener.d.ts","sourceRoot":"","sources":["../src/listener.ts"],"names":[],"mappings":"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"}
|
package/dist/listener.js
CHANGED
|
@@ -25,8 +25,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
25
25
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
26
26
|
};
|
|
27
27
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
28
|
-
exports.
|
|
29
|
-
exports.handleListener = exports.resolveWsUrl = exports.computeListenerDeviceId = exports.computeBackoff = exports.handlePush = exports.gcAttachments = exports.setAttachmentContext = exports.writeRemoteMarker = exports.isInventoried = exports.syncTmuxAgentNames = exports.recordInventory = exports.collectSessionsVerbose = exports.handleCommandInput = exports.pendingInputDecrypts = exports.MAX_PENDING_DECRYPTS = exports.MAX_INPUT_LANES = exports.validateInputMessage = void 0;
|
|
28
|
+
exports.buildStreamFrame = exports.isStreamCapReached = exports.stopAllStreams = exports.stopStream = exports.MAX_CONCURRENT_STREAMS = exports.STREAM_RENEW_FRESH_MS = exports.STREAM_LEASE_MS = exports.claimFrameSend = exports.hasFrameBudget = exports.streamCadence = exports.MAX_FRAMES_PER_SEC = exports.BURST_WINDOW_MS = exports.BURST_INTERVAL_MS = exports.STREAM_INTERVAL_MS = exports.STREAM_CAPTURE_LINES = exports.scheduleInjectSnapshots = exports.historyLinesIn = exports.cursorLineFor = exports.parsePaneGeometry = exports.handleScreenHistoryRequest = exports.SCREEN_HISTORY_MAX_LINES = exports.handleSessionForgetRequest = exports.handleSessionExitRequest = exports.SESSION_EXIT_STEP_MS = exports.handleSessionResumeRequest = exports.handleDiffFileRequest = exports.handleDiffFilesRequest = exports.DIFF_PAGE_MAX_BYTES = exports.handleScreenRequest = exports.collectWatchHits = exports.resetPatternWatches = exports.setPatternWatches = exports.deriveSessionState = exports.resetSessionStates = exports.detectRemoteAgent = exports.tmuxTargetFor = exports.recordTargets = exports.isSubagentSessionName = exports.parseSessionName = exports.invalidateTmuxSocketCache = exports.resolveKeys = exports.paneCurrentCommand = exports.checkRateLimit = exports.AUTH_FAILURE_CODES = exports.sessionsReportDue = exports.sessionsFingerprint = exports.knownSessionsFingerprint = exports.knownSessionsToReport = exports.KNOWN_SESSIONS_REPORTED = exports.SESSION_REPORT_HEARTBEAT_MS = void 0;
|
|
29
|
+
exports.handleListener = exports.resolveWsUrl = exports.computeListenerDeviceId = exports.computeBackoff = exports.handlePush = exports.gcAttachments = exports.setAttachmentContext = exports.writeRemoteMarker = exports.isInventoried = exports.syncTmuxAgentNames = exports.recordInventory = exports.collectSessionsVerbose = exports.handleCommandInput = exports.pendingInputDecrypts = exports.MAX_PENDING_DECRYPTS = exports.MAX_INPUT_LANES = exports.validateInputMessage = exports.MAX_INPUT_BODY_CHARS = exports.MAX_INPUT_KEYS = exports.handleStreamControl = void 0;
|
|
30
30
|
const child_process_1 = require("child_process");
|
|
31
31
|
const crypto_1 = require("crypto");
|
|
32
32
|
const fs_1 = require("fs");
|
|
@@ -185,15 +185,30 @@ const checkRateLimit = (session, now = Date.now(), cost = 1) => {
|
|
|
185
185
|
return true;
|
|
186
186
|
};
|
|
187
187
|
exports.checkRateLimit = checkRateLimit;
|
|
188
|
-
/**
|
|
188
|
+
/**
|
|
189
|
+
* Read the foreground command on the named session's PINNED pane, verifying
|
|
190
|
+
* the pane still belongs to that session. A pane id is stable across restarts
|
|
191
|
+
* only within one tmux server: after a restart the same `%N` can name a pane
|
|
192
|
+
* in a different session, and typing into that pane would be RCE into someone
|
|
193
|
+
* else's shell. The owning session rides along in the same display-message —
|
|
194
|
+
* one spawn, no second probe — and a mismatch answers null ("no such
|
|
195
|
+
* session"), which refuses the inject until the next sweep re-pins.
|
|
196
|
+
*/
|
|
189
197
|
const paneCurrentCommand = (session) => {
|
|
190
|
-
const
|
|
198
|
+
const target = (0, exports.tmuxTargetFor)(session);
|
|
199
|
+
if (target === null)
|
|
200
|
+
return null; // unresolvable subagent — never spawn
|
|
201
|
+
const result = (0, child_process_1.spawnSync)('tmux', tmuxArgs(['display-message', '-p', '-t', target,
|
|
202
|
+
`#{pane_current_command}${FIELD_SEP}#{session_name}`]), {
|
|
191
203
|
encoding: 'utf-8',
|
|
192
204
|
stdio: ['ignore', 'pipe', 'ignore'],
|
|
193
205
|
});
|
|
194
206
|
if (result.status !== 0)
|
|
195
207
|
return null;
|
|
196
|
-
|
|
208
|
+
const parts = (result.stdout ?? '').trim().split(FIELD_SEP);
|
|
209
|
+
if (parts.length !== 2 || parts[1] !== session)
|
|
210
|
+
return null;
|
|
211
|
+
return parts[0] || null;
|
|
197
212
|
};
|
|
198
213
|
exports.paneCurrentCommand = paneCurrentCommand;
|
|
199
214
|
const isShellPane = (command) => {
|
|
@@ -205,8 +220,13 @@ const isShellPane = (command) => {
|
|
|
205
220
|
* so the user's own paste stack is never pushed onto, and `-d` drops it
|
|
206
221
|
* again the moment it has been delivered. */
|
|
207
222
|
const INJECT_BUFFER = 'zeph-inject';
|
|
208
|
-
const sendLiteral = (session, text) =>
|
|
209
|
-
|
|
223
|
+
const sendLiteral = (session, text) => {
|
|
224
|
+
const target = (0, exports.tmuxTargetFor)(session);
|
|
225
|
+
if (target === null)
|
|
226
|
+
return false; // unresolvable subagent — never spawn
|
|
227
|
+
return (0, child_process_1.spawnSync)('tmux', tmuxArgs(['send-keys', '-l', '-t', target, text]), { stdio: ['ignore', 'ignore', 'pipe'] })
|
|
228
|
+
.status === 0;
|
|
229
|
+
};
|
|
210
230
|
/**
|
|
211
231
|
* Put the message in the pane as a PASTE rather than as typing.
|
|
212
232
|
*
|
|
@@ -233,7 +253,10 @@ const pasteText = (session, text) => {
|
|
|
233
253
|
const set = (0, child_process_1.spawnSync)('tmux', tmuxArgs(['set-buffer', '-b', INJECT_BUFFER, '--', text]), { stdio: ['ignore', 'ignore', 'pipe'] });
|
|
234
254
|
if (set.status !== 0)
|
|
235
255
|
return sendLiteral(session, text);
|
|
236
|
-
const
|
|
256
|
+
const pasteTarget = (0, exports.tmuxTargetFor)(session);
|
|
257
|
+
if (pasteTarget === null)
|
|
258
|
+
return false; // unresolvable subagent — never spawn
|
|
259
|
+
const paste = (0, child_process_1.spawnSync)('tmux', tmuxArgs(['paste-buffer', '-d', '-p', '-b', INJECT_BUFFER, '-t', pasteTarget]), { stdio: ['ignore', 'ignore', 'pipe'] });
|
|
237
260
|
if (paste.status === 0)
|
|
238
261
|
return true;
|
|
239
262
|
// `-d` never ran, so the buffer is still there holding the message.
|
|
@@ -252,7 +275,10 @@ const pasteText = (session, text) => {
|
|
|
252
275
|
const injectKeys = (session, text) => {
|
|
253
276
|
if (!pasteText(session, text))
|
|
254
277
|
return false;
|
|
255
|
-
const
|
|
278
|
+
const enterTarget = (0, exports.tmuxTargetFor)(session);
|
|
279
|
+
if (enterTarget === null)
|
|
280
|
+
return false; // unresolvable subagent — never spawn
|
|
281
|
+
const b = (0, child_process_1.spawnSync)('tmux', tmuxArgs(['send-keys', '-t', enterTarget, 'Enter']), { stdio: ['ignore', 'ignore', 'pipe'] });
|
|
256
282
|
return b.status === 0;
|
|
257
283
|
};
|
|
258
284
|
// Named keys the phone may inject to drive a full-screen Claude Code pane
|
|
@@ -310,7 +336,10 @@ exports.resolveKeys = resolveKeys;
|
|
|
310
336
|
* whole sequence in order.
|
|
311
337
|
*/
|
|
312
338
|
const injectNamedKeys = (session, tokens) => {
|
|
313
|
-
const
|
|
339
|
+
const target = (0, exports.tmuxTargetFor)(session);
|
|
340
|
+
if (target === null)
|
|
341
|
+
return false; // unresolvable subagent — never spawn
|
|
342
|
+
const r = (0, child_process_1.spawnSync)('tmux', tmuxArgs(['send-keys', '-t', target, ...tokens]), { stdio: ['ignore', 'ignore', 'pipe'] });
|
|
314
343
|
return r.status === 0;
|
|
315
344
|
};
|
|
316
345
|
const stamp = () => new Date().toISOString().slice(11, 19);
|
|
@@ -603,8 +632,51 @@ exports.parseSessionName = parseSessionName;
|
|
|
603
632
|
// arrived at the consumer end. A printable Unicode char passes through
|
|
604
633
|
// verbatim and won't appear in any real session name or filesystem path.
|
|
605
634
|
const FIELD_SEP = '␟';
|
|
635
|
+
// ─── Pane targets ───────────────────────────────────────────────────
|
|
636
|
+
// A bare `-t <session>` resolves to whichever pane has FOCUS, so the moment a
|
|
637
|
+
// second pane exists in a `zeph-*` session (pi-interactive-subagents splits
|
|
638
|
+
// one off for every subagent), capture and input silently follow the user's
|
|
639
|
+
// focus instead of the agent. The inventory sweep pins each session to its
|
|
640
|
+
// main pane id, and every `-t` call site goes through `tmuxTargetFor` so the
|
|
641
|
+
// pinning cannot be bypassed by one call site forgetting it.
|
|
642
|
+
/** Session name → pinned pane id, replaced wholesale by each inventory sweep. */
|
|
643
|
+
let targetsBySession = new Map();
|
|
644
|
+
/**
|
|
645
|
+
* A subagent session name: `<session>.<pane id digits>` (`zeph-zeph.48`).
|
|
646
|
+
* tmux forbids `.` in session names, so the shape cannot collide; `#` would
|
|
647
|
+
* break the server's stream-sub keys and `:` is the web key separator.
|
|
648
|
+
*/
|
|
649
|
+
const isSubagentSessionName = (name) => /^zeph-.+\.\d+$/.test(name);
|
|
650
|
+
exports.isSubagentSessionName = isSubagentSessionName;
|
|
651
|
+
/** Store the latest sweep's name → pane-id map (see `CollectResult.targets`). */
|
|
652
|
+
const recordTargets = (targets) => {
|
|
653
|
+
targetsBySession = new Map(Object.entries(targets ?? {}));
|
|
654
|
+
};
|
|
655
|
+
exports.recordTargets = recordTargets;
|
|
656
|
+
/**
|
|
657
|
+
* The tmux target for a wire session name: its pinned pane id when the last
|
|
658
|
+
* sweep saw the session, else the name itself (a session younger than one
|
|
659
|
+
* sweep, or tmux unreachable at startup — today's resolution, active pane).
|
|
660
|
+
*
|
|
661
|
+
* A SUBAGENT name is the one exception: it resolves ONLY through the map, and
|
|
662
|
+
* an unknown one is null — because tmux parses `zeph-zeph.48` as session
|
|
663
|
+
* `zeph-zeph`, pane INDEX 48, and silently falls back to the active pane when
|
|
664
|
+
* that index is missing (measured: `display -t zeph-zeph.99` → main pane,
|
|
665
|
+
* exit 0). Every caller treats null as "gone": no spawn, refusal, or capture
|
|
666
|
+
* failure — never a write to whichever pane happens to be focused.
|
|
667
|
+
*/
|
|
668
|
+
const tmuxTargetFor = (name) => {
|
|
669
|
+
const hit = targetsBySession.get(name);
|
|
670
|
+
if (hit !== undefined)
|
|
671
|
+
return hit;
|
|
672
|
+
return (0, exports.isSubagentSessionName)(name) ? null : name;
|
|
673
|
+
};
|
|
674
|
+
exports.tmuxTargetFor = tmuxTargetFor;
|
|
606
675
|
const readPaneInfo = (session) => {
|
|
607
|
-
const
|
|
676
|
+
const target = (0, exports.tmuxTargetFor)(session);
|
|
677
|
+
if (target === null)
|
|
678
|
+
return { currentCommand: null, startCommand: null, currentPath: null, panePid: null };
|
|
679
|
+
const r = (0, child_process_1.spawnSync)('tmux', tmuxArgs(['display-message', '-p', '-t', target,
|
|
608
680
|
`#{pane_current_command}${FIELD_SEP}#{pane_start_command}${FIELD_SEP}#{pane_current_path}${FIELD_SEP}#{pane_pid}`]), {
|
|
609
681
|
encoding: 'utf-8',
|
|
610
682
|
stdio: ['ignore', 'pipe', 'ignore'],
|
|
@@ -674,8 +746,13 @@ const resetSessionStates = () => {
|
|
|
674
746
|
sessionStates.clear();
|
|
675
747
|
};
|
|
676
748
|
exports.resetSessionStates = resetSessionStates;
|
|
677
|
-
const capturePaneText = (session) => {
|
|
678
|
-
|
|
749
|
+
const capturePaneText = (session, target) => {
|
|
750
|
+
// Explicit target for the sweep (subagent rows aren't in the recorded
|
|
751
|
+
// target map yet); otherwise resolve through it.
|
|
752
|
+
const resolved = target ?? (0, exports.tmuxTargetFor)(session);
|
|
753
|
+
if (resolved === null)
|
|
754
|
+
return null; // unresolvable subagent — never spawn
|
|
755
|
+
const r = (0, child_process_1.spawnSync)('tmux', tmuxArgs(['capture-pane', '-p', '-t', resolved, '-S', `-${STATE_CAPTURE_LINES}`]), {
|
|
679
756
|
encoding: 'utf-8',
|
|
680
757
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
681
758
|
});
|
|
@@ -1063,6 +1140,10 @@ const handleSessionResumeRequest = (req, send) => {
|
|
|
1063
1140
|
send({ ...base, ...fields });
|
|
1064
1141
|
return true;
|
|
1065
1142
|
};
|
|
1143
|
+
// A subagent is a pane OF a live session, not a session to start — and
|
|
1144
|
+
// before the rate bucket, so refused subagent traffic costs nothing.
|
|
1145
|
+
if ((0, exports.isSubagentSessionName)(sessionName))
|
|
1146
|
+
return reply({ error: 'subagent_view_only' });
|
|
1066
1147
|
// Charged like a submitted command, not like a keystroke: this starts a
|
|
1067
1148
|
// process, and the two share one budget so a flood cannot be laundered
|
|
1068
1149
|
// through whichever path is cheaper.
|
|
@@ -1154,6 +1235,11 @@ const handleSessionExitRequest = (req, send) => {
|
|
|
1154
1235
|
// Same budget as resume and as a submitted command: ending a session is a
|
|
1155
1236
|
// session-lifecycle action, and pricing it like a keystroke would let a
|
|
1156
1237
|
// flood through the cheaper door.
|
|
1238
|
+
// Subagent refusal first, though — outside the bucket, like resume's:
|
|
1239
|
+
// ending a subagent pane is a kill(2) on the parent's child, not a
|
|
1240
|
+
// lifecycle action the phone is ever offered.
|
|
1241
|
+
if ((0, exports.isSubagentSessionName)(sessionName))
|
|
1242
|
+
return answer({ error: 'subagent_view_only' });
|
|
1157
1243
|
if (!(0, exports.checkRateLimit)(sessionName, undefined, SUBMIT_COST))
|
|
1158
1244
|
return answer({ error: 'rate_limited' });
|
|
1159
1245
|
if (!sessionExists(sessionName))
|
|
@@ -1228,6 +1314,11 @@ const handleSessionForgetRequest = (req, send) => {
|
|
|
1228
1314
|
};
|
|
1229
1315
|
// Charged like a submitted command: it writes to disk and is irreversible,
|
|
1230
1316
|
// so it shares the budget with the paths that start and stop processes.
|
|
1317
|
+
// Subagent refusal before the bucket: a subagent has no registry record
|
|
1318
|
+
// to forget (the sweep never remembers panes), so the honest answer is
|
|
1319
|
+
// the view-only one, not unknown_session.
|
|
1320
|
+
if ((0, exports.isSubagentSessionName)(sessionName))
|
|
1321
|
+
return reply({ error: 'subagent_view_only' });
|
|
1231
1322
|
if (!(0, exports.checkRateLimit)(sessionName, undefined, SUBMIT_COST))
|
|
1232
1323
|
return reply({ error: 'rate_limited' });
|
|
1233
1324
|
if (sessionExists(sessionName))
|
|
@@ -1248,10 +1339,20 @@ const handleSessionForgetRequest = (req, send) => {
|
|
|
1248
1339
|
return reply({ forgotten: true });
|
|
1249
1340
|
};
|
|
1250
1341
|
exports.handleSessionForgetRequest = handleSessionForgetRequest;
|
|
1251
|
-
/**
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1342
|
+
/**
|
|
1343
|
+
* Whether this machine currently holds a session by this name. A subagent
|
|
1344
|
+
* pane cannot be asked with has-session: tmux would parse `zeph-x.48` as
|
|
1345
|
+
* session `zeph-x`, pane index 48 and answer for the WRONG thing (or exit 1
|
|
1346
|
+
* for a missing index) — so subs are answered from the sweep's target map,
|
|
1347
|
+
* which is exactly what "a pane we can address without ambiguity" means.
|
|
1348
|
+
*/
|
|
1349
|
+
const sessionExists = (name) => {
|
|
1350
|
+
if ((0, exports.isSubagentSessionName)(name))
|
|
1351
|
+
return targetsBySession.has(name);
|
|
1352
|
+
return (0, child_process_1.spawnSync)('tmux', tmuxArgs(['has-session', '-t', name]), {
|
|
1353
|
+
stdio: ['ignore', 'ignore', 'ignore'],
|
|
1354
|
+
}).status === 0;
|
|
1355
|
+
};
|
|
1255
1356
|
// ─── Deep pull: scrollback above the live window ───────────────────
|
|
1256
1357
|
//
|
|
1257
1358
|
// The live stream captures a fixed window and every frame is capped at
|
|
@@ -1270,7 +1371,10 @@ const isPageOffset = (v) => typeof v === 'number' && Number.isInteger(v) && v >=
|
|
|
1270
1371
|
/** How many lines of scrollback the pane is holding, or null when tmux won't
|
|
1271
1372
|
* say — which is also how a dead pane answers. */
|
|
1272
1373
|
const paneHistorySize = (sessionName) => {
|
|
1273
|
-
const
|
|
1374
|
+
const target = (0, exports.tmuxTargetFor)(sessionName);
|
|
1375
|
+
if (target === null)
|
|
1376
|
+
return null;
|
|
1377
|
+
const r = (0, child_process_1.spawnSync)('tmux', tmuxArgs(['display-message', '-p', '-t', target, '#{history_size}']), { encoding: 'utf-8', stdio: ['ignore', 'pipe', 'pipe'] });
|
|
1274
1378
|
if (r.status !== 0)
|
|
1275
1379
|
return null;
|
|
1276
1380
|
const size = Number((r.stdout ?? '').trim());
|
|
@@ -1279,8 +1383,11 @@ const paneHistorySize = (sessionName) => {
|
|
|
1279
1383
|
/** Capture one explicit range. tmux line 0 is the top of the visible pane and
|
|
1280
1384
|
* negative numbers reach into the history, so both bounds are negative here. */
|
|
1281
1385
|
const capturePaneRange = (sessionName, start, end) => {
|
|
1386
|
+
const target = (0, exports.tmuxTargetFor)(sessionName);
|
|
1387
|
+
if (target === null)
|
|
1388
|
+
return null;
|
|
1282
1389
|
const r = (0, child_process_1.spawnSync)('tmux', tmuxArgs([
|
|
1283
|
-
'capture-pane', '-p', '-e', '-t',
|
|
1390
|
+
'capture-pane', '-p', '-e', '-t', target,
|
|
1284
1391
|
'-S', String(start), '-E', String(end),
|
|
1285
1392
|
]), { encoding: 'utf-8', stdio: ['ignore', 'pipe', 'pipe'] });
|
|
1286
1393
|
if (r.status !== 0)
|
|
@@ -1392,9 +1499,12 @@ const capturePane = (sessionName, escapes = false, lines = SCREEN_PEEK_LINES) =>
|
|
|
1392
1499
|
// `lines` sets how far back the capture reaches — the live stream grabs
|
|
1393
1500
|
// more history so the mirror has room to scroll; SCREEN_PEEK_MAX_BYTES
|
|
1394
1501
|
// still caps the payload below.
|
|
1502
|
+
const target = (0, exports.tmuxTargetFor)(sessionName);
|
|
1503
|
+
if (target === null)
|
|
1504
|
+
return null;
|
|
1395
1505
|
const captureArgs = escapes
|
|
1396
|
-
? ['capture-pane', '-p', '-e', '-t',
|
|
1397
|
-
: ['capture-pane', '-p', '-t',
|
|
1506
|
+
? ['capture-pane', '-p', '-e', '-t', target, '-S', `-${lines}`]
|
|
1507
|
+
: ['capture-pane', '-p', '-t', target, '-S', `-${lines}`];
|
|
1398
1508
|
const r = (0, child_process_1.spawnSync)('tmux', tmuxArgs(captureArgs), {
|
|
1399
1509
|
encoding: 'utf-8',
|
|
1400
1510
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
@@ -1419,8 +1529,11 @@ const capturePane = (sessionName, escapes = false, lines = SCREEN_PEEK_LINES) =>
|
|
|
1419
1529
|
* spawn per SENT frame rather than per tick.
|
|
1420
1530
|
*/
|
|
1421
1531
|
const capturePaneCursor = (sessionName) => {
|
|
1532
|
+
const target = (0, exports.tmuxTargetFor)(sessionName);
|
|
1533
|
+
if (target === null)
|
|
1534
|
+
return null;
|
|
1422
1535
|
const r = (0, child_process_1.spawnSync)('tmux', tmuxArgs([
|
|
1423
|
-
'display-message', '-p', '-t',
|
|
1536
|
+
'display-message', '-p', '-t', target,
|
|
1424
1537
|
'#{cursor_x},#{cursor_y},#{pane_height},#{history_size}',
|
|
1425
1538
|
]), { encoding: 'utf-8', stdio: ['ignore', 'pipe', 'ignore'] });
|
|
1426
1539
|
if (r.status !== 0)
|
|
@@ -2430,20 +2543,25 @@ exports.handleCommandInput = handleCommandInput;
|
|
|
2430
2543
|
* re-attach, and the current command is `node` rather than `claude`).
|
|
2431
2544
|
*/
|
|
2432
2545
|
const collectSessionsVerbose = () => {
|
|
2433
|
-
|
|
2434
|
-
|
|
2546
|
+
// One sweep for the whole server: every pane of every session, so a
|
|
2547
|
+
// session's main pane is known regardless of which pane has focus, and
|
|
2548
|
+
// extra panes are visible to later slices. Per-pane spawns (the old
|
|
2549
|
+
// per-session display-message) would multiply with split panes; the worker
|
|
2550
|
+
// thread keeps the one blocking sweep off the event loop.
|
|
2551
|
+
const list = (0, child_process_1.spawnSync)('tmux', tmuxArgs(['list-panes', '-a', '-F',
|
|
2552
|
+
`#{session_name}${FIELD_SEP}#{session_attached}${FIELD_SEP}#{session_created}${FIELD_SEP}#{session_activity}${FIELD_SEP}#{window_index}${FIELD_SEP}#{pane_index}${FIELD_SEP}#{pane_id}${FIELD_SEP}#{pane_current_command}${FIELD_SEP}#{pane_start_command}${FIELD_SEP}#{pane_current_path}${FIELD_SEP}#{pane_pid}${FIELD_SEP}#{@zeph_pane_label}`]), {
|
|
2435
2553
|
encoding: 'utf-8',
|
|
2436
2554
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
2437
2555
|
});
|
|
2438
2556
|
if (list.status !== 0) {
|
|
2439
2557
|
const stderr = (list.stderr ?? '').toString().trim();
|
|
2440
|
-
log(` tmux list-
|
|
2558
|
+
log(` tmux list-panes failed: status=${list.status}${stderr ? ', stderr=' + stderr : ''}`);
|
|
2441
2559
|
// Tmux call failed against the cached socket — the server it
|
|
2442
2560
|
// pointed at is gone (died, restarted at a different path, etc).
|
|
2443
2561
|
// Invalidate so the next cycle re-runs full discovery instead of
|
|
2444
2562
|
// wedging the listener at "reported 0 session(s)" forever.
|
|
2445
2563
|
(0, exports.invalidateTmuxSocketCache)();
|
|
2446
|
-
return { sessions: [], rejected: [] };
|
|
2564
|
+
return { sessions: [], rejected: [], targets: {} };
|
|
2447
2565
|
}
|
|
2448
2566
|
const rawLines = (list.stdout ?? '').split('\n').filter(Boolean);
|
|
2449
2567
|
// Sanity-check that the format separator actually survived. tmux is
|
|
@@ -2453,66 +2571,159 @@ const collectSessionsVerbose = () => {
|
|
|
2453
2571
|
// it as "not zeph-*". Detect that explicitly so the user isn't left
|
|
2454
2572
|
// guessing.
|
|
2455
2573
|
if (rawLines.length > 0 && !rawLines[0].includes(FIELD_SEP)) {
|
|
2456
|
-
log(` tmux output missing FIELD_SEP — likely encoding issue. Raw line: ${JSON.stringify(rawLines[0])}`);
|
|
2574
|
+
log(` tmux list-panes output missing FIELD_SEP — likely encoding issue. Raw line: ${JSON.stringify(rawLines[0])}`);
|
|
2457
2575
|
}
|
|
2458
2576
|
const sessions = [];
|
|
2459
2577
|
const rejected = [];
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
const
|
|
2578
|
+
/** 12 fields per row; a mismatch is the mangled-separator failure the
|
|
2579
|
+
* sanity log above exists for — skip the row loudly, never misparse it. */
|
|
2580
|
+
const PANE_FIELDS = 12;
|
|
2581
|
+
const groups = new Map();
|
|
2582
|
+
let malformed = 0;
|
|
2464
2583
|
for (const line of rawLines) {
|
|
2465
|
-
const
|
|
2466
|
-
|
|
2467
|
-
|
|
2584
|
+
const f = line.split(FIELD_SEP);
|
|
2585
|
+
if (f.length !== PANE_FIELDS) {
|
|
2586
|
+
malformed += 1;
|
|
2587
|
+
continue;
|
|
2588
|
+
}
|
|
2589
|
+
const [name, attached, created, activity, win, idx, paneId, current, start, path, pid, label] = f;
|
|
2590
|
+
if (!(0, exports.parseSessionName)(name)) {
|
|
2468
2591
|
// Not noisy enough to log every plain tmux session here —
|
|
2469
2592
|
// would clutter the verbose output on machines with many
|
|
2470
2593
|
// non-zeph sessions.
|
|
2471
2594
|
continue;
|
|
2472
2595
|
}
|
|
2473
|
-
const
|
|
2474
|
-
|
|
2475
|
-
|
|
2596
|
+
const numeric = (v) => {
|
|
2597
|
+
const n = Number(v);
|
|
2598
|
+
return Number.isInteger(n) && n >= 0 ? n : Number.MAX_SAFE_INTEGER;
|
|
2599
|
+
};
|
|
2600
|
+
const row = {
|
|
2601
|
+
paneId,
|
|
2602
|
+
win: numeric(win),
|
|
2603
|
+
idx: numeric(idx),
|
|
2604
|
+
label: label ?? '',
|
|
2605
|
+
info: {
|
|
2606
|
+
currentCommand: current || null,
|
|
2607
|
+
startCommand: start || null,
|
|
2608
|
+
currentPath: path || null,
|
|
2609
|
+
panePid: numeric(pid) === Number.MAX_SAFE_INTEGER ? null : numeric(pid),
|
|
2610
|
+
},
|
|
2611
|
+
};
|
|
2612
|
+
const group = groups.get(name) ?? { attached: attached === '1', created, activity, panes: [] };
|
|
2613
|
+
group.panes.push(row);
|
|
2614
|
+
groups.set(name, group);
|
|
2615
|
+
}
|
|
2616
|
+
if (malformed > 0) {
|
|
2617
|
+
log(` tmux list-panes: skipped ${malformed} malformed row(s) — format separator may be mangled`);
|
|
2618
|
+
}
|
|
2619
|
+
// Pane cwd per session, read in the same sweep. Kept beside the wire shape
|
|
2620
|
+
// rather than in it: AgentSession is a server/phone contract and the
|
|
2621
|
+
// directory is local knowledge the registry needs, nothing the phone gets.
|
|
2622
|
+
const paneCwdOf = new Map();
|
|
2623
|
+
const targets = {};
|
|
2624
|
+
for (const [name, group] of groups) {
|
|
2625
|
+
const parsed = (0, exports.parseSessionName)(name);
|
|
2626
|
+
if (!parsed)
|
|
2627
|
+
continue; // unreachable — groups only holds parsed names
|
|
2628
|
+
// Main pane = the lowest (window, pane) index that runs an agent.
|
|
2629
|
+
// pi-interactive-subagents splits `-d` to the RIGHT of the parent, so
|
|
2630
|
+
// the parent keeps the lower index; a manual left split would take the
|
|
2631
|
+
// main role — accepted. Focus decides nothing here, which is the point:
|
|
2632
|
+
// focusing a subagent pane must not move the phone's view of the main.
|
|
2633
|
+
group.panes.sort((a, b) => (a.win - b.win) || (a.idx - b.idx));
|
|
2634
|
+
let main = null;
|
|
2635
|
+
for (const row of group.panes) {
|
|
2636
|
+
const agent = (0, exports.detectRemoteAgent)(row.info);
|
|
2637
|
+
if (agent) {
|
|
2638
|
+
main = { row, agent };
|
|
2639
|
+
break;
|
|
2640
|
+
}
|
|
2641
|
+
}
|
|
2642
|
+
if (!main) {
|
|
2643
|
+
const first = group.panes[0]?.info;
|
|
2476
2644
|
rejected.push({
|
|
2477
2645
|
name,
|
|
2478
|
-
reason: `no agent in pane (start=${
|
|
2646
|
+
reason: `no agent in pane (start=${first?.startCommand ?? 'null'}, current=${first?.currentCommand ?? 'null'})`,
|
|
2479
2647
|
});
|
|
2480
2648
|
continue;
|
|
2481
2649
|
}
|
|
2650
|
+
const info = main.row.info;
|
|
2482
2651
|
const agentSessionId = info.currentPath
|
|
2483
|
-
? (agent.resolveSessionId?.(info.currentPath, info.panePid ?? undefined) ?? null)
|
|
2652
|
+
? (main.agent.resolveSessionId?.(info.currentPath, info.panePid ?? undefined) ?? null)
|
|
2484
2653
|
: null;
|
|
2485
2654
|
const providerSessionName = info.currentPath
|
|
2486
|
-
? (agent.resolveSessionName?.(info.currentPath, info.panePid ?? undefined) ?? null)
|
|
2655
|
+
? (main.agent.resolveSessionName?.(info.currentPath, info.panePid ?? undefined) ?? null)
|
|
2487
2656
|
: null;
|
|
2488
2657
|
if (info.currentPath)
|
|
2489
2658
|
paneCwdOf.set(name, info.currentPath);
|
|
2659
|
+
targets[name] = main.row.paneId;
|
|
2490
2660
|
sessions.push({
|
|
2491
2661
|
name,
|
|
2492
|
-
attached: attached
|
|
2493
|
-
agentKind: agent.kind,
|
|
2662
|
+
attached: group.attached,
|
|
2663
|
+
agentKind: main.agent.kind,
|
|
2494
2664
|
agentSessionId,
|
|
2495
2665
|
project: parsed.project,
|
|
2496
2666
|
label: parsed.label,
|
|
2497
2667
|
providerSessionName,
|
|
2498
|
-
createdAt: epochToIso(created),
|
|
2499
|
-
lastActivityAt: epochToIso(activity),
|
|
2500
|
-
...(0, exports.deriveSessionState)(name, agent.kind, capturePaneText(name)),
|
|
2668
|
+
createdAt: epochToIso(group.created),
|
|
2669
|
+
lastActivityAt: epochToIso(group.activity),
|
|
2670
|
+
...(0, exports.deriveSessionState)(name, main.agent.kind, capturePaneText(name, main.row.paneId)),
|
|
2501
2671
|
});
|
|
2672
|
+
// Subagent panes: every OTHER pane of this session whose tty's
|
|
2673
|
+
// foreground process group runs a registered agent (measured:
|
|
2674
|
+
// pane_current_command alone says `bash` for a pi subagent — the
|
|
2675
|
+
// fg group's `comm` is what names it). View-only wire entities
|
|
2676
|
+
// named `<session>.<pane id digits>`; ordered by pane id so the
|
|
2677
|
+
// phone's switcher is stable across sweeps (tmux pane ids are
|
|
2678
|
+
// monotonic server-wide).
|
|
2679
|
+
const paneNum = (p) => Number(p.paneId.slice(1)) || 0;
|
|
2680
|
+
const extras = group.panes
|
|
2681
|
+
.filter((p) => p !== main.row)
|
|
2682
|
+
.sort((a, b) => paneNum(a) - paneNum(b));
|
|
2683
|
+
const fallbackCounts = new Map();
|
|
2684
|
+
for (const extra of extras) {
|
|
2685
|
+
const subAgent = (0, remote_agents_js_1.foregroundAgentFor)(extra.info.panePid ?? 0);
|
|
2686
|
+
if (!subAgent)
|
|
2687
|
+
continue; // a shell / non-agent pane — not reportable
|
|
2688
|
+
const subName = `${name}.${paneNum(extra)}`;
|
|
2689
|
+
targets[subName] = extra.paneId;
|
|
2690
|
+
const n = (fallbackCounts.get(subAgent.kind) ?? 0) + 1;
|
|
2691
|
+
fallbackCounts.set(subAgent.kind, n);
|
|
2692
|
+
sessions.push({
|
|
2693
|
+
name: subName,
|
|
2694
|
+
parentName: name,
|
|
2695
|
+
attached: group.attached,
|
|
2696
|
+
agentKind: subAgent.kind,
|
|
2697
|
+
agentSessionId: null,
|
|
2698
|
+
project: parsed.project,
|
|
2699
|
+
// The subagent names itself by setting @zeph_pane_label
|
|
2700
|
+
// (PI_EXTENSION); a manual `tmux set-option -p` works too.
|
|
2701
|
+
// Fallback names per agent kind so two subagents of the
|
|
2702
|
+
// same kind stay distinguishable.
|
|
2703
|
+
label: extra.label.trim() || `${subAgent.displayName} ${n}`,
|
|
2704
|
+
createdAt: epochToIso(group.created),
|
|
2705
|
+
lastActivityAt: epochToIso(group.activity),
|
|
2706
|
+
...(0, exports.deriveSessionState)(subName, subAgent.kind, capturePaneText(subName, extra.paneId)),
|
|
2707
|
+
});
|
|
2708
|
+
}
|
|
2502
2709
|
}
|
|
2503
2710
|
pruneSessionStates(new Set(sessions.map((s) => s.name)));
|
|
2504
2711
|
// Write down what each live session IS, while it still exists to be read.
|
|
2505
2712
|
// tmux forgets a session the moment it ends, which is exactly when the
|
|
2506
2713
|
// phone wants it back — and a resume must take its directory and its binary
|
|
2507
2714
|
// from what this machine observed, never from the wire.
|
|
2508
|
-
(0, session_registry_js_1.rememberSessions)(
|
|
2715
|
+
(0, session_registry_js_1.rememberSessions)(
|
|
2716
|
+
// Subagents are view-only panes OF a session, not resumable ones:
|
|
2717
|
+
// the registry records what a session IS so exit/resume can act on
|
|
2718
|
+
// it, and neither is ever offered for a subagent.
|
|
2719
|
+
sessions.filter((s) => !s.parentName).map((s) => ({
|
|
2509
2720
|
name: s.name,
|
|
2510
2721
|
cwd: paneCwdOf.get(s.name) ?? null,
|
|
2511
2722
|
agentKind: s.agentKind,
|
|
2512
2723
|
project: s.project,
|
|
2513
2724
|
label: s.label,
|
|
2514
2725
|
})));
|
|
2515
|
-
return { sessions, rejected };
|
|
2726
|
+
return { sessions, rejected, targets };
|
|
2516
2727
|
};
|
|
2517
2728
|
exports.collectSessionsVerbose = collectSessionsVerbose;
|
|
2518
2729
|
/**
|
|
@@ -2524,7 +2735,14 @@ exports.collectSessionsVerbose = collectSessionsVerbose;
|
|
|
2524
2735
|
* something not registered in remote-agents.ts are filtered out — the
|
|
2525
2736
|
* phone can't usefully address them.
|
|
2526
2737
|
*/
|
|
2527
|
-
const collectSessions = () =>
|
|
2738
|
+
const collectSessions = () => {
|
|
2739
|
+
const result = (0, exports.collectSessionsVerbose)();
|
|
2740
|
+
// The membership path also refreshes the pane targets: a session younger
|
|
2741
|
+
// than one report cycle gets its pane id pinned here rather than falling
|
|
2742
|
+
// back to the (focus-following) bare session name.
|
|
2743
|
+
(0, exports.recordTargets)(result.targets);
|
|
2744
|
+
return result.sessions;
|
|
2745
|
+
};
|
|
2528
2746
|
/** Names from the most recent inventory sweep; null until the first one lands —
|
|
2529
2747
|
* a membership check in that window (the connect burst) still sweeps in-thread. */
|
|
2530
2748
|
let inventorySnapshot = null;
|
|
@@ -2571,6 +2789,12 @@ const publishedTmuxNames = new Map();
|
|
|
2571
2789
|
const syncTmuxAgentNames = (sessions) => {
|
|
2572
2790
|
const liveKeys = new Set();
|
|
2573
2791
|
for (const s of sessions) {
|
|
2792
|
+
// Subagents are view-only panes of the parent; publishing a name
|
|
2793
|
+
// for them would run set-option against a `<session>.<pane>` name
|
|
2794
|
+
// that tmux parses as the PARENT session (pane index) — clobbering
|
|
2795
|
+
// the main pane's published name.
|
|
2796
|
+
if (s.parentName)
|
|
2797
|
+
continue;
|
|
2574
2798
|
const key = `${s.name}\u241f${s.createdAt ?? ''}`;
|
|
2575
2799
|
liveKeys.add(key);
|
|
2576
2800
|
const value = s.providerSessionName ?? '';
|
|
@@ -2618,6 +2842,15 @@ exports.isInventoried = isInventoried;
|
|
|
2618
2842
|
* prefix path route through here so the defense layers can't diverge.
|
|
2619
2843
|
*/
|
|
2620
2844
|
const passesInjectGuards = (session, deps, cost = 1) => {
|
|
2845
|
+
// Subagent panes are view-only: the phone reads them but the agent
|
|
2846
|
+
// itself answers at the terminal. This sits above the rate bucket so a
|
|
2847
|
+
// flood of refused subagent writes costs nothing and spawns nothing —
|
|
2848
|
+
// with an unresolvable name every downstream tmux call is a no-op, but
|
|
2849
|
+
// the refusal must not depend on the pane still being mapped.
|
|
2850
|
+
if ((0, exports.isSubagentSessionName)(session)) {
|
|
2851
|
+
log(`! ${session}: subagent pane is view-only — drop`);
|
|
2852
|
+
return false;
|
|
2853
|
+
}
|
|
2621
2854
|
// Rate bucket first: the pane probe below is a blocking tmux spawnSync,
|
|
2622
2855
|
// and the sequencer can flush several held messages back-to-back — an
|
|
2623
2856
|
// empty bucket must refuse before paying that probe N times, not after.
|
|
@@ -3084,8 +3317,9 @@ const streamSession = (wsUrl, apiKey) => {
|
|
|
3084
3317
|
sweepInFlight = false;
|
|
3085
3318
|
}
|
|
3086
3319
|
};
|
|
3087
|
-
const publishSessions = ({ sessions, rejected }) => {
|
|
3320
|
+
const publishSessions = ({ sessions, rejected, targets }) => {
|
|
3088
3321
|
(0, exports.recordInventory)(sessions);
|
|
3322
|
+
(0, exports.recordTargets)(targets);
|
|
3089
3323
|
// Let the user's own status bar say what the phone says. Change-gated
|
|
3090
3324
|
// internally, so an unchanged sweep spawns nothing.
|
|
3091
3325
|
(0, exports.syncTmuxAgentNames)(sessions);
|
package/dist/remote-agents.d.ts
CHANGED
|
@@ -76,6 +76,15 @@ export interface ProcTable {
|
|
|
76
76
|
children: Map<number, number[]>;
|
|
77
77
|
/** pid → process start time in epoch ms. Only pids whose `lstart` parsed. */
|
|
78
78
|
startTimes: Map<number, number>;
|
|
79
|
+
/** pid → its process group id. Absent when the row carried no pgid. */
|
|
80
|
+
pgidOf: Map<number, number>;
|
|
81
|
+
/** pid → the foreground process group of its controlling tty. A pane
|
|
82
|
+
* shell whose tpgid equals its own pgid IS the foreground — a plain
|
|
83
|
+
* prompt; anything else is running a foreground command. */
|
|
84
|
+
tpgidOf: Map<number, number>;
|
|
85
|
+
/** pid → its command name (`comm`), last column because it may contain
|
|
86
|
+
* spaces (`tmux: client`). Basename-matched against the agent registry. */
|
|
87
|
+
commOf: Map<number, string>;
|
|
79
88
|
}
|
|
80
89
|
/**
|
|
81
90
|
* Parse `ps -axo pid=,ppid=,lstart=`. A row is `<pid> <ppid> [<lstart>]`, e.g.
|
|
@@ -92,7 +101,30 @@ export interface ProcTable {
|
|
|
92
101
|
* allowed to go missing, and every consumer of `startTimes` treats an absent
|
|
93
102
|
* entry as "no match" rather than guessing.
|
|
94
103
|
*/
|
|
104
|
+
/**
|
|
105
|
+
* Parse `ps -axo pid=,ppid=,pgid=,tpgid=,lstart=,comm=`. A row is
|
|
106
|
+
* `<pid> <ppid> <pgid> <tpgid> [<lstart>] [<comm>]`, e.g.
|
|
107
|
+
* ` 902 1 902 902 Fri Aug 7 11:12:59 2026 zsh` — note the two spaces
|
|
108
|
+
* before a single-digit day and the trailing padding.
|
|
109
|
+
*
|
|
110
|
+
* Token positions, not one regex: `lstart` is a fixed 5 tokens when present
|
|
111
|
+
* and `comm` is LAST because it may contain spaces. A row with fewer tokens
|
|
112
|
+
* simply contributes fewer maps — the shape is load-bearing rather than
|
|
113
|
+
* defensive: parent links must survive an unreadable timestamp (the reason
|
|
114
|
+
* `lstart` is optional), and the pgid/tpgid/comm columns are absent only when
|
|
115
|
+
* a caller fed the old narrower argv, which nothing in production does.
|
|
116
|
+
*/
|
|
95
117
|
export declare const parseProcTable: (table: string) => ProcTable;
|
|
118
|
+
/**
|
|
119
|
+
* The agent running in the FOREGROUND process group of the tty owned by a
|
|
120
|
+
* pane shell, or null. This is what separates a subagent pane from a plain
|
|
121
|
+
* prompt: the subagent pane reports `pane_current_command=bash` (a script
|
|
122
|
+
* execs pi), so the pane-level command identifies nothing — but the tty's
|
|
123
|
+
* foreground group is pi's, and `comm` names it. A pane sitting at its login
|
|
124
|
+
* shell has the shell's own group in the foreground (tpgid === pgid) and is
|
|
125
|
+
* not a subagent, no matter what the registry would match.
|
|
126
|
+
*/
|
|
127
|
+
export declare const foregroundAgentFor: (panePid: number, table?: ProcTable | null) => RegisteredRemoteAgent | null;
|
|
96
128
|
/** Start times for this cycle's snapshot. Empty when `ps` is unavailable. */
|
|
97
129
|
export declare const psStartTimes: () => Map<number, number>;
|
|
98
130
|
/** pid set of `rootPid` + all descendants, from one `ps` snapshot. */
|
|
@@ -1 +1 @@
|
|
|
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;IAC1E;;;;;;;;;OASG;IACH,iBAAiB,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;CAC5E;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;
|
|
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;IAC1E;;;;;;;;;OASG;IACH,iBAAiB,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;CAC5E;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;IAChC,uEAAuE;IACvE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5B;;iEAE6D;IAC7D,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B;gFAC4E;IAC5E,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC/B;AAED;;;;;;;;;;;;;;GAcG;AACH;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,cAAc,GAAI,OAAO,MAAM,KAAG,SA4B9C,CAAC;AAgBF;;;;;;;;GAQG;AACH,eAAO,MAAM,kBAAkB,GAC3B,SAAS,MAAM,EACf,QAAO,SAAS,GAAG,IAAuB,KAC3C,qBAAqB,GAAG,IAW1B,CAAC;AAEF,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;;;;;;;GAOG;AACH,eAAO,MAAM,sBAAsB,QAAO,OAA+C,CAAC;AAE1F;;;;;;;;;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;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,oBAAoB,GAAI,SAAS,MAAM,GAAG,IAAI,EAAE,UAAU,MAAM,KAAG,MAAM,GAAG,IA+BxF,CAAC;AAeF;;;;;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;;;;;;;;;;;EAgL2B,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
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.matchAgentByPaneCommand = exports.findAgentBySubcommand = exports.REMOTE_AGENTS = exports.detectCodexSessionName = exports.newestVersionedDb = exports.detectHermesSessionName = exports.sqliteJson = exports.pickRowByProcStart = exports.claudeTranscriptPath = exports.detectClaudeSessionNameByPid = exports.detectClaudeSessionIdByPid = exports.detectClaudeSessionByPid = exports.pidSessionRecordsExist = exports.collectDescendantPids = exports.psStartTimes = exports.parseProcTable = exports.detectClaudeSessionId = void 0;
|
|
3
|
+
exports.matchAgentByPaneCommand = exports.findAgentBySubcommand = exports.REMOTE_AGENTS = exports.detectCodexSessionName = exports.newestVersionedDb = exports.detectHermesSessionName = exports.sqliteJson = exports.pickRowByProcStart = exports.claudeTranscriptPath = exports.detectClaudeSessionNameByPid = exports.detectClaudeSessionIdByPid = exports.detectClaudeSessionByPid = exports.pidSessionRecordsExist = exports.collectDescendantPids = exports.psStartTimes = exports.foregroundAgentFor = exports.parseProcTable = exports.detectClaudeSessionId = void 0;
|
|
4
4
|
/**
|
|
5
5
|
* Remote-control agent registry — the single table behind every
|
|
6
6
|
* `zeph <agent>` subcommand, the listener's pane matching, and the
|
|
@@ -178,24 +178,50 @@ const ttlMemo = (ttlMs, compute) => {
|
|
|
178
178
|
* allowed to go missing, and every consumer of `startTimes` treats an absent
|
|
179
179
|
* entry as "no match" rather than guessing.
|
|
180
180
|
*/
|
|
181
|
+
/**
|
|
182
|
+
* Parse `ps -axo pid=,ppid=,pgid=,tpgid=,lstart=,comm=`. A row is
|
|
183
|
+
* `<pid> <ppid> <pgid> <tpgid> [<lstart>] [<comm>]`, e.g.
|
|
184
|
+
* ` 902 1 902 902 Fri Aug 7 11:12:59 2026 zsh` — note the two spaces
|
|
185
|
+
* before a single-digit day and the trailing padding.
|
|
186
|
+
*
|
|
187
|
+
* Token positions, not one regex: `lstart` is a fixed 5 tokens when present
|
|
188
|
+
* and `comm` is LAST because it may contain spaces. A row with fewer tokens
|
|
189
|
+
* simply contributes fewer maps — the shape is load-bearing rather than
|
|
190
|
+
* defensive: parent links must survive an unreadable timestamp (the reason
|
|
191
|
+
* `lstart` is optional), and the pgid/tpgid/comm columns are absent only when
|
|
192
|
+
* a caller fed the old narrower argv, which nothing in production does.
|
|
193
|
+
*/
|
|
181
194
|
const parseProcTable = (table) => {
|
|
182
195
|
const children = new Map();
|
|
183
196
|
const startTimes = new Map();
|
|
197
|
+
const pgidOf = new Map();
|
|
198
|
+
const tpgidOf = new Map();
|
|
199
|
+
const commOf = new Map();
|
|
184
200
|
for (const line of table.split('\n')) {
|
|
185
|
-
const
|
|
186
|
-
|
|
201
|
+
const tok = line.trim().split(/\s+/);
|
|
202
|
+
const pid = Number(tok[0]);
|
|
203
|
+
const ppid = Number(tok[1]);
|
|
204
|
+
if (!Number.isInteger(pid) || !Number.isInteger(ppid))
|
|
187
205
|
continue;
|
|
188
|
-
const [pid, ppid] = [Number(m[1]), Number(m[2])];
|
|
189
206
|
const list = children.get(ppid) ?? [];
|
|
190
207
|
list.push(pid);
|
|
191
208
|
children.set(ppid, list);
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
209
|
+
let rest = tok.slice(2);
|
|
210
|
+
if (rest.length >= 2 && Number.isInteger(Number(rest[0]))) {
|
|
211
|
+
pgidOf.set(pid, Number(rest[0]));
|
|
212
|
+
tpgidOf.set(pid, Number(rest[1]));
|
|
213
|
+
rest = rest.slice(2);
|
|
214
|
+
}
|
|
215
|
+
if (rest.length >= 5) {
|
|
216
|
+
const started = Date.parse(rest.slice(0, 5).join(' '));
|
|
217
|
+
if (Number.isFinite(started))
|
|
218
|
+
startTimes.set(pid, started);
|
|
219
|
+
rest = rest.slice(5);
|
|
220
|
+
}
|
|
221
|
+
if (rest.length > 0)
|
|
222
|
+
commOf.set(pid, rest.join(' '));
|
|
197
223
|
}
|
|
198
|
-
return { children, startTimes };
|
|
224
|
+
return { children, startTimes, pgidOf, tpgidOf, commOf };
|
|
199
225
|
};
|
|
200
226
|
exports.parseProcTable = parseProcTable;
|
|
201
227
|
/**
|
|
@@ -205,9 +231,38 @@ exports.parseProcTable = parseProcTable;
|
|
|
205
231
|
* second `ps` spawn to learn that would undo what this memo is for.
|
|
206
232
|
*/
|
|
207
233
|
const readPsSnapshot = ttlMemo(SNAPSHOT_TTL_MS, () => {
|
|
208
|
-
|
|
234
|
+
// pgid/tpgid/comm ride along for the subagent detection (foreground
|
|
235
|
+
// process group), so the extra panes cost zero new spawns — one `ps`
|
|
236
|
+
// per report cycle is still the whole table (KB precedent).
|
|
237
|
+
const r = (0, child_process_1.spawnSync)('ps', ['-axo', 'pid=,ppid=,pgid=,tpgid=,lstart=,comm='], { encoding: 'utf-8', stdio: ['ignore', 'pipe', 'ignore'] });
|
|
209
238
|
return r.status === 0 ? (0, exports.parseProcTable)(r.stdout ?? '') : null;
|
|
210
239
|
});
|
|
240
|
+
/**
|
|
241
|
+
* The agent running in the FOREGROUND process group of the tty owned by a
|
|
242
|
+
* pane shell, or null. This is what separates a subagent pane from a plain
|
|
243
|
+
* prompt: the subagent pane reports `pane_current_command=bash` (a script
|
|
244
|
+
* execs pi), so the pane-level command identifies nothing — but the tty's
|
|
245
|
+
* foreground group is pi's, and `comm` names it. A pane sitting at its login
|
|
246
|
+
* shell has the shell's own group in the foreground (tpgid === pgid) and is
|
|
247
|
+
* not a subagent, no matter what the registry would match.
|
|
248
|
+
*/
|
|
249
|
+
const foregroundAgentFor = (panePid, table = readPsSnapshot()) => {
|
|
250
|
+
if (!Number.isInteger(panePid) || panePid <= 0 || !table)
|
|
251
|
+
return null;
|
|
252
|
+
const pgid = table.pgidOf.get(panePid);
|
|
253
|
+
const tpgid = table.tpgidOf.get(panePid);
|
|
254
|
+
if (pgid === undefined || tpgid === undefined || tpgid === pgid)
|
|
255
|
+
return null;
|
|
256
|
+
for (const [pid, pgrp] of table.pgidOf) {
|
|
257
|
+
if (pgrp !== tpgid)
|
|
258
|
+
continue;
|
|
259
|
+
const agent = (0, exports.matchAgentByPaneCommand)((0, path_1.basename)(table.commOf.get(pid) ?? ''));
|
|
260
|
+
if (agent)
|
|
261
|
+
return agent;
|
|
262
|
+
}
|
|
263
|
+
return null;
|
|
264
|
+
};
|
|
265
|
+
exports.foregroundAgentFor = foregroundAgentFor;
|
|
211
266
|
/** Start times for this cycle's snapshot. Empty when `ps` is unavailable. */
|
|
212
267
|
const psStartTimes = () => readPsSnapshot()?.startTimes ?? new Map();
|
|
213
268
|
exports.psStartTimes = psStartTimes;
|
package/dist/templates.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"templates.d.ts","sourceRoot":"","sources":["../src/templates.ts"],"names":[],"mappings":"AAwGA,oGAAoG;AACpG,eAAO,MAAM,kBAAkB,QAAS,CAAC;AA8IzC,6FAA6F;AAC7F,eAAO,MAAM,WAAW,QAKtB,CAAC;AAEH,6FAA6F;AAC7F,eAAO,MAAM,aAAa,QAIxB,CAAC;AAEH,+GAA+G;AAC/G,eAAO,MAAM,WAAW,QAAoE,CAAC;AAE7F,4GAA4G;AAC5G,eAAO,MAAM,UAAU,QAAoE,CAAC;AAE5F,oGAAoG;AACpG,eAAO,MAAM,YAAY,QAIvB,CAAC;AAEH,gFAAgF;AAChF,eAAO,MAAM,UAAU,QAIrB,CAAC;AAEH,sGAAsG;AACtG,eAAO,MAAM,UAAU,QAIrB,CAAC;AAEH,wJAAwJ;AACxJ,eAAO,MAAM,OAAO,QAKlB,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,
|
|
1
|
+
{"version":3,"file":"templates.d.ts","sourceRoot":"","sources":["../src/templates.ts"],"names":[],"mappings":"AAwGA,oGAAoG;AACpG,eAAO,MAAM,kBAAkB,QAAS,CAAC;AA8IzC,6FAA6F;AAC7F,eAAO,MAAM,WAAW,QAKtB,CAAC;AAEH,6FAA6F;AAC7F,eAAO,MAAM,aAAa,QAIxB,CAAC;AAEH,+GAA+G;AAC/G,eAAO,MAAM,WAAW,QAAoE,CAAC;AAE7F,4GAA4G;AAC5G,eAAO,MAAM,UAAU,QAAoE,CAAC;AAE5F,oGAAoG;AACpG,eAAO,MAAM,YAAY,QAIvB,CAAC;AAEH,gFAAgF;AAChF,eAAO,MAAM,UAAU,QAIrB,CAAC;AAEH,sGAAsG;AACtG,eAAO,MAAM,UAAU,QAIrB,CAAC;AAEH,wJAAwJ;AACxJ,eAAO,MAAM,OAAO,QAKlB,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,QAyKxB,CAAC;AAEF,kGAAkG;AAClG,eAAO,MAAM,eAAe,QAwG3B,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
|
@@ -368,7 +368,7 @@ exports.COPILOT_HOOKS = JSON.stringify({
|
|
|
368
368
|
// *_PLUGIN for the same quiet-default guard, at the string level.
|
|
369
369
|
/** Pi extension source — written to ~/.pi/agent/extensions/zeph.ts (drop-in auto-load). */
|
|
370
370
|
exports.PI_EXTENSION = `// Generated by @zeph-to/cli — reinstall overwrites; \`zeph uninstall\` removes.
|
|
371
|
-
import { spawn } from "node:child_process";
|
|
371
|
+
import { spawn, execFileSync } from "node:child_process";
|
|
372
372
|
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
373
373
|
|
|
374
374
|
const sh = (cmd: string, cwd: string, stdin?: string): Promise<string> =>
|
|
@@ -406,12 +406,32 @@ const pushHigh = (cwd: string, title: string, body: string): void => {
|
|
|
406
406
|
...process.env,
|
|
407
407
|
ZEPH_PUSH_TITLE: title,
|
|
408
408
|
ZEPH_PUSH_BODY: body.length > 200 ? body.slice(0, 199) + "…" : body,
|
|
409
|
+
...(SUBAGENT_SESSION ? { ZEPH_AGENT_SESSION_NAME: SUBAGENT_SESSION } : {}),
|
|
409
410
|
};
|
|
410
411
|
const child = spawn("sh", ["-c", ${JSON.stringify(highNotifyCmd)}], { cwd, env, stdio: "ignore", detached: true });
|
|
411
412
|
child.on("error", () => {});
|
|
412
413
|
child.unref();
|
|
413
414
|
};
|
|
414
415
|
|
|
416
|
+
// Subagent mode: pi spawned this process as a subagent (PI_SUBAGENT_NAME set
|
|
417
|
+
// by the spawner). Label this tmux pane so the listener's sweep picks the name
|
|
418
|
+
// up, and file pushes under the subagent's own session key
|
|
419
|
+
// (<parent session>.<pane id>) — the listener's naming — instead of the
|
|
420
|
+
// parent's, so a phone push opens the subagent's stream, not the parent's.
|
|
421
|
+
const SUBAGENT_NAME = process.env.PI_SUBAGENT_NAME || "";
|
|
422
|
+
const SUBAGENT_SESSION = (() => {
|
|
423
|
+
if (!SUBAGENT_NAME || !process.env.TMUX_PANE) return "";
|
|
424
|
+
try {
|
|
425
|
+
const pane = spawn("tmux", ["set-option", "-p", "-t", process.env.TMUX_PANE, "@zeph_pane_label", SUBAGENT_NAME], { stdio: "ignore", detached: true });
|
|
426
|
+
pane.on("error", () => {});
|
|
427
|
+
pane.unref();
|
|
428
|
+
// Targeted at this pane and bounded: this runs while pi loads, so a
|
|
429
|
+
// wedged tmux server must cost at most 2s, never the whole startup.
|
|
430
|
+
const s = execFileSync("tmux", ["display-message", "-p", "-t", process.env.TMUX_PANE, "#S"], { encoding: "utf8", timeout: 2000 }).trim();
|
|
431
|
+
return s ? s + "." + process.env.TMUX_PANE.slice(1) : "";
|
|
432
|
+
} catch { return ""; }
|
|
433
|
+
})();
|
|
434
|
+
|
|
415
435
|
export default function (pi: ExtensionAPI) {
|
|
416
436
|
// Turn facts for the push gate. One agent per process, so plain counters
|
|
417
437
|
// suffice — no session keying.
|
|
@@ -467,7 +487,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
467
487
|
?? (running ? running.toolName + " is waiting for your answer" : "Waiting for your input");
|
|
468
488
|
promptTimer = setTimeout(() => {
|
|
469
489
|
promptTimer = undefined;
|
|
470
|
-
pushHigh(ctx.cwd, "pi asks: " + projectOf(ctx.cwd), body);
|
|
490
|
+
pushHigh(ctx.cwd, "pi asks: " + projectOf(ctx.cwd) + (SUBAGENT_NAME ? " · " + SUBAGENT_NAME : ""), body);
|
|
471
491
|
}, PROMPT_GRACE_MS);
|
|
472
492
|
promptTimer.unref?.();
|
|
473
493
|
});
|
|
@@ -481,6 +501,11 @@ export default function (pi: ExtensionAPI) {
|
|
|
481
501
|
agentRunning = false;
|
|
482
502
|
clearTimeout(promptTimer);
|
|
483
503
|
promptTimer = undefined;
|
|
504
|
+
// A subagent never pushes — not its completion, not its error. The parent
|
|
505
|
+
// settles on their results (4 parallel subagents would otherwise mean 4
|
|
506
|
+
// simultaneous pushes), and an error stays live in the subagent's own
|
|
507
|
+
// stream, which the phone is already mirroring.
|
|
508
|
+
if (SUBAGENT_NAME) return;
|
|
484
509
|
// Esc (at the terminal, or a key sent from the phone): whoever stopped the
|
|
485
510
|
// turn is already looking at it.
|
|
486
511
|
if (stop?.reason === "aborted") return;
|
package/dist/zeph-hook.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"zeph-hook.d.ts","sourceRoot":"","sources":["../src/zeph-hook.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,YAAY,EAAE,UAAU,EAAE,UAAU,EAAY,gBAAgB,EAAE,gBAAgB,EAAoB,mBAAmB,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"zeph-hook.d.ts","sourceRoot":"","sources":["../src/zeph-hook.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,YAAY,EAAE,UAAU,EAAE,UAAU,EAAY,gBAAgB,EAAE,gBAAgB,EAAoB,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAyCxL,qBAAa,QAAQ;IACnB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IAEnC,OAAO,CAAC,iBAAiB,CAAS;gBAEtB,OAAO,EAAE,WAAW;IAShC;;;;;;;;OAQG;YACW,YAAY;IAyB1B;;;;;;;;;;;OAWG;IACG,MAAM,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC;YAgB7C,UAAU;YAyCV,cAAc;IA6DtB,aAAa,CAAC,MAAM,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAK7G,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAcrF,IAAI,CAAC,MAAM,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC;IAuB9C,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAKlD,UAAU,IAAI,OAAO,CAAC,gBAAgB,CAAC;IAK7C;;;;OAIG;IACG,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;YASxF,OAAO;IAiCrB,OAAO,CAAC,UAAU;CASnB"}
|
package/dist/zeph-hook.js
CHANGED
|
@@ -21,6 +21,12 @@ const PREVIEW_LENGTH = 200;
|
|
|
21
21
|
const agentSessionContext = () => {
|
|
22
22
|
if (!process.env.TMUX)
|
|
23
23
|
return null;
|
|
24
|
+
// A pi subagent pane carries its own wire name (<#S>.<pane> — the
|
|
25
|
+
// listener's naming) in this env, set by the extension for its notify
|
|
26
|
+
// children. It wins over #S, which would file the push under the parent.
|
|
27
|
+
const fromEnv = process.env.ZEPH_AGENT_SESSION_NAME?.trim();
|
|
28
|
+
if (fromEnv)
|
|
29
|
+
return { agentDeviceId: (0, listener_device_id_js_1.listenerDeviceId)(), agentSessionName: fromEnv };
|
|
24
30
|
let name;
|
|
25
31
|
try {
|
|
26
32
|
name = (0, node_child_process_1.execFileSync)('tmux', ['display-message', '-p', '#S'], { encoding: 'utf-8' }).trim();
|