@zeph-to/cli 2.14.0 → 2.16.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.
@@ -39,6 +39,17 @@ export interface RemoteAgent {
39
39
  * name at all, so there is nothing to read and the computed label stands.
40
40
  */
41
41
  resolveSessionName?: (paneCwd: string, panePid?: number) => string | null;
42
+ /**
43
+ * Resolve the file this agent is writing its session transcript to, for the
44
+ * live chat timeline (`turn-watch`).
45
+ *
46
+ * Same shape and the same EXTENSION POINT rule as the two above: a row
47
+ * carries this only once that agent's transcript format is confirmed, and a
48
+ * pane whose agent omits it answers `no_transcript` rather than guessing.
49
+ * That is the seam a second agent hangs off — the reader that parses the
50
+ * file is the other half, and lives beside this one.
51
+ */
52
+ resolveTranscript?: (paneCwd: string, panePid?: number) => string | null;
42
53
  }
43
54
  /**
44
55
  * Locate the most recent Claude Code session UUID for the working
@@ -91,6 +102,15 @@ export interface PidResolveDeps {
91
102
  records?: PidSessionRecord[];
92
103
  descendants?: Set<number>;
93
104
  }
105
+ /**
106
+ * Whether this machine's Claude Code writes `~/.claude/sessions` records at all.
107
+ *
108
+ * The difference between "no records anywhere" (an older CC — the mtime
109
+ * heuristic is the only option) and "records exist, none match this pane" (the
110
+ * pane is not a Claude session) is the difference between a useful fallback and
111
+ * a wrong answer, so callers that care ask it explicitly.
112
+ */
113
+ export declare const pidSessionRecordsExist: () => boolean;
94
114
  /**
95
115
  * Exact resolution: the session record whose pid lives in the pane's
96
116
  * process tree AND whose cwd matches (guards against OS pid reuse
@@ -110,6 +130,20 @@ export declare const detectClaudeSessionIdByPid: (panePid: number, paneCwd: stri
110
130
  * keeps the computed label.
111
131
  */
112
132
  export declare const detectClaudeSessionNameByPid: (panePid: number, paneCwd: string | null, deps?: PidResolveDeps) => string | null;
133
+ /**
134
+ * The transcript file for the Claude Code session running in a tmux pane.
135
+ *
136
+ * Pid first, cwd only as a fallback, and the order is the whole point: the cwd
137
+ * heuristic picks the newest `*.jsonl` in the directory, so a second `claude`
138
+ * started in the same repo steals the first one's transcript (the comment above
139
+ * `detectClaudeSessionIdByPid` records that failure). Live-timeline viewers are
140
+ * per tmux session, so two sessions in one directory must resolve to two files
141
+ * or each phone reads the other's work.
142
+ *
143
+ * Returns null when this pane is not running Claude Code at all — a Codex or
144
+ * Gemini pane has no transcript here, and that is an answer, not a failure.
145
+ */
146
+ export declare const claudeTranscriptPath: (paneCwd: string | null, panePid?: number) => string | null;
113
147
  /**
114
148
  * The row whose timestamp is closest to when one of the pane's processes started,
115
149
  * within {@link PROC_MATCH_TOLERANCE_MS}. Null when nothing qualifies — including
@@ -164,6 +198,7 @@ declare const REMOTE_AGENT_TABLE: readonly [{
164
198
  readonly quitCommand: "/exit";
165
199
  readonly resolveSessionId: (paneCwd: string, panePid: number | undefined) => string | null;
166
200
  readonly resolveSessionName: (paneCwd: string, panePid: number | undefined) => string | null;
201
+ readonly resolveTranscript: (paneCwd: string, panePid: number | undefined) => string | null;
167
202
  }, {
168
203
  readonly kind: "codex";
169
204
  readonly displayName: "Codex CLI";
@@ -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":"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"}
@@ -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.detectClaudeSessionNameByPid = exports.detectClaudeSessionIdByPid = exports.detectClaudeSessionByPid = 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.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
@@ -248,6 +248,16 @@ const collectDescendantPids = (rootPid) => {
248
248
  return descendantCache.set(rootPid, walkDescendants(rootPid, children));
249
249
  };
250
250
  exports.collectDescendantPids = collectDescendantPids;
251
+ /**
252
+ * Whether this machine's Claude Code writes `~/.claude/sessions` records at all.
253
+ *
254
+ * The difference between "no records anywhere" (an older CC — the mtime
255
+ * heuristic is the only option) and "records exist, none match this pane" (the
256
+ * pane is not a Claude session) is the difference between a useful fallback and
257
+ * a wrong answer, so callers that care ask it explicitly.
258
+ */
259
+ const pidSessionRecordsExist = () => cachedPidSessionRecords().length > 0;
260
+ exports.pidSessionRecordsExist = pidSessionRecordsExist;
251
261
  /**
252
262
  * Exact resolution: the session record whose pid lives in the pane's
253
263
  * process tree AND whose cwd matches (guards against OS pid reuse
@@ -276,6 +286,54 @@ exports.detectClaudeSessionIdByPid = detectClaudeSessionIdByPid;
276
286
  */
