@particle-academy/fancy-term-host 0.1.1 → 0.1.2

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.cts CHANGED
@@ -366,6 +366,23 @@ declare class HostClient extends EventEmitter implements PtyBackend {
366
366
  * the reattach (renderer remounts these specs, replaying host scrollback). */
367
367
  liveIds(): string[];
368
368
  isConnected(): boolean;
369
+ /**
370
+ * Gracefully shut the host DOWN — the deliberate counterpart to
371
+ * `disconnect()` (which leaves the host running). Asks the host to kill its
372
+ * ptys, remove its pidfile/socket, and exit cleanly, then drops the local
373
+ * socket. Use this when a consumer needs the host genuinely gone — e.g.
374
+ * before an Electron auto-update whose installer must overwrite the binary
375
+ * the host runs on — INSTEAD of SIGKILLing by pidfile pid, which skips the
376
+ * host's own cleanup.
377
+ *
378
+ * The client mirror already holds the live scrollback, so snapshot via the
379
+ * SnapshotStore BEFORE calling this if you want T1 history to survive.
380
+ *
381
+ * Resolves once the host acknowledges (`shutdown-ok`) or the connection
382
+ * closes (the host exited), whichever comes first; never rejects — a host
383
+ * that's already gone is a successful shutdown.
384
+ */
385
+ shutdownHost(timeoutMs?: number): Promise<void>;
369
386
  /** Disconnect WITHOUT killing host ptys (before-quit leave-running). */
370
387
  disconnect(): void;
371
388
  create(opts: CreateTerminalOpts): AttachResult;
@@ -450,6 +467,19 @@ declare function initTerminalBackend(): Promise<{
450
467
  * the host running so the next launch reattaches.
451
468
  */
452
469
  declare function disconnectHostLeaveRunning(): void;
470
+ /**
471
+ * Gracefully STOP the detached host (the opposite of leave-running): ask it to
472
+ * kill its ptys, clean up its pidfile/socket, and exit, then drop our client and
473
+ * revert to the in-process backend so any later create() still works.
474
+ *
475
+ * Intended for the case where a consumer needs the host genuinely gone — most
476
+ * notably before an Electron auto-update whose installer must overwrite the
477
+ * binary the detached host is running on. Snapshot first (the normal before-quit
478
+ * T1 path) if you want history to survive; this is a clean shutdown, NOT a
479
+ * SIGKILL-by-pidfile, so the host runs its own cleanup. No-op (resolves) when no
480
+ * host is active. NEVER throws.
481
+ */
482
+ declare function shutdownHost(timeoutMs?: number): Promise<void>;
453
483
 
454
484
  /**
455
485
  * Absolute path to the bundled detached pty-host script (Tier 3), so a
@@ -544,7 +574,7 @@ declare function resolveHostScript(dirname: string): string | null;
544
574
  * refuses to attach to a host whose pidfile reports a different version and
545
575
  * spawns a fresh host instead — see host-client.ts connect-or-spawn.
546
576
  */
547
- declare const PROTOCOL_VERSION = 1;
577
+ declare const PROTOCOL_VERSION = 2;
548
578
  /** Requests the client sends to the host. `seq` correlates a reply. */
549
579
  type ClientMessage = {
550
580
  kind: 'hello';
@@ -588,6 +618,9 @@ type ClientMessage = {
588
618
  } | {
589
619
  kind: 'ping';
590
620
  seq: number;
621
+ } | {
622
+ kind: 'shutdown';
623
+ seq: number;
591
624
  };
592
625
  /** Pushes + replies the host sends to the client. */
593
626
  type HostMessage = {
@@ -620,6 +653,9 @@ type HostMessage = {
620
653
  } | {
621
654
  kind: 'pong';
622
655
  seq: number;
656
+ } | {
657
+ kind: 'shutdown-ok';
658
+ seq: number;
623
659
  } | {
624
660
  kind: 'data';
625
661
  id: string;
@@ -808,4 +844,4 @@ declare function toNativeCwd(p: string): string;
808
844
  */
809
845
  declare function resolveSpawnCwd(requested: string | undefined | null): string;
810
846
 
811
- export { type AttachResult, type BackendDeps, type ClientMessage, type CreateTerminalOpts, type CwdHook, type Encryptor, type Frame, FrameDecoder, HostClient, type HostMessage, type HostSpawner, type HostStatus, PROTOCOL_VERSION, type Pidfile, type PtyBackend, type SettingsProvider, type ShellInfo, type ShellKind, type SnapshotRead, type SnapshotStore, type SnapshotStoreConfig, type TerminalInfo, type TerminalManager, configureHostLifecycle, configureInProcessBackend, createSnapshotStore, cwdHookEnv, cwdHookSpawn, defaultShell, defaultShellId, deletePidfile, detectShells, disconnectHostLeaveRunning, encodeFrame, getHostClient, inProcessBackend, initTerminalBackend, isHostBacked, isPidAlive, parseCommandLine, parseFileUrl, pidfilePath, pidfileUsable, ptyHostScriptPath, readPidfile, resolveDefaultShell, resolveHostScript, resolveSpawnCwd, scanOsc7Cwd, setActiveBackend, shellKind, socketPathFor, subscribeBackendEvents, terminalManager, toNativeCwd, userHash, writePidfile };
847
+ export { type AttachResult, type BackendDeps, type ClientMessage, type CreateTerminalOpts, type CwdHook, type Encryptor, type Frame, FrameDecoder, HostClient, type HostMessage, type HostSpawner, type HostStatus, PROTOCOL_VERSION, type Pidfile, type PtyBackend, type SettingsProvider, type ShellInfo, type ShellKind, type SnapshotRead, type SnapshotStore, type SnapshotStoreConfig, type TerminalInfo, type TerminalManager, configureHostLifecycle, configureInProcessBackend, createSnapshotStore, cwdHookEnv, cwdHookSpawn, defaultShell, defaultShellId, deletePidfile, detectShells, disconnectHostLeaveRunning, encodeFrame, getHostClient, inProcessBackend, initTerminalBackend, isHostBacked, isPidAlive, parseCommandLine, parseFileUrl, pidfilePath, pidfileUsable, ptyHostScriptPath, readPidfile, resolveDefaultShell, resolveHostScript, resolveSpawnCwd, scanOsc7Cwd, setActiveBackend, shellKind, shutdownHost, socketPathFor, subscribeBackendEvents, terminalManager, toNativeCwd, userHash, writePidfile };
package/dist/index.d.ts CHANGED
@@ -366,6 +366,23 @@ declare class HostClient extends EventEmitter implements PtyBackend {
366
366
  * the reattach (renderer remounts these specs, replaying host scrollback). */
367
367
  liveIds(): string[];
368
368
  isConnected(): boolean;
369
+ /**
370
+ * Gracefully shut the host DOWN — the deliberate counterpart to
371
+ * `disconnect()` (which leaves the host running). Asks the host to kill its
372
+ * ptys, remove its pidfile/socket, and exit cleanly, then drops the local
373
+ * socket. Use this when a consumer needs the host genuinely gone — e.g.
374
+ * before an Electron auto-update whose installer must overwrite the binary
375
+ * the host runs on — INSTEAD of SIGKILLing by pidfile pid, which skips the
376
+ * host's own cleanup.
377
+ *
378
+ * The client mirror already holds the live scrollback, so snapshot via the
379
+ * SnapshotStore BEFORE calling this if you want T1 history to survive.
380
+ *
381
+ * Resolves once the host acknowledges (`shutdown-ok`) or the connection
382
+ * closes (the host exited), whichever comes first; never rejects — a host
383
+ * that's already gone is a successful shutdown.
384
+ */
385
+ shutdownHost(timeoutMs?: number): Promise<void>;
369
386
  /** Disconnect WITHOUT killing host ptys (before-quit leave-running). */
370
387
  disconnect(): void;
371
388
  create(opts: CreateTerminalOpts): AttachResult;
@@ -450,6 +467,19 @@ declare function initTerminalBackend(): Promise<{
450
467
  * the host running so the next launch reattaches.
451
468
  */
452
469
  declare function disconnectHostLeaveRunning(): void;
470
+ /**
471
+ * Gracefully STOP the detached host (the opposite of leave-running): ask it to
472
+ * kill its ptys, clean up its pidfile/socket, and exit, then drop our client and
473
+ * revert to the in-process backend so any later create() still works.
474
+ *
475
+ * Intended for the case where a consumer needs the host genuinely gone — most
476
+ * notably before an Electron auto-update whose installer must overwrite the
477
+ * binary the detached host is running on. Snapshot first (the normal before-quit
478
+ * T1 path) if you want history to survive; this is a clean shutdown, NOT a
479
+ * SIGKILL-by-pidfile, so the host runs its own cleanup. No-op (resolves) when no
480
+ * host is active. NEVER throws.
481
+ */
482
+ declare function shutdownHost(timeoutMs?: number): Promise<void>;
453
483
 
454
484
  /**
455
485
  * Absolute path to the bundled detached pty-host script (Tier 3), so a
@@ -544,7 +574,7 @@ declare function resolveHostScript(dirname: string): string | null;
544
574
  * refuses to attach to a host whose pidfile reports a different version and
545
575
  * spawns a fresh host instead — see host-client.ts connect-or-spawn.
546
576
  */
547
- declare const PROTOCOL_VERSION = 1;
577
+ declare const PROTOCOL_VERSION = 2;
548
578
  /** Requests the client sends to the host. `seq` correlates a reply. */
549
579
  type ClientMessage = {
550
580
  kind: 'hello';
@@ -588,6 +618,9 @@ type ClientMessage = {
588
618
  } | {
589
619
  kind: 'ping';
590
620
  seq: number;
621
+ } | {
622
+ kind: 'shutdown';
623
+ seq: number;
591
624
  };
592
625
  /** Pushes + replies the host sends to the client. */
593
626
  type HostMessage = {
@@ -620,6 +653,9 @@ type HostMessage = {
620
653
  } | {
621
654
  kind: 'pong';
622
655
  seq: number;
656
+ } | {
657
+ kind: 'shutdown-ok';
658
+ seq: number;
623
659
  } | {
624
660
  kind: 'data';
625
661
  id: string;
@@ -808,4 +844,4 @@ declare function toNativeCwd(p: string): string;
808
844
  */
809
845
  declare function resolveSpawnCwd(requested: string | undefined | null): string;
810
846
 
811
- export { type AttachResult, type BackendDeps, type ClientMessage, type CreateTerminalOpts, type CwdHook, type Encryptor, type Frame, FrameDecoder, HostClient, type HostMessage, type HostSpawner, type HostStatus, PROTOCOL_VERSION, type Pidfile, type PtyBackend, type SettingsProvider, type ShellInfo, type ShellKind, type SnapshotRead, type SnapshotStore, type SnapshotStoreConfig, type TerminalInfo, type TerminalManager, configureHostLifecycle, configureInProcessBackend, createSnapshotStore, cwdHookEnv, cwdHookSpawn, defaultShell, defaultShellId, deletePidfile, detectShells, disconnectHostLeaveRunning, encodeFrame, getHostClient, inProcessBackend, initTerminalBackend, isHostBacked, isPidAlive, parseCommandLine, parseFileUrl, pidfilePath, pidfileUsable, ptyHostScriptPath, readPidfile, resolveDefaultShell, resolveHostScript, resolveSpawnCwd, scanOsc7Cwd, setActiveBackend, shellKind, socketPathFor, subscribeBackendEvents, terminalManager, toNativeCwd, userHash, writePidfile };
847
+ export { type AttachResult, type BackendDeps, type ClientMessage, type CreateTerminalOpts, type CwdHook, type Encryptor, type Frame, FrameDecoder, HostClient, type HostMessage, type HostSpawner, type HostStatus, PROTOCOL_VERSION, type Pidfile, type PtyBackend, type SettingsProvider, type ShellInfo, type ShellKind, type SnapshotRead, type SnapshotStore, type SnapshotStoreConfig, type TerminalInfo, type TerminalManager, configureHostLifecycle, configureInProcessBackend, createSnapshotStore, cwdHookEnv, cwdHookSpawn, defaultShell, defaultShellId, deletePidfile, detectShells, disconnectHostLeaveRunning, encodeFrame, getHostClient, inProcessBackend, initTerminalBackend, isHostBacked, isPidAlive, parseCommandLine, parseFileUrl, pidfilePath, pidfileUsable, ptyHostScriptPath, readPidfile, resolveDefaultShell, resolveHostScript, resolveSpawnCwd, scanOsc7Cwd, setActiveBackend, shellKind, shutdownHost, socketPathFor, subscribeBackendEvents, terminalManager, toNativeCwd, userHash, writePidfile };
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
- import { FrameDecoder, PROTOCOL_VERSION, encodeFrame, readPidfile, pidfileUsable, deletePidfile, resolveHostScript, resolveSpawnCwd, toNativeCwd } from './chunk-WMP4YLM5.js';
2
- export { FrameDecoder, PROTOCOL_VERSION, deletePidfile, encodeFrame, isPidAlive, pidfilePath, pidfileUsable, readPidfile, resolveHostScript, resolveSpawnCwd, socketPathFor, toNativeCwd, userHash, writePidfile } from './chunk-WMP4YLM5.js';
1
+ import { FrameDecoder, PROTOCOL_VERSION, encodeFrame, readPidfile, pidfileUsable, deletePidfile, resolveHostScript, resolveSpawnCwd, toNativeCwd } from './chunk-M5TFZDJA.js';
2
+ export { FrameDecoder, PROTOCOL_VERSION, deletePidfile, encodeFrame, isPidAlive, pidfilePath, pidfileUsable, readPidfile, resolveHostScript, resolveSpawnCwd, socketPathFor, toNativeCwd, userHash, writePidfile } from './chunk-M5TFZDJA.js';
3
3
  import { spawn } from 'node-pty';
4
4
  import { EventEmitter } from 'events';
5
5
  import fs2 from 'fs';
@@ -805,6 +805,42 @@ var HostClient = class _HostClient extends EventEmitter {
805
805
  isConnected() {
806
806
  return this.connected;
807
807
  }
808
+ /**
809
+ * Gracefully shut the host DOWN — the deliberate counterpart to
810
+ * `disconnect()` (which leaves the host running). Asks the host to kill its
811
+ * ptys, remove its pidfile/socket, and exit cleanly, then drops the local
812
+ * socket. Use this when a consumer needs the host genuinely gone — e.g.
813
+ * before an Electron auto-update whose installer must overwrite the binary
814
+ * the host runs on — INSTEAD of SIGKILLing by pidfile pid, which skips the
815
+ * host's own cleanup.
816
+ *
817
+ * The client mirror already holds the live scrollback, so snapshot via the
818
+ * SnapshotStore BEFORE calling this if you want T1 history to survive.
819
+ *
820
+ * Resolves once the host acknowledges (`shutdown-ok`) or the connection
821
+ * closes (the host exited), whichever comes first; never rejects — a host
822
+ * that's already gone is a successful shutdown.
823
+ */
824
+ shutdownHost(timeoutMs = 2e3) {
825
+ if (!this.socket || !this.connected) {
826
+ this.disconnect();
827
+ return Promise.resolve();
828
+ }
829
+ this.connected = false;
830
+ return new Promise((resolve) => {
831
+ let done = false;
832
+ const finish = () => {
833
+ if (done) return;
834
+ done = true;
835
+ clearTimeout(timer);
836
+ this.disconnect();
837
+ resolve();
838
+ };
839
+ const timer = setTimeout(finish, timeoutMs);
840
+ this.socket?.once("close", finish);
841
+ this.request({ kind: "shutdown", seq: this.nextSeq() }).then(finish).catch(finish);
842
+ });
843
+ }
808
844
  /** Disconnect WITHOUT killing host ptys (before-quit leave-running). */
809
845
  disconnect() {
810
846
  this.connected = false;
@@ -1009,11 +1045,22 @@ function disconnectHostLeaveRunning() {
1009
1045
  }
1010
1046
  }
1011
1047
  }
1048
+ async function shutdownHost(timeoutMs = 2e3) {
1049
+ const c = client;
1050
+ usingHost = false;
1051
+ client = null;
1052
+ setActiveBackend(inProcessBackend());
1053
+ if (!c) return;
1054
+ try {
1055
+ await c.shutdownHost(timeoutMs);
1056
+ } catch {
1057
+ }
1058
+ }
1012
1059
  function ptyHostScriptPath() {
1013
1060
  const here = typeof __dirname !== "undefined" ? __dirname : path.dirname(fileURLToPath(import.meta.url));
1014
1061
  return resolveHostScript(here) ?? path.join(here, "pty-host.js");
1015
1062
  }
1016
1063
 
1017
- export { HostClient, configureHostLifecycle, configureInProcessBackend, createSnapshotStore, cwdHookEnv, cwdHookSpawn, defaultShell, defaultShellId, detectShells, disconnectHostLeaveRunning, getHostClient, inProcessBackend, initTerminalBackend, isHostBacked, parseCommandLine, parseFileUrl, ptyHostScriptPath, resolveDefaultShell, scanOsc7Cwd, setActiveBackend, shellKind, subscribeBackendEvents, terminalManager };
1064
+ export { HostClient, configureHostLifecycle, configureInProcessBackend, createSnapshotStore, cwdHookEnv, cwdHookSpawn, defaultShell, defaultShellId, detectShells, disconnectHostLeaveRunning, getHostClient, inProcessBackend, initTerminalBackend, isHostBacked, parseCommandLine, parseFileUrl, ptyHostScriptPath, resolveDefaultShell, scanOsc7Cwd, setActiveBackend, shellKind, shutdownHost, subscribeBackendEvents, terminalManager };
1018
1065
  //# sourceMappingURL=index.js.map
1019
1066
  //# sourceMappingURL=index.js.map