@zswarm/core 0.4.2 → 0.6.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/dist/index.d.ts CHANGED
@@ -5,11 +5,12 @@ export { createGitClient, defaultWorktreeRoot, normalizeRepoPath, parseWorktreeL
5
5
  export { expandHomePath, looksLikeZswarmBinary, isZellijVersionOutput, resolveZellijBinary, resetZellijIdentityCache, sanitizeZellijEnv, validateSshDestination, validateSshMode, type ZellijExecFn, type ZellijExecResult, } from "./zellij/binary.js";
6
6
  export { normalizePaneId, parsePaneList, resolvePane, type ZellijPane, } from "./zellij/panes.js";
7
7
  export { liveSessionNames, parseCreatedAge, parseSessionList, resolveSelfPaneId, resolveSelfSession, type ZellijSession, type ZellijSessionResolve, } from "./zellij/session.js";
8
- export { buildClosePaneArgs, buildDumpArgs, buildLaunchPluginArgs, buildListPanesArgs, buildNewPaneArgs, buildNewTabArgs, buildPasteArgs, buildPipeArgs, buildSendEnterArgs, buildSendKeysArgs, buildWriteCharsArgs, scrollbackPayload, waitPayload, type LaunchPluginInput, type NewPaneInput, type NewTabInput, type PaneDirection, type PipeInput, type ScrollbackRequest, type WaitRequest, } from "./zellij/args.js";
8
+ export { assignServersToSessions, findAncestorServer, liveServers, matchServerToSession, paneMatchesId, parseServerArgs, readProcessTable, type ProcInfo, type ProcessRunner, type ReadProcessTableOptions, type ServerInfo, type SessionPanes, } from "./zellij/server-identity.js";
9
+ export { buildClosePaneArgs, buildDumpArgs, buildLaunchPluginArgs, buildListPanesArgs, buildNewPaneArgs, buildNewTabArgs, buildPasteArgs, buildPipeArgs, buildRenameSessionArgs, buildSendEnterArgs, buildSendKeysArgs, buildWriteCharsArgs, scrollbackPayload, waitPayload, type LaunchPluginInput, type NewPaneInput, type NewTabInput, type PaneDirection, type PipeInput, type ScrollbackRequest, type WaitRequest, } from "./zellij/args.js";
9
10
  export { busPluginUrl, busToPanes, isBusPluginPane, nextConfigKey, parseBusReply, parseScrollbackReply, resolveBusPlugin, scrollbackToScreen, BUS_PIPE_NAME, DEFAULT_BUS_KEY, DEFAULT_BUS_TIMEOUT_MS, type BusMarker, type BusPane, type BusScrollback, type BusScrollbackPane, type BusSnapshot, } from "./zellij/bus.js";
10
11
  export { busSnapshot, closeBusPluginPanes, planBus, resetBusCache, type BusPlan, } from "./ops/bus.js";
11
- export { createZellijClient, type ZellijClient, type ZellijClientOptions, type ZellijTransport, } from "./zellij/client.js";
12
- export { createStateStore, defaultStateDir, type LeaseRecord, type LogEntry, type SignalChannel, type StateStore, type StateStoreOptions, } from "./state.js";
12
+ export { createZellijClient, resetSelfResolutionCache, type ZellijClient, type ZellijClientOptions, type ZellijTransport, } from "./zellij/client.js";
13
+ export { createStateStore, defaultStateDir, type LeaseRecord, type LogEntry, type SessionAliasEntry, type SessionAliasMap, type SignalChannel, type StateStore, type StateStoreOptions, } from "./state.js";
13
14
  export { findLease, leaseKey, leaseStale, listLeases, releaseLease, releaseLeaseKey, takeLease, type LeaseTakeInput, type LeaseTakeResult, type LeaseTarget, } from "./host/lease.js";
14
15
  export { dispatchZswarm, resolveInvocationEnv } from "./ops/dispatch.js";
15
16
  export { EXIT_WAIT_MS, HANDOFF_INLINE_MAX, HANDOFF_MARKER, HANDOFF_SELF_WAIT_MS, READY_SETTLE_MS, READY_STABLE_GAP_MS, READY_WAIT_MS, restartLaunchCommand, restartPane, restartPaneKind, type RestartPaneKind, type RestartStep, } from "./ops/restart.js";
package/dist/index.js CHANGED
@@ -5,10 +5,11 @@ export { createGitClient, defaultWorktreeRoot, normalizeRepoPath, parseWorktreeL
5
5
  export { expandHomePath, looksLikeZswarmBinary, isZellijVersionOutput, resolveZellijBinary, resetZellijIdentityCache, sanitizeZellijEnv, validateSshDestination, validateSshMode, } from "./zellij/binary.js";
6
6
  export { normalizePaneId, parsePaneList, resolvePane, } from "./zellij/panes.js";
7
7
  export { liveSessionNames, parseCreatedAge, parseSessionList, resolveSelfPaneId, resolveSelfSession, } from "./zellij/session.js";
8
- export { buildClosePaneArgs, buildDumpArgs, buildLaunchPluginArgs, buildListPanesArgs, buildNewPaneArgs, buildNewTabArgs, buildPasteArgs, buildPipeArgs, buildSendEnterArgs, buildSendKeysArgs, buildWriteCharsArgs, scrollbackPayload, waitPayload, } from "./zellij/args.js";
8
+ export { assignServersToSessions, findAncestorServer, liveServers, matchServerToSession, paneMatchesId, parseServerArgs, readProcessTable, } from "./zellij/server-identity.js";
9
+ export { buildClosePaneArgs, buildDumpArgs, buildLaunchPluginArgs, buildListPanesArgs, buildNewPaneArgs, buildNewTabArgs, buildPasteArgs, buildPipeArgs, buildRenameSessionArgs, buildSendEnterArgs, buildSendKeysArgs, buildWriteCharsArgs, scrollbackPayload, waitPayload, } from "./zellij/args.js";
9
10
  export { busPluginUrl, busToPanes, isBusPluginPane, nextConfigKey, parseBusReply, parseScrollbackReply, resolveBusPlugin, scrollbackToScreen, BUS_PIPE_NAME, DEFAULT_BUS_KEY, DEFAULT_BUS_TIMEOUT_MS, } from "./zellij/bus.js";
10
11
  export { busSnapshot, closeBusPluginPanes, planBus, resetBusCache, } from "./ops/bus.js";
11
- export { createZellijClient, } from "./zellij/client.js";
12
+ export { createZellijClient, resetSelfResolutionCache, } from "./zellij/client.js";
12
13
  export { createStateStore, defaultStateDir, } from "./state.js";
13
14
  export { findLease, leaseKey, leaseStale, listLeases, releaseLease, releaseLeaseKey, takeLease, } from "./host/lease.js";
14
15
  export { dispatchZswarm, resolveInvocationEnv } from "./ops/dispatch.js";
@@ -26,8 +26,12 @@ export type SenderOrigin = {
26
26
  * splittable), and the result is capped at 64 chars.
27
27
  */
28
28
  export declare function sanitizeOriginPart(raw: unknown): string | null;
29
- /** The origin of the caller's own process, read from its environment. */
30
- export declare function resolveSenderOrigin(env: NodeJS.ProcessEnv): SenderOrigin;
29
+ /**
30
+ * The origin of the caller's own process, read from its environment.
31
+ * `session` overrides the env name when the caller has resolved the live
32
+ * session through the process table (a renamed session leaves the env stale).
33
+ */
34
+ export declare function resolveSenderOrigin(env: NodeJS.ProcessEnv, session?: string | null): SenderOrigin;
31
35
  /**
32
36
  * The origin carried by a serve request. Only the serve worker trusts it: a
33
37
  * local caller cannot claim another pane. Missing/garbage input (an older
@@ -20,8 +20,12 @@ export function sanitizeOriginPart(raw) {
20
20
  ? cleaned
21
21
  : cleaned.slice(0, ORIGIN_PART_MAX).replace(/_+$/, "");
22
22
  }
23
- /** The origin of the caller's own process, read from its environment. */
24
- export function resolveSenderOrigin(env) {
23
+ /**
24
+ * The origin of the caller's own process, read from its environment.
25
+ * `session` overrides the env name when the caller has resolved the live
26
+ * session through the process table (a renamed session leaves the env stale).
27
+ */
28
+ export function resolveSenderOrigin(env, session) {
25
29
  const configured = env.ZSWARM_HOST;
26
30
  const host = configured === undefined
27
31
  ? sanitizeOriginPart(hostname().split(".")[0])
@@ -30,7 +34,7 @@ export function resolveSenderOrigin(env) {
30
34
  : sanitizeOriginPart(configured);
31
35
  return {
32
36
  host,
33
- session: sanitizeOriginPart(resolveSelfSession(env)),
37
+ session: sanitizeOriginPart(session ?? resolveSelfSession(env)),
34
38
  pane: sanitizeOriginPart(resolveSelfPaneId(env)),
35
39
  via: null,
36
40
  };
@@ -216,6 +216,18 @@ async function unglueScreen(client, session, pane, text, full, fromBus) {
216
216
  }
217
217
  return unfoldScreen(ansi, columns) ?? text;
218
218
  }
219
+ /**
220
+ * Ops whose sender header or self-pane guard needs the caller's live session.
221
+ * Read-only ops never pay for that resolution.
222
+ */
223
+ const SELF_SESSION_OPS = new Set([
224
+ "send",
225
+ "broadcast",
226
+ "keys",
227
+ "interrupt",
228
+ "close",
229
+ "restart",
230
+ ]);
219
231
  async function dispatchOperation(args, injected, deps, context, env) {
220
232
  const op = String(args.op ?? "");
221
233
  const verbose = isVerbose(args);
@@ -322,10 +334,20 @@ async function dispatchOperation(args, injected, deps, context, env) {
322
334
  manager: deps.serveTunnels,
323
335
  });
324
336
  }
325
- const baseClient = injected ?? createZellijClient({ env, signal, cache: isTrue(args.fresh) ? false : undefined });
337
+ const baseClient = injected ??
338
+ createZellijClient({
339
+ env,
340
+ signal,
341
+ cache: isTrue(args.fresh) ? false : undefined,
342
+ // Rename memory so stale env names keep working across runs.
343
+ aliases: state(),
344
+ });
326
345
  const client = {
327
346
  ...baseClient,
328
347
  get transport() { return baseClient.transport; },
348
+ // Pass the getter through: a spread would freeze the env value and the
349
+ // self-pane guard would compare a stale name.
350
+ get selfSession() { return baseClient.selfSession; },
329
351
  async resolveSession(...input) {
330
352
  const resolved = await baseClient.resolveSession(...input);
331
353
  context.session = resolved.session;
@@ -333,6 +355,15 @@ async function dispatchOperation(args, injected, deps, context, env) {
333
355
  return resolved;
334
356
  },
335
357
  };
358
+ // Only ops that build a sender header or compare against the caller's own
359
+ // pane need the resolved self session; read-only ops must not pay a
360
+ // Zellij round-trip for it.
361
+ if (deps.viaServe !== true && SELF_SESSION_OPS.has(op) && typeof client.resolveSelf === "function") {
362
+ // The pane's ZELLIJ_SESSION_NAME can be stale after a rename; the header
363
+ // must name the live session peers can reply to.
364
+ const self = await client.resolveSelf();
365
+ args = { ...args, origin: resolveSenderOrigin(env, self) };
366
+ }
336
367
  switch (op) {
337
368
  case "sessions": {
338
369
  // Resolve SSH/IPC first so a Windows interactive crew is reachable
@@ -646,7 +677,7 @@ async function dispatchOperation(args, injected, deps, context, env) {
646
677
  case "signal":
647
678
  return postSignal(state(), args, clock);
648
679
  case "signals":
649
- return listSignals(state());
680
+ return listSignals(state(), args);
650
681
  case "await":
651
682
  return await awaitSignal(state(), args, clock);
652
683
  case "log":
@@ -3,7 +3,8 @@ import type { ZellijClient } from "../zellij/client.js";
3
3
  import type { OpsResult } from "./types.js";
4
4
  /**
5
5
  * Give a pane (or its tab) a stable name, so peers can be addressed as
6
- * `reviewer` instead of whatever id Zellij handed out.
6
+ * `reviewer` instead of whatever id Zellij handed out. With `sessionName`
7
+ * (and no `to`/`tab`) it renames the session itself instead.
7
8
  */
8
9
  export declare function renameTarget(client: ZellijClient, args: Record<string, unknown>, policy?: Policy): Promise<OpsResult>;
9
10
  export declare function focusTarget(client: ZellijClient, args: Record<string, unknown>, policy?: Policy): Promise<OpsResult>;
package/dist/ops/panes.js CHANGED
@@ -7,14 +7,27 @@ async function session(client, args) {
7
7
  }
8
8
  /**
9
9
  * Give a pane (or its tab) a stable name, so peers can be addressed as
10
- * `reviewer` instead of whatever id Zellij handed out.
10
+ * `reviewer` instead of whatever id Zellij handed out. With `sessionName`
11
+ * (and no `to`/`tab`) it renames the session itself instead.
11
12
  */
12
13
  export async function renameTarget(client, args, policy) {
14
+ const sessionName = optionalString(args.sessionName);
15
+ const tabKey = optionalString(args.tab);
16
+ const to = optionalString(args.to);
17
+ if (sessionName && !tabKey && !to) {
18
+ // Renaming the session itself: resolve the old name first so a stale
19
+ // ZELLIJ_SESSION_NAME or alias still names the live session.
20
+ const resolved = await client.resolveSession(typeof args.session === "string" ? args.session : undefined);
21
+ const renamed = await client.renameSession({
22
+ session: resolved.session,
23
+ name: sessionName,
24
+ });
25
+ return { ok: true, data: { session: renamed.session, was: renamed.was } };
26
+ }
13
27
  const name = optionalString(args.name);
14
28
  if (!name)
15
29
  throw new ZellijError("missing_name", "name required");
16
30
  const sess = await session(client, args);
17
- const tabKey = optionalString(args.tab);
18
31
  if (tabKey) {
19
32
  const tab = client.resolveTab(await client.listTabs(sess, undefined, { fresh: true }), tabKey);
20
33
  const renamed = await client.renameTab({
@@ -27,7 +40,6 @@ export async function renameTarget(client, args, policy) {
27
40
  data: { session: sess, tab: renamed.tabId, was: tab.name, name },
28
41
  };
29
42
  }
30
- const to = optionalString(args.to);
31
43
  if (!to)
32
44
  throw new ZellijError("missing_peer", "to (or tab) required");
33
45
  const pane = client.resolvePane(await client.listPanes(sess, undefined, { fresh: true }), to);
@@ -5,6 +5,6 @@ import type { Clock, OpsResult } from "./types.js";
5
5
  * crew can rendezvous without any of them staying resident.
6
6
  */
7
7
  export declare function postSignal(state: StateStore, args: Record<string, unknown>, clock: Clock): OpsResult;
8
- export declare function listSignals(state: StateStore): OpsResult;
8
+ export declare function listSignals(state: StateStore, args?: Record<string, unknown>): OpsResult;
9
9
  /** Block until a channel reaches `count` posts, or the deadline passes. */
10
10
  export declare function awaitSignal(state: StateStore, args: Record<string, unknown>, clock: Clock): Promise<OpsResult>;
@@ -28,20 +28,33 @@ export function postSignal(state, args, clock) {
28
28
  data: { channel, count: posted.count, at: posted.at, payload: posted.last },
29
29
  };
30
30
  }
31
- export function listSignals(state) {
31
+ export function listSignals(state, args = {}) {
32
32
  const all = state.readSignals();
33
+ const total = Object.keys(all).length;
34
+ const channel = optionalString(args.channel);
35
+ const since = optionalString(args.since);
36
+ const sinceAt = since ? Number(since) : null;
37
+ const hasLimit = args.limit !== undefined && args.limit !== null && args.limit !== "";
38
+ let matched = Object.entries(all).map(([name, v]) => ({
39
+ channel: name,
40
+ count: v.count,
41
+ at: v.at,
42
+ last: v.last ?? null,
43
+ }));
44
+ if (channel)
45
+ matched = matched.filter((c) => c.channel.startsWith(channel));
46
+ if (sinceAt !== null && Number.isFinite(sinceAt)) {
47
+ matched = matched.filter((c) => c.at >= sinceAt);
48
+ }
49
+ const matchedCount = matched.length;
50
+ const channels = hasLimit
51
+ ? matched
52
+ .sort((a, b) => b.at - a.at)
53
+ .slice(0, numberArg(args, "limit", 1, { min: 1, max: 1_000 }))
54
+ : matched.sort((a, b) => a.channel.localeCompare(b.channel));
33
55
  return {
34
56
  ok: true,
35
- data: {
36
- channels: Object.entries(all)
37
- .map(([channel, v]) => ({
38
- channel,
39
- count: v.count,
40
- at: v.at,
41
- last: v.last ?? null,
42
- }))
43
- .sort((a, b) => a.channel.localeCompare(b.channel)),
44
- },
57
+ data: { total, matched: matchedCount, channels },
45
58
  };
46
59
  }
47
60
  /** Block until a channel reaches `count` posts, or the deadline passes. */
package/dist/schema.js CHANGED
@@ -141,8 +141,8 @@ export const PARAMS = [
141
141
  name: "channel",
142
142
  type: "string",
143
143
  flags: ["--channel"],
144
- ops: ["signal", "await"],
145
- description: "signal/await: channel name",
144
+ ops: ["signal", "await", "signals"],
145
+ description: "signal/await: channel name; signals: only channels whose name starts with this",
146
146
  },
147
147
  {
148
148
  name: "payload",
@@ -216,15 +216,15 @@ export const PARAMS = [
216
216
  name: "limit",
217
217
  type: "number",
218
218
  flags: ["--limit"],
219
- ops: ["log"],
220
- description: "log: how many entries to return (default 20)",
219
+ ops: ["log", "signals"],
220
+ description: "log: how many entries to return (default 20); signals: the N most recently updated channels",
221
221
  },
222
222
  {
223
223
  name: "since",
224
224
  type: "string",
225
225
  flags: ["--since"],
226
- ops: ["log"],
227
- description: "log: only entries at or after this epoch millisecond",
226
+ ops: ["log", "signals"],
227
+ description: "log: only entries at or after this epoch millisecond; signals: only channels updated at or after this epoch millisecond",
228
228
  },
229
229
  {
230
230
  name: "failed",
@@ -446,6 +446,13 @@ export const PARAMS = [
446
446
  ops: ["spawn", "rename"],
447
447
  description: "spawn: pane (or tab) name; rename: the new name",
448
448
  },
449
+ {
450
+ name: "sessionName",
451
+ type: "string",
452
+ flags: ["--session-name"],
453
+ ops: ["rename"],
454
+ description: "rename: rename the session itself to this name; the old name stays an alias so panes that still carry it keep working",
455
+ },
449
456
  {
450
457
  name: "submit",
451
458
  type: "string",
package/dist/state.d.ts CHANGED
@@ -55,6 +55,20 @@ export type LeaseRecord = {
55
55
  /** Relays that forced through while this lease was held. */
56
56
  sharedBy?: string[];
57
57
  };
58
+ /**
59
+ * What an old session name now resolves to. Zellij never updates the
60
+ * ZELLIJ_SESSION_NAME a pane started with, so after a rename every older pane
61
+ * keeps the old name; this is how zswarm maps it to the live session. The
62
+ * server pid pins the entry to the process that owned the old name, so a
63
+ * later session reusing that name does not inherit the alias.
64
+ */
65
+ export type SessionAliasEntry = {
66
+ current: string;
67
+ serverPid: number | null;
68
+ creation: string | null;
69
+ at: number;
70
+ };
71
+ export type SessionAliasMap = Record<string, SessionAliasEntry>;
58
72
  /** How much of the end of the log `readLog` reads; older entries are not shown. */
59
73
  export declare const LOG_TAIL_BYTES: number;
60
74
  /**
@@ -78,6 +92,8 @@ export declare function createStateStore(options?: StateStoreOptions): {
78
92
  readCursor: (key: string) => string | null;
79
93
  writeCursor: (key: string, text: string) => void;
80
94
  clearCursor: (key: string) => void;
95
+ readSessionAliases: () => SessionAliasMap;
96
+ recordSessionAlias: (oldName: string, entry: SessionAliasEntry) => void;
81
97
  readBus: (session: string) => BusMarkerRecord | null;
82
98
  writeBus: (session: string, marker: BusMarkerRecord) => void;
83
99
  clearBus: (session?: string) => void;
package/dist/state.js CHANGED
@@ -9,6 +9,8 @@ const CURSORS_LOCK = "cursors.lock";
9
9
  const BUS_FILE = "bus.json";
10
10
  const LEASES_FILE = "leases.json";
11
11
  const LEASES_LOCK = "leases.lock";
12
+ const SESSION_ALIASES_FILE = "session-aliases.json";
13
+ const SESSION_ALIASES_LOCK = "session-aliases.lock";
12
14
  /** How much of the end of the log `readLog` reads; older entries are not shown. */
13
15
  export const LOG_TAIL_BYTES = 512 * 1024;
14
16
  /**
@@ -397,6 +399,52 @@ export function createStateStore(options = {}) {
397
399
  writeJson(CURSORS_FILE, all);
398
400
  });
399
401
  }
402
+ function asAliasEntry(value) {
403
+ if (!value || typeof value !== "object")
404
+ return null;
405
+ const rec = value;
406
+ if (typeof rec.current !== "string" || !rec.current)
407
+ return null;
408
+ return {
409
+ current: rec.current,
410
+ serverPid: typeof rec.serverPid === "number" &&
411
+ Number.isInteger(rec.serverPid) &&
412
+ rec.serverPid > 0
413
+ ? rec.serverPid
414
+ : null,
415
+ creation: typeof rec.creation === "string" && rec.creation ? rec.creation : null,
416
+ at: typeof rec.at === "number" ? rec.at : 0,
417
+ };
418
+ }
419
+ function readSessionAliases() {
420
+ const raw = readJson(SESSION_ALIASES_FILE, {});
421
+ const out = {};
422
+ for (const [name, entry] of Object.entries(raw)) {
423
+ const parsed = asAliasEntry(entry);
424
+ if (parsed)
425
+ out[name] = parsed;
426
+ }
427
+ return out;
428
+ }
429
+ /**
430
+ * Remember `oldName -> entry.current` and repoint every existing entry whose
431
+ * current name was the old one, so rename chains A -> B -> C leave both A
432
+ * and B resolving to C.
433
+ */
434
+ function recordSessionAlias(oldName, entry) {
435
+ const key = oldName.trim();
436
+ if (!key)
437
+ return;
438
+ withFileLock(SESSION_ALIASES_LOCK, () => {
439
+ const all = readSessionAliases();
440
+ for (const [name, previous] of Object.entries(all)) {
441
+ if (previous.current === key)
442
+ all[name] = { ...previous, current: entry.current };
443
+ }
444
+ all[key] = entry;
445
+ writeJson(SESSION_ALIASES_FILE, all);
446
+ });
447
+ }
400
448
  function asMarker(value) {
401
449
  if (!value || typeof value !== "object")
402
450
  return null;
@@ -495,6 +543,8 @@ export function createStateStore(options = {}) {
495
543
  readCursor,
496
544
  writeCursor,
497
545
  clearCursor,
546
+ readSessionAliases,
547
+ recordSessionAlias,
498
548
  readBus,
499
549
  writeBus,
500
550
  clearBus,
@@ -88,6 +88,8 @@ export declare function buildSendKeysArgs(session: string, paneId: string, keys:
88
88
  export declare function buildWriteCharsArgs(session: string, paneId: string, chars: string): string[];
89
89
  export declare function buildRenamePaneArgs(session: string, paneId: string, name: string): string[];
90
90
  export declare function buildRenameTabArgs(session: string, tabId: number, name: string): string[];
91
+ /** Rename the session itself: `zellij --session <old> action rename-session <new>`. */
92
+ export declare function buildRenameSessionArgs(session: string, name: string): string[];
91
93
  export declare function buildFocusPaneArgs(session: string, paneId: string): string[];
92
94
  export declare function buildListTabsArgs(session: string): string[];
93
95
  export declare function buildDumpLayoutArgs(session: string): string[];
@@ -183,6 +183,10 @@ export function buildRenameTabArgs(session, tabId, name) {
183
183
  name,
184
184
  ];
185
185
  }
186
+ /** Rename the session itself: `zellij --session <old> action rename-session <new>`. */
187
+ export function buildRenameSessionArgs(session, name) {
188
+ return [...sessionPrefix(session), "action", "rename-session", name];
189
+ }
186
190
  export function buildFocusPaneArgs(session, paneId) {
187
191
  return [
188
192
  ...sessionPrefix(session),
@@ -1,11 +1,13 @@
1
1
  import { ListingCache } from "./cache.js";
2
- import { buildClosePaneArgs, buildDumpArgs, buildListPanesArgs, buildNewPaneArgs, buildNewTabArgs, buildPasteArgs, buildSendEnterArgs, buildSendKeysArgs, buildWriteCharsArgs, type WaitRequest, type LaunchPluginInput, type NewPaneInput, type NewTabInput, type PipeInput } from "./args.js";
2
+ import { buildClosePaneArgs, buildDumpArgs, buildListPanesArgs, buildNewPaneArgs, buildNewTabArgs, buildPasteArgs, buildRenameSessionArgs, buildSendEnterArgs, buildSendKeysArgs, buildWriteCharsArgs, type WaitRequest, type LaunchPluginInput, type NewPaneInput, type NewTabInput, type PipeInput } from "./args.js";
3
3
  import { resolveTab, type ZellijTab } from "./tabs.js";
4
4
  import { type IpcDiscoveryState } from "../exec.js";
5
5
  import { type SenderOrigin } from "../ops/delivery.js";
6
6
  import { type ZellijExecFn } from "./binary.js";
7
7
  import { normalizePaneId, resolvePane, type ZellijPane } from "./panes.js";
8
+ import { type ProcInfo } from "./server-identity.js";
8
9
  import { type ZellijSession, type ZellijSessionResolve } from "./session.js";
10
+ import type { SessionAliasEntry, SessionAliasMap } from "../state.js";
9
11
  export type ZellijClientOptions = {
10
12
  exec?: ZellijExecFn;
11
13
  zellijPath?: string;
@@ -18,7 +20,18 @@ export type ZellijClientOptions = {
18
20
  cache?: ListingCache | false;
19
21
  /** Clock for cache TTLs; process deadlines continue using wall time. */
20
22
  now?: () => number;
23
+ /** Rename memory (StateStore); injected by dispatch, or by tests. */
24
+ aliases?: {
25
+ readSessionAliases(): SessionAliasMap;
26
+ recordSessionAlias(oldName: string, entry: SessionAliasEntry): void;
27
+ };
28
+ /** Process-table snapshot override (tests); defaults to a real read. */
29
+ processTable?: () => ProcInfo[] | Promise<ProcInfo[]>;
30
+ /** Platform override (tests); defaults to process.platform. */
31
+ platform?: NodeJS.Platform;
21
32
  };
33
+ /** Test helper: forget every cached self resolution (and its process table). */
34
+ export declare function resetSelfResolutionCache(): void;
22
35
  export type ZellijTransport = {
23
36
  kind: "local" | "ssh";
24
37
  mode: "local" | "ssh" | "interactive";
@@ -33,7 +46,12 @@ export type ZellijTransport = {
33
46
  export declare function createZellijClient(options?: ZellijClientOptions): {
34
47
  zellijPath: string;
35
48
  selfPaneId: string | null;
36
- selfSession: string | null;
49
+ /**
50
+ * The caller's session: the resolved live name once resolveSelf (or a
51
+ * self resolveSession) has run, else the raw ZELLIJ_SESSION_NAME. A getter
52
+ * so a rename resolution is visible to the self-pane guard.
53
+ */
54
+ readonly selfSession: string | null;
37
55
  contextKey: () => string;
38
56
  invalidateListings: (session: string) => void;
39
57
  observeManifest: (session: string, revision: string) => void;
@@ -45,6 +63,7 @@ export declare function createZellijClient(options?: ZellijClientOptions): {
45
63
  }) => Promise<ZellijSession[]>;
46
64
  deleteSession: (name: string, callTimeoutMs?: number) => Promise<void>;
47
65
  resolveSession: (explicit?: string | null, callTimeoutMs?: number) => Promise<ZellijSessionResolve>;
66
+ resolveSelf: () => Promise<string | null>;
48
67
  listPanes: (session: string, callTimeoutMs?: number, opts?: {
49
68
  fresh?: boolean;
50
69
  }) => Promise<ZellijPane[]>;
@@ -121,6 +140,14 @@ export declare function createZellijClient(options?: ZellijClientOptions): {
121
140
  session: string;
122
141
  name: string;
123
142
  }>;
143
+ renameSession: (input: {
144
+ session: string;
145
+ name: string;
146
+ callTimeoutMs?: number;
147
+ }) => Promise<{
148
+ session: string;
149
+ was: string;
150
+ }>;
124
151
  focusPane: (input: {
125
152
  session: string;
126
153
  paneId: string;
@@ -194,5 +221,6 @@ export declare function createZellijClient(options?: ZellijClientOptions): {
194
221
  buildClosePaneArgs: typeof buildClosePaneArgs;
195
222
  buildNewPaneArgs: typeof buildNewPaneArgs;
196
223
  buildNewTabArgs: typeof buildNewTabArgs;
224
+ buildRenameSessionArgs: typeof buildRenameSessionArgs;
197
225
  };
198
226
  export type ZellijClient = ReturnType<typeof createZellijClient>;