277
287
  const detectClaudeSessionNameByPid = (panePid, paneCwd, deps = {}) => nonBlank((0, exports.detectClaudeSessionByPid)(panePid, paneCwd, deps)?.name);
278
288
  exports.detectClaudeSessionNameByPid = detectClaudeSessionNameByPid;
289
+ /**
290
+ * The transcript file for the Claude Code session running in a tmux pane.
291
+ *
292
+ * Pid first, cwd only as a fallback, and the order is the whole point: the cwd
293
+ * heuristic picks the newest `*.jsonl` in the directory, so a second `claude`
294
+ * started in the same repo steals the first one's transcript (the comment above
295
+ * `detectClaudeSessionIdByPid` records that failure). Live-timeline viewers are
296
+ * per tmux session, so two sessions in one directory must resolve to two files
297
+ * or each phone reads the other's work.
298
+ *
299
+ * Returns null when this pane is not running Claude Code at all — a Codex or
300
+ * Gemini pane has no transcript here, and that is an answer, not a failure.
301
+ */
302
+ const claudeTranscriptPath = (paneCwd, panePid) => {
303
+ if (!paneCwd)
304
+ return null;
305
+ let sessionId = null;
306
+ if (panePid) {
307
+ sessionId = (0, exports.detectClaudeSessionIdByPid)(panePid, paneCwd);
308
+ // Records exist but this pane matched none: the pane is not running
309
+ // Claude Code, or its record has not landed yet. Falling through to the
310
+ // mtime heuristic here is what lets a *second* `claude` in the same
311
+ // directory hand this pane the other session's transcript — and a
312
+ // viewer reading another session's work is worse than one reading none.
313
+ // Only an installation that writes no records at all earns the fallback.
314
+ if (!sessionId && (0, exports.pidSessionRecordsExist)())
315
+ return null;
316
+ }
317
+ sessionId ??= (0, exports.detectClaudeSessionId)(paneCwd);
318
+ if (!sessionId)
319
+ return null;
320
+ // Claude Code flattens the cwd into one directory name by replacing every
321
+ // `/` AND `.` with `-`: `/Users/x/.claude-mem/y` becomes
322
+ // `-Users-x--claude-mem-y`. Encoding only the slashes yields a path that
323
+ // never exists, and the watcher would then poll a missing file forever
324
+ // without ever saying so.
325
+ const projectDir = (0, path_1.join)(CLAUDE_PROJECTS_DIR, paneCwd.replace(/[/.]/g, '-'));
326
+ const path = (0, path_1.join)(projectDir, `${sessionId}.jsonl`);
327
+ // Prove it before handing it out. The pid path never touches the filesystem,
328
+ // so without this a mis-encoded directory reads as a healthy silent session.
329
+ try {
330
+ return (0, fs_1.statSync)(path).isFile() ? path : null;
331
+ }
332
+ catch {
333
+ return null;
334
+ }
335
+ };
336
+ exports.claudeTranscriptPath = claudeTranscriptPath;
279
337
  // ── Agents whose session store keeps no pid ──────────────────────
280
338
  //
281
339
  // Hermes and Codex both record a session per cwd with a creation timestamp and
@@ -437,6 +495,7 @@ const REMOTE_AGENT_TABLE = [
437
495
  resolveSessionId: (paneCwd, panePid) => (panePid !== undefined ? (0, exports.detectClaudeSessionIdByPid)(panePid, paneCwd) : null)
438
496
  ?? (0, exports.detectClaudeSessionId)(paneCwd),
439
497
  resolveSessionName: (paneCwd, panePid) => panePid !== undefined ? (0, exports.detectClaudeSessionNameByPid)(panePid, paneCwd) : null,
498
+ resolveTranscript: (paneCwd, panePid) => (0, exports.claudeTranscriptPath)(paneCwd, panePid),
440
499
  },
441
500
  {
442
501
  kind: 'codex',
@@ -66,7 +66,14 @@ export declare const rememberSessions: (live: Array<{
66
66
  * running, so nothing re-adds an entry for a session that has ended. Running
67
67
  * that name again is what brings it back, which is also the only way back.
68
68
  */
69
- export declare const forgetSession: (name: string) => boolean;
69
+ export type ForgetOutcome =
70
+ /** This machine never had a record under that name. */
71
+ 'unknown'
72
+ /** Registry entry and chat scrollback both gone. */
73
+ | 'forgotten'
74
+ /** Registry entry gone, but the scrollback file would not delete. */
75
+ | 'scrollback_kept';
76
+ export declare const forgetSession: (name: string) => ForgetOutcome;
70
77
  /** Whether the registry knows this name — the resume whitelist check. */
71
78
  export declare const isKnownSession: (name: string, now?: number) => boolean;
72
79
  /** Test seam: the file this module reads and writes. */
@@ -1 +1 @@
1
- {"version":3,"file":"session-registry.d.ts","sourceRoot":"","sources":["../src/session-registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAMH,MAAM,WAAW,YAAY;IACzB,uDAAuD;IACvD,IAAI,EAAE,MAAM,CAAC;IACb,0EAA0E;IAC1E,GAAG,EAAE,MAAM,CAAC;IACZ,gFAAgF;IAChF,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,sDAAsD;IACtD,UAAU,EAAE,MAAM,CAAC;CACtB;AAED;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,MAAM,CAAC;AACtC;2DAC2D;AAC3D,eAAO,MAAM,oBAAoB,QAA2B,CAAC;AAsC7D,0EAA0E;AAC1E,eAAO,MAAM,aAAa,GAAI,MAAK,MAAmB,KAAG,YAAY,EAGJ,CAAC;AAElE,6EAA6E;AAC7E,eAAO,MAAM,aAAa,GAAI,MAAM,MAAM,EAAE,MAAK,MAAmB,KAAG,YAAY,GAAG,IAC3B,CAAC;AAE5D;;;;;;;;GAQG;AACH,eAAO,MAAM,gBAAgB,GACzB,MAAM,KAAK,CAAC;IACR,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB,CAAC,EACF,MAAK,MAAmB,KACzB,IAmBF,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,aAAa,GAAI,MAAM,MAAM,KAAG,OAM5C,CAAC;AAEF,yEAAyE;AACzE,eAAO,MAAM,cAAc,GAAI,MAAM,MAAM,EAAE,MAAK,MAAmB,KAAG,OACnC,CAAC;AAEtC,wDAAwD;AACxD,eAAO,MAAM,iBAAiB,QA9GL,MA8GoB,CAAC;AAE9C,0EAA0E;AAC1E,eAAO,MAAM,sBAAsB,GAAI,OAAO,YAAY,KAAG,OAAgC,CAAC"}
1
+ {"version":3,"file":"session-registry.d.ts","sourceRoot":"","sources":["../src/session-registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAOH,MAAM,WAAW,YAAY;IACzB,uDAAuD;IACvD,IAAI,EAAE,MAAM,CAAC;IACb,0EAA0E;IAC1E,GAAG,EAAE,MAAM,CAAC;IACZ,gFAAgF;IAChF,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,sDAAsD;IACtD,UAAU,EAAE,MAAM,CAAC;CACtB;AAED;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,MAAM,CAAC;AACtC;2DAC2D;AAC3D,eAAO,MAAM,oBAAoB,QAA2B,CAAC;AAsC7D,0EAA0E;AAC1E,eAAO,MAAM,aAAa,GAAI,MAAK,MAAmB,KAAG,YAAY,EAGJ,CAAC;AAElE,6EAA6E;AAC7E,eAAO,MAAM,aAAa,GAAI,MAAM,MAAM,EAAE,MAAK,MAAmB,KAAG,YAAY,GAAG,IAC3B,CAAC;AAE5D;;;;;;;;GAQG;AACH,eAAO,MAAM,gBAAgB,GACzB,MAAM,KAAK,CAAC;IACR,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB,CAAC,EACF,MAAK,MAAmB,KACzB,IAmBF,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,aAAa;AACrB,uDAAuD;AACrD,SAAS;AACX,oDAAoD;GAClD,WAAW;AACb,qEAAqE;GACnE,iBAAiB,CAAC;AAExB,eAAO,MAAM,aAAa,GAAI,MAAM,MAAM,KAAG,aAU5C,CAAC;AAEF,yEAAyE;AACzE,eAAO,MAAM,cAAc,GAAI,MAAM,MAAM,EAAE,MAAK,MAAmB,KAAG,OACnC,CAAC;AAEtC,wDAAwD;AACxD,eAAO,MAAM,iBAAiB,QA1HL,MA0HoB,CAAC;AAE9C,0EAA0E;AAC1E,eAAO,MAAM,sBAAsB,GAAI,OAAO,YAAY,KAAG,OAAgC,CAAC"}
@@ -17,6 +17,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
17
17
  exports.sessionDirectoryExists = exports.knownSessionsPath = exports.isKnownSession = exports.forgetSession = exports.rememberSessions = exports.recallSession = exports.knownSessions = exports.KNOWN_SESSION_TTL_MS = exports.MAX_KNOWN_SESSIONS = void 0;
18
18
  const fs_1 = require("fs");
19
19
  const path_1 = require("path");
20
+ const turn_ring_js_1 = require("./turn-ring.js");
20
21
  const gate_js_1 = require("./gate.js");
21
22
  /**
22
23
  * Ceiling on remembered sessions. tmux names come from a small reused pool
@@ -100,25 +101,17 @@ const rememberSessions = (live, now = Date.now()) => {
100
101
  writeAll(entries);
101
102
  };
102
103
  exports.rememberSessions = rememberSessions;
103
- /**
104
- * Forget one session, by name. Returns false when this machine never knew it.
105
- *
106
- * This is what deleting a past session means on the machine that ran it: the
107
- * entry leaves the file, so the phone stops being offered the session AND —
108
- * since this file is the resume whitelist — stops being able to start it.
109
- * That is the intended pair, not a side effect.
110
- *
111
- * It stays forgotten: `rememberSessions` only writes down sessions that are
112
- * running, so nothing re-adds an entry for a session that has ended. Running
113
- * that name again is what brings it back, which is also the only way back.
114
- */
115
104
  const forgetSession = (name) => {
116
105
  const entries = readAll();
117
106
  const kept = entries.filter((e) => e.name !== name);
118
107
  if (kept.length === entries.length)
119
- return false;
108
+ return 'unknown';
120
109
  writeAll(kept);
121
- return true;
110
+ // The chat's scrollback for that session goes with it. Forgetting a session
111
+ // everywhere except the one file that holds a week of its prompts and tool
112
+ // targets is not forgetting it — and a failure to delete that file has to
113
+ // reach the person who asked, not stay in a swallowed catch.
114
+ return (0, turn_ring_js_1.removeTurnRing)(name) ? 'forgotten' : 'scrollback_kept';
122
115
  };
123
116
  exports.forgetSession = forgetSession;
124
117
  /** Whether the registry knows this name — the resume whitelist check. */
@@ -1 +1 @@
1
- {"version":3,"file":"templates.d.ts","sourceRoot":"","sources":["../src/templates.ts"],"names":[],"mappings":"AA4KA,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,QAsDxB,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"}
1
+ {"version":3,"file":"templates.d.ts","sourceRoot":"","sources":["../src/templates.ts"],"names":[],"mappings":"AA6KA,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,QAsDxB,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
@@ -43,8 +43,9 @@ const zeph_core_generated_js_1 = require("./zeph-core.generated.js");
43
43
  // `--pushmode-default normal` is what keeps the first half of that true. The
44
44
  // built-in default for a project with no dial is quiet, and quiet only lets a
45
45
  // `high` Push Signal marker through — a marker these hooks have no way to
46
- // emit. Without the flag they would install and then never push again. The
47
- // user's own dial still outranks it, so /zeph-quiet keeps working here.
46
+ // emit or a turn the user was away for (presence.ts). Without the flag they
47
+ // would install and then stay silent whenever the user is at the terminal.
48
+ // The user's own dial still outranks it, so /zeph-quiet keeps working here.
48
49
  //
49
50
  // Older installed `zeph` versions parse both flags as unknown booleans and
50
51
  // ignore them — graceful backward compatibility, and for `--pushmode-default`
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Point `stateDir()` at a throwaway directory for the length of one suite.
3
+ *
4
+ * Both files that keep state under `stateDir()` need this and both had rolled
5
+ * it by hand, restore-else-delete included. Modules that read the env at call
6
+ * time (`gate.ts`'s `stateDir`) can be imported normally; only ones that freeze
7
+ * a path at module scope need the dynamic-import dance.
8
+ */
9
+ export declare const withTmpStateDir: (prefix: string) => (() => string);
10
+ //# sourceMappingURL=test-state-dir.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-state-dir.d.ts","sourceRoot":"","sources":["../src/test-state-dir.ts"],"names":[],"mappings":"AAKA;;;;;;;GAOG;AACH,eAAO,MAAM,eAAe,GAAI,QAAQ,MAAM,KAAG,CAAC,MAAM,MAAM,CAa7D,CAAC"}
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.withTmpStateDir = void 0;
4
+ const fs_1 = require("fs");
5
+ const os_1 = require("os");
6
+ const path_1 = require("path");
7
+ const vitest_1 = require("vitest");
8
+ /**
9
+ * Point `stateDir()` at a throwaway directory for the length of one suite.
10
+ *
11
+ * Both files that keep state under `stateDir()` need this and both had rolled
12
+ * it by hand, restore-else-delete included. Modules that read the env at call
13
+ * time (`gate.ts`'s `stateDir`) can be imported normally; only ones that freeze
14
+ * a path at module scope need the dynamic-import dance.
15
+ */
16
+ const withTmpStateDir = (prefix) => {
17
+ let dir = '';
18
+ const original = process.env.XDG_STATE_HOME;
19
+ (0, vitest_1.beforeEach)(() => {
20
+ dir = (0, fs_1.mkdtempSync)((0, path_1.join)((0, os_1.tmpdir)(), prefix));
21
+ process.env.XDG_STATE_HOME = dir;
22
+ });
23
+ (0, vitest_1.afterEach)(() => {
24
+ (0, fs_1.rmSync)(dir, { recursive: true, force: true });
25
+ if (original === undefined)
26
+ delete process.env.XDG_STATE_HOME;
27
+ else
28
+ process.env.XDG_STATE_HOME = original;
29
+ });
30
+ return () => dir;
31
+ };
32
+ exports.withTmpStateDir = withTmpStateDir;
@@ -0,0 +1,147 @@
1
+ /**
2
+ * Claude Code session transcript (`~/.claude/projects/<hash>/<uuid>.jsonl`) →
3
+ * the small events the agent chat timeline draws.
4
+ *
5
+ * Two pure pieces, deliberately split: reading bytes off a growing file, and
6
+ * deciding what of it is worth putting on the wire. Neither touches the socket,
7
+ * so both are testable without tmux, WebSocket, or a clock.
8
+ *
9
+ * Everything here is sized by what a real transcript actually contains, measured
10
+ * 2026-09-08 over 1443 files in `~/.claude/projects`: the largest file was
11
+ * 75.9 MB (p90 1.1 MB) and the longest single line 915,292 bytes. Those two
12
+ * numbers are why the reader starts near the end and refuses oversized lines
13
+ * before parsing them — a tail that starts at byte 0, or that hands a ~1 MB
14
+ * string to `JSON.parse` and only then decides to drop it, has already paid the
15
+ * cost the cap exists to avoid.
16
+ */
17
+ /**
18
+ * How far back from the end of the file the first read starts.
19
+ *
20
+ * Not zero: a fresh viewer that sees nothing until the *next* tool call is a
21
+ * blank screen for whoever just picked up their phone mid-turn. Not the whole
22
+ * file either — that is up to 75.9 MB. A fixed window from the end costs the
23
+ * same on an 8 KB transcript and a 76 MB one.
24
+ */
25
+ export declare const TRANSCRIPT_BACKFILL_BYTES: number;
26
+ /** Ceiling on one tick's read, so a burst of appends cannot be swallowed whole. */
27
+ export declare const MAX_TAIL_BYTES_PER_TICK: number;
28
+ /**
29
+ * A line longer than this is abandoned unparsed, the reader skipping to the next
30
+ * newline. The measured worst case is a 915 KB `tool_result`, whose body this
31
+ * module drops anyway — buffering one to completion would be paying megabytes to
32
+ * learn a tool id.
33
+ */
34
+ export declare const MAX_TRANSCRIPT_LINE_CHARS: number;
35
+ /**
36
+ * Ceiling on a tool's label — its name, and the short string saying what it
37
+ * acted on. A path or a one-line description; anything longer is a runaway
38
+ * input, not a label.
39
+ */
40
+ export declare const MAX_EVENT_FIELD_CHARS = 512;
41
+ /**
42
+ * Ceiling on prose — what the agent wrote, and what the person asked.
43
+ *
44
+ * Deliberately far above the label cap: 512 characters is a filename, and
45
+ * applying it here cut every reply off mid-sentence. 5000 is what the
46
+ * completion push already carries for the same text (`zeph-stop.sh`), so the
47
+ * live lane and the push that replaces it agree on how much of a reply is
48
+ * worth sending.
49
+ */
50
+ export declare const MAX_EVENT_TEXT_CHARS = 5000;
51
+ /**
52
+ * Where the reader is in one file.
53
+ *
54
+ * `size`/`mtimeMs` are the skip check: when neither moved there is nothing to
55
+ * read, and the tick returns without allocating. Since idle is this watcher's
56
+ * normal state, that check is what keeps it off the GC's back.
57
+ */
58
+ export interface TailState {
59
+ readonly offset: number;
60
+ readonly size: number;
61
+ readonly mtimeMs: number;
62
+ /** Which file this offset belongs to. A new inode is a new file at the same path. */
63
+ readonly ino: number;
64
+ /** Bytes after the last newline seen — an incomplete line, held for the next tick. */
65
+ readonly carry: string;
66
+ /** Inside an oversized line: discard bytes until the next newline. */
67
+ readonly resyncing: boolean;
68
+ }
69
+ export interface TailRead {
70
+ /** Whole lines, in file order. Never includes a partial line. */
71
+ readonly lines: string[];
72
+ readonly state: TailState;
73
+ readonly bytesRead: number;
74
+ /** Lines abandoned for exceeding MAX_TRANSCRIPT_LINE_CHARS. */
75
+ readonly droppedLines: number;
76
+ }
77
+ /**
78
+ * No state yet. `null` rather than a sentinel-filled record: "never read this
79
+ * file" and "read it and got nothing" are different, and an out-of-band value
80
+ * that has to stay below every real offset is a trap for the next `>=`.
81
+ */
82
+ export declare const initialTailState: () => TailState | null;
83
+ /**
84
+ * Read what was appended since `prev`, or `null` when there is nothing to do —
85
+ * the file is unreadable, or neither its size nor its mtime moved.
86
+ *
87
+ * `null` is the common case (an idle session) and is deliberately allocation
88
+ * free: no buffer, no string, no array.
89
+ */
90
+ export declare const readTranscriptDelta: (path: string, prev: TailState | null) => TailRead | null;
91
+ /**
92
+ * What the timeline draws. Stateless by design: a `tool_result` arrives as its
93
+ * own event rather than mutating an earlier one, because the call it answers is
94
+ * routinely in a previous tick's batch — merging by `id` is the viewer's job,
95
+ * and it is the only side that holds the whole turn.
96
+ */
97
+ /**
98
+ * `at` is the transcript entry's own timestamp, carried so the viewer can place
99
+ * a live turn among the pushes in time order instead of parking the whole live
100
+ * block below them — where a message sent while reading lands above the turn it
101
+ * answers.
102
+ */
103
+ export type TurnEvent = {
104
+ at?: string;
105
+ } & ({
106
+ kind: 'tool';
107
+ id: string;
108
+ name: string;
109
+ target?: string;
110
+ } | {
111
+ kind: 'tool_result';
112
+ id: string;
113
+ ok: boolean;
114
+ } | {
115
+ kind: 'text';
116
+ text: string;
117
+ } | {
118
+ kind: 'prompt';
119
+ text: string;
120
+ });
121
+ /**
122
+ * Turn raw JSONL lines into wire events.
123
+ *
124
+ * Nothing a tool read or wrote survives this function: only the tool's name, a
125
+ * short label for what it acted on, and whether it worked. That is the whole
126
+ * privacy story of the feature — the transcript holds file contents and command
127
+ * output, and this is the one place that decides none of it leaves the machine.
128
+ *
129
+ * `sinceLastPrompt` is for the backfill window: finished turns already exist in
130
+ * the chat as their completion pushes, so replaying them would double every
131
+ * message. Only the turn still in flight is new information.
132
+ *
133
+ * The prompt a person typed IS carried, unlike anything a tool read or wrote.
134
+ * It is their own words, it is the same class of content the completion push
135
+ * already sends, and without it the timeline is a list of tool names with no
136
+ * record of what was asked.
137
+ *
138
+ * Everything here — the block shapes, the entry types, `TARGET_KEYS` — is Claude
139
+ * Code's transcript format. Supporting another agent (pi, Codex) means a
140
+ * projector of its own alongside this one, reached the way `REMOTE_AGENTS`
141
+ * already reaches per-agent session resolvers; `turn-watch` takes the reader as
142
+ * a dependency and needs no change for it.
143
+ */
144
+ export declare const projectTranscriptEntries: (lines: readonly string[], opts?: {
145
+ sinceLastPrompt?: boolean;
146
+ }) => TurnEvent[];
147
+ //# sourceMappingURL=transcript-tail.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transcript-tail.d.ts","sourceRoot":"","sources":["../src/transcript-tail.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAIH;;;;;;;GAOG;AACH,eAAO,MAAM,yBAAyB,QAAa,CAAC;AAEpD,mFAAmF;AACnF,eAAO,MAAM,uBAAuB,QAAa,CAAC;AAElD;;;;;GAKG;AACH,eAAO,MAAM,yBAAyB,QAAc,CAAC;AAErD;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,MAAM,CAAC;AAEzC;;;;;;;;GAQG;AACH,eAAO,MAAM,oBAAoB,OAAO,CAAC;AAEzC;;;;;;GAMG;AACH,MAAM,WAAW,SAAS;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,qFAAqF;IACrF,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,sFAAsF;IACtF,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,sEAAsE;IACtE,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;CAC/B;AAED,MAAM,WAAW,QAAQ;IACrB,iEAAiE;IACjE,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,+DAA+D;IAC/D,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CACjC;AAoBD;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,QAAO,SAAS,GAAG,IAAY,CAAC;AAE7D;;;;;;GAMG;AACH,eAAO,MAAM,mBAAmB,GAAI,MAAM,MAAM,EAAE,MAAM,SAAS,GAAG,IAAI,KAAG,QAAQ,GAAG,IAuHrF,CAAC;AAIF;;;;;GAKG;AACH;;;;;GAKG;AACH,MAAM,MAAM,SAAS,GAAG;IAAE,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,CACpC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAC3D;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,OAAO,CAAA;CAAE,GAChD;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC9B;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CACrC,CAAC;AA4HF;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,eAAO,MAAM,wBAAwB,GACjC,OAAO,SAAS,MAAM,EAAE,EACxB,OAAM;IAAE,eAAe,CAAC,EAAE,OAAO,CAAA;CAAO,KACzC,SAAS,EAwDX,CAAC"}