@termlink/cli 0.1.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.
Files changed (147) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +84 -0
  3. package/dist/auth/login.d.ts +55 -0
  4. package/dist/auth/login.d.ts.map +1 -0
  5. package/dist/auth/login.js +238 -0
  6. package/dist/auth/login.js.map +1 -0
  7. package/dist/auth/oauth-defaults.d.ts +9 -0
  8. package/dist/auth/oauth-defaults.d.ts.map +1 -0
  9. package/dist/auth/oauth-defaults.js +9 -0
  10. package/dist/auth/oauth-defaults.js.map +1 -0
  11. package/dist/cli.d.ts +3 -0
  12. package/dist/cli.d.ts.map +1 -0
  13. package/dist/cli.js +319 -0
  14. package/dist/cli.js.map +1 -0
  15. package/dist/errors.d.ts +8 -0
  16. package/dist/errors.d.ts.map +1 -0
  17. package/dist/errors.js +13 -0
  18. package/dist/errors.js.map +1 -0
  19. package/dist/index.d.ts +20 -0
  20. package/dist/index.d.ts.map +1 -0
  21. package/dist/index.js +19 -0
  22. package/dist/index.js.map +1 -0
  23. package/dist/providers/claude/history.d.ts +15 -0
  24. package/dist/providers/claude/history.d.ts.map +1 -0
  25. package/dist/providers/claude/history.js +71 -0
  26. package/dist/providers/claude/history.js.map +1 -0
  27. package/dist/providers/claude/input-queue.d.ts +8 -0
  28. package/dist/providers/claude/input-queue.d.ts.map +1 -0
  29. package/dist/providers/claude/input-queue.js +34 -0
  30. package/dist/providers/claude/input-queue.js.map +1 -0
  31. package/dist/providers/claude/mapper.d.ts +21 -0
  32. package/dist/providers/claude/mapper.d.ts.map +1 -0
  33. package/dist/providers/claude/mapper.js +136 -0
  34. package/dist/providers/claude/mapper.js.map +1 -0
  35. package/dist/providers/claude/provider.d.ts +46 -0
  36. package/dist/providers/claude/provider.d.ts.map +1 -0
  37. package/dist/providers/claude/provider.js +148 -0
  38. package/dist/providers/claude/provider.js.map +1 -0
  39. package/dist/providers/claude/session.d.ts +27 -0
  40. package/dist/providers/claude/session.d.ts.map +1 -0
  41. package/dist/providers/claude/session.js +353 -0
  42. package/dist/providers/claude/session.js.map +1 -0
  43. package/dist/providers/codex/app-server.d.ts +24 -0
  44. package/dist/providers/codex/app-server.d.ts.map +1 -0
  45. package/dist/providers/codex/app-server.js +79 -0
  46. package/dist/providers/codex/app-server.js.map +1 -0
  47. package/dist/providers/codex/command.d.ts +12 -0
  48. package/dist/providers/codex/command.d.ts.map +1 -0
  49. package/dist/providers/codex/command.js +60 -0
  50. package/dist/providers/codex/command.js.map +1 -0
  51. package/dist/providers/codex/history.d.ts +5 -0
  52. package/dist/providers/codex/history.d.ts.map +1 -0
  53. package/dist/providers/codex/history.js +33 -0
  54. package/dist/providers/codex/history.js.map +1 -0
  55. package/dist/providers/codex/mapper.d.ts +13 -0
  56. package/dist/providers/codex/mapper.d.ts.map +1 -0
  57. package/dist/providers/codex/mapper.js +83 -0
  58. package/dist/providers/codex/mapper.js.map +1 -0
  59. package/dist/providers/codex/protocol.d.ts +223 -0
  60. package/dist/providers/codex/protocol.d.ts.map +1 -0
  61. package/dist/providers/codex/protocol.js +11 -0
  62. package/dist/providers/codex/protocol.js.map +1 -0
  63. package/dist/providers/codex/provider.d.ts +28 -0
  64. package/dist/providers/codex/provider.d.ts.map +1 -0
  65. package/dist/providers/codex/provider.js +116 -0
  66. package/dist/providers/codex/provider.js.map +1 -0
  67. package/dist/providers/codex/rpc.d.ts +23 -0
  68. package/dist/providers/codex/rpc.d.ts.map +1 -0
  69. package/dist/providers/codex/rpc.js +104 -0
  70. package/dist/providers/codex/rpc.js.map +1 -0
  71. package/dist/providers/codex/session.d.ts +16 -0
  72. package/dist/providers/codex/session.d.ts.map +1 -0
  73. package/dist/providers/codex/session.js +262 -0
  74. package/dist/providers/codex/session.js.map +1 -0
  75. package/dist/providers/display.d.ts +9 -0
  76. package/dist/providers/display.d.ts.map +1 -0
  77. package/dist/providers/display.js +21 -0
  78. package/dist/providers/display.js.map +1 -0
  79. package/dist/providers/terminal.d.ts +24 -0
  80. package/dist/providers/terminal.d.ts.map +1 -0
  81. package/dist/providers/terminal.js +33 -0
  82. package/dist/providers/terminal.js.map +1 -0
  83. package/dist/providers/types.d.ts +72 -0
  84. package/dist/providers/types.d.ts.map +1 -0
  85. package/dist/providers/types.js +2 -0
  86. package/dist/providers/types.js.map +1 -0
  87. package/dist/relay/api.d.ts +13 -0
  88. package/dist/relay/api.d.ts.map +1 -0
  89. package/dist/relay/api.js +75 -0
  90. package/dist/relay/api.js.map +1 -0
  91. package/dist/relay/device.d.ts +26 -0
  92. package/dist/relay/device.d.ts.map +1 -0
  93. package/dist/relay/device.js +83 -0
  94. package/dist/relay/device.js.map +1 -0
  95. package/dist/relay/relay-host.d.ts +41 -0
  96. package/dist/relay/relay-host.d.ts.map +1 -0
  97. package/dist/relay/relay-host.js +238 -0
  98. package/dist/relay/relay-host.js.map +1 -0
  99. package/dist/server/coalesce.d.ts +15 -0
  100. package/dist/server/coalesce.d.ts.map +1 -0
  101. package/dist/server/coalesce.js +50 -0
  102. package/dist/server/coalesce.js.map +1 -0
  103. package/dist/server/connection.d.ts +30 -0
  104. package/dist/server/connection.d.ts.map +1 -0
  105. package/dist/server/connection.js +182 -0
  106. package/dist/server/connection.js.map +1 -0
  107. package/dist/server/local-server.d.ts +27 -0
  108. package/dist/server/local-server.d.ts.map +1 -0
  109. package/dist/server/local-server.js +108 -0
  110. package/dist/server/local-server.js.map +1 -0
  111. package/dist/session/event-log.d.ts +17 -0
  112. package/dist/session/event-log.d.ts.map +1 -0
  113. package/dist/session/event-log.js +21 -0
  114. package/dist/session/event-log.js.map +1 -0
  115. package/dist/session/manager.d.ts +62 -0
  116. package/dist/session/manager.d.ts.map +1 -0
  117. package/dist/session/manager.js +282 -0
  118. package/dist/session/manager.js.map +1 -0
  119. package/dist/session/session.d.ts +43 -0
  120. package/dist/session/session.d.ts.map +1 -0
  121. package/dist/session/session.js +310 -0
  122. package/dist/session/session.js.map +1 -0
  123. package/dist/session/store.d.ts +22 -0
  124. package/dist/session/store.d.ts.map +1 -0
  125. package/dist/session/store.js +44 -0
  126. package/dist/session/store.js.map +1 -0
  127. package/dist/session/terminal-session.d.ts +52 -0
  128. package/dist/session/terminal-session.d.ts.map +1 -0
  129. package/dist/session/terminal-session.js +210 -0
  130. package/dist/session/terminal-session.js.map +1 -0
  131. package/dist/util/id.d.ts +2 -0
  132. package/dist/util/id.d.ts.map +1 -0
  133. package/dist/util/id.js +5 -0
  134. package/dist/util/id.js.map +1 -0
  135. package/dist/util/lock.d.ts +12 -0
  136. package/dist/util/lock.d.ts.map +1 -0
  137. package/dist/util/lock.js +52 -0
  138. package/dist/util/lock.js.map +1 -0
  139. package/dist/util/which.d.ts +3 -0
  140. package/dist/util/which.d.ts.map +1 -0
  141. package/dist/util/which.js +12 -0
  142. package/dist/util/which.js.map +1 -0
  143. package/dist/version.d.ts +2 -0
  144. package/dist/version.d.ts.map +1 -0
  145. package/dist/version.js +5 -0
  146. package/dist/version.js.map +1 -0
  147. package/package.json +56 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/session/session.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ import type { AutoApprove, ProviderId } from "@termlink/protocol";
2
+ /** What the host remembers about a session so it can resume it after a restart. */
3
+ export interface SessionRecord {
4
+ id: string;
5
+ provider: ProviderId;
6
+ providerSessionId: string;
7
+ cwd: string;
8
+ title: string | null;
9
+ createdAt: number;
10
+ updatedAt: number;
11
+ autoApprove?: AutoApprove;
12
+ }
13
+ export declare function defaultStatePath(): string;
14
+ /** A small JSON file of session records, rewritten atomically. Writes are serialized. */
15
+ export declare class SessionStore {
16
+ #private;
17
+ readonly file: string;
18
+ constructor(file?: string);
19
+ load(): Promise<SessionRecord[]>;
20
+ save(records: SessionRecord[]): Promise<void>;
21
+ }
22
+ //# sourceMappingURL=store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/session/store.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAElE,mFAAmF;AACnF,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,UAAU,CAAC;IACrB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,WAAW,CAAC;CAC3B;AAED,wBAAgB,gBAAgB,IAAI,MAAM,CAEzC;AAcD,yFAAyF;AACzF,qBAAa,YAAY;;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAGtB,YAAY,IAAI,GAAE,MAA2B,EAE5C;IAEK,IAAI,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC,CAOrC;IAED,IAAI,CAAC,OAAO,EAAE,aAAa,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAG5C;CAQF"}
@@ -0,0 +1,44 @@
1
+ import { mkdir, readFile, rename, writeFile } from "node:fs/promises";
2
+ import os from "node:os";
3
+ import path from "node:path";
4
+ export function defaultStatePath() {
5
+ return path.join(os.homedir(), ".termlink", "agent-sessions.json");
6
+ }
7
+ function isRecord(value) {
8
+ if (typeof value !== "object" || value === null)
9
+ return false;
10
+ const r = value;
11
+ return (typeof r.id === "string" &&
12
+ typeof r.provider === "string" &&
13
+ typeof r.providerSessionId === "string" &&
14
+ typeof r.cwd === "string" &&
15
+ typeof r.createdAt === "number");
16
+ }
17
+ /** A small JSON file of session records, rewritten atomically. Writes are serialized. */
18
+ export class SessionStore {
19
+ file;
20
+ #queue = Promise.resolve();
21
+ constructor(file = defaultStatePath()) {
22
+ this.file = file;
23
+ }
24
+ async load() {
25
+ try {
26
+ const data = JSON.parse(await readFile(this.file, "utf8"));
27
+ return Array.isArray(data.sessions) ? data.sessions.filter(isRecord) : [];
28
+ }
29
+ catch {
30
+ return [];
31
+ }
32
+ }
33
+ save(records) {
34
+ this.#queue = this.#queue.then(() => this.#write(records)).catch(() => { });
35
+ return this.#queue;
36
+ }
37
+ async #write(records) {
38
+ await mkdir(path.dirname(this.file), { recursive: true });
39
+ const temp = `${this.file}.${process.pid}.tmp`;
40
+ await writeFile(temp, `${JSON.stringify({ version: 1, sessions: records }, null, 2)}\n`, { mode: 0o600 });
41
+ await rename(temp, this.file);
42
+ }
43
+ }
44
+ //# sourceMappingURL=store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/session/store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACtE,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAe7B,MAAM,UAAU,gBAAgB;IAC9B,OAAO,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,WAAW,EAAE,qBAAqB,CAAC,CAAC;AACrE,CAAC;AAED,SAAS,QAAQ,CAAC,KAAc;IAC9B,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IAC9D,MAAM,CAAC,GAAG,KAAgC,CAAC;IAC3C,OAAO,CACL,OAAO,CAAC,CAAC,EAAE,KAAK,QAAQ;QACxB,OAAO,CAAC,CAAC,QAAQ,KAAK,QAAQ;QAC9B,OAAO,CAAC,CAAC,iBAAiB,KAAK,QAAQ;QACvC,OAAO,CAAC,CAAC,GAAG,KAAK,QAAQ;QACzB,OAAO,CAAC,CAAC,SAAS,KAAK,QAAQ,CAChC,CAAC;AACJ,CAAC;AAED,yFAAyF;AACzF,MAAM,OAAO,YAAY;IACd,IAAI,CAAS;IACtB,MAAM,GAAkB,OAAO,CAAC,OAAO,EAAE,CAAC;IAE1C,YAAY,IAAI,GAAW,gBAAgB,EAAE;QAC3C,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;IAED,KAAK,CAAC,IAAI;QACR,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAA2B,CAAC;YACrF,OAAO,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAC5E,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC;IAED,IAAI,CAAC,OAAwB;QAC3B,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QAC3E,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,OAAwB;QACnC,MAAM,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC1D,MAAM,IAAI,GAAG,GAAG,IAAI,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,MAAM,CAAC;QAC/C,MAAM,SAAS,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QAC1G,MAAM,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;IAChC,CAAC;CACF"}
@@ -0,0 +1,52 @@
1
+ import { type SessionInfo } from "@termlink/protocol";
2
+ import type { Terminal } from "@termlink/terminal";
3
+ import type { Listener } from "./session.js";
4
+ export interface TerminalListener {
5
+ /** JSON events for this session: terminal.size, terminal.reset. */
6
+ event: Listener;
7
+ /** Output bytes, already framed. */
8
+ bytes: (frame: Uint8Array) => void;
9
+ }
10
+ export interface TerminalAttachment {
11
+ detach: () => void;
12
+ /** Sends terminal.reset and the current screen to everyone attached. Call after the attach reply. */
13
+ catchUp: () => Promise<void>;
14
+ }
15
+ export interface FlowControlOptions {
16
+ /** Unacknowledged output that pauses the shell. */
17
+ highWaterBytes?: number | undefined;
18
+ /** Unacknowledged output below which a paused shell resumes. */
19
+ lowWaterBytes?: number | undefined;
20
+ /** A client that owes an ack for this long is treated as gone. */
21
+ ackTimeoutMs?: number | undefined;
22
+ }
23
+ /**
24
+ * One terminal session: a shell in a PTY and the connections watching it. Output is
25
+ * broadcast as binary frames; there is no replay log, a late client gets the screen.
26
+ *
27
+ * Flow control: clients say how much output they have drawn (terminal.ack). When the
28
+ * slowest one falls too far behind, the shell is paused, so a slow link is not dropped
29
+ * by the relay for failing to keep up. A client that stops acking is dropped from the
30
+ * calculation after a timeout, so one dead browser tab cannot freeze the shell.
31
+ */
32
+ export declare class TerminalSession {
33
+ #private;
34
+ readonly id: string;
35
+ constructor(info: SessionInfo, onLifecycle: Listener, flow?: FlowControlOptions);
36
+ get info(): SessionInfo;
37
+ get closed(): boolean;
38
+ /** Bytes of output sent so far. For tests. */
39
+ get sentBytes(): number;
40
+ get paused(): boolean;
41
+ announce(): void;
42
+ bind(terminal: Terminal): void;
43
+ attach(listener: TerminalListener, clientId?: string): TerminalAttachment;
44
+ /** A client left without detaching its attachment (session.detach with a clientId). */
45
+ forgetClient(clientId: string): void;
46
+ write(data: Uint8Array): void;
47
+ resize(cols: number, rows: number): void;
48
+ ack(clientId: string, bytes: number): void;
49
+ kill(): void;
50
+ close(reason: string | null, exitCode?: number | null): Promise<void>;
51
+ }
52
+ //# sourceMappingURL=terminal-session.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"terminal-session.d.ts","sourceRoot":"","sources":["../../src/session/terminal-session.ts"],"names":[],"mappings":"AAAA,OAAO,EAOL,KAAK,WAAW,EACjB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAEnD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAE7C,MAAM,WAAW,gBAAgB;IAC/B,mEAAmE;IACnE,KAAK,EAAE,QAAQ,CAAC;IAChB,oCAAoC;IACpC,KAAK,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;CACpC;AAED,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,qGAAqG;IACrG,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9B;AAED,MAAM,WAAW,kBAAkB;IACjC,mDAAmD;IACnD,cAAc,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,gEAAgE;IAChE,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,kEAAkE;IAClE,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACnC;AAWD;;;;;;;;GAQG;AACH,qBAAa,eAAe;;IAC1B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IAYpB,YAAY,IAAI,EAAE,WAAW,EAAE,WAAW,EAAE,QAAQ,EAAE,IAAI,GAAE,kBAAuB,EASlF;IAED,IAAI,IAAI,IAAI,WAAW,CAEtB;IAED,IAAI,MAAM,IAAI,OAAO,CAEpB;IAED,8CAA8C;IAC9C,IAAI,SAAS,IAAI,MAAM,CAEtB;IAED,IAAI,MAAM,IAAI,OAAO,CAEpB;IAED,QAAQ,IAAI,IAAI,CAEf;IAED,IAAI,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAQ7B;IAED,MAAM,CAAC,QAAQ,EAAE,gBAAgB,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,kBAAkB,CAWxE;IAED,uFAAuF;IACvF,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAEnC;IAED,KAAK,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,CAG5B;IAED,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAQvC;IAED,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAMzC;IAED,IAAI,IAAI,IAAI,CAGX;IAEK,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,EAAE,QAAQ,GAAE,MAAM,GAAG,IAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAahF;CA6EF"}
@@ -0,0 +1,210 @@
1
+ import { PROTOCOL_VERSION, TERMINAL_FRAME_OUTPUT, encodeTerminalFrames, } from "@termlink/protocol";
2
+ import { HostError } from "../errors.js";
3
+ const DEFAULT_FLOW = { highWaterBytes: 512 * 1024, lowWaterBytes: 128 * 1024, ackTimeoutMs: 5_000 };
4
+ /**
5
+ * One terminal session: a shell in a PTY and the connections watching it. Output is
6
+ * broadcast as binary frames; there is no replay log, a late client gets the screen.
7
+ *
8
+ * Flow control: clients say how much output they have drawn (terminal.ack). When the
9
+ * slowest one falls too far behind, the shell is paused, so a slow link is not dropped
10
+ * by the relay for failing to keep up. A client that stops acking is dropped from the
11
+ * calculation after a timeout, so one dead browser tab cannot freeze the shell.
12
+ */
13
+ export class TerminalSession {
14
+ id;
15
+ #info;
16
+ #onLifecycle;
17
+ #listeners = new Set();
18
+ #clients = new Map();
19
+ #flow;
20
+ #terminal = null;
21
+ #sent = 0;
22
+ #pausedForFlow = false;
23
+ #pausedForCatchUp = 0;
24
+ #flowTimer = null;
25
+ constructor(info, onLifecycle, flow = {}) {
26
+ this.id = info.id;
27
+ this.#info = info;
28
+ this.#onLifecycle = onLifecycle;
29
+ this.#flow = {
30
+ highWaterBytes: flow.highWaterBytes ?? DEFAULT_FLOW.highWaterBytes,
31
+ lowWaterBytes: flow.lowWaterBytes ?? DEFAULT_FLOW.lowWaterBytes,
32
+ ackTimeoutMs: flow.ackTimeoutMs ?? DEFAULT_FLOW.ackTimeoutMs,
33
+ };
34
+ }
35
+ get info() {
36
+ return { ...this.#info };
37
+ }
38
+ get closed() {
39
+ return this.#info.status === "closed";
40
+ }
41
+ /** Bytes of output sent so far. For tests. */
42
+ get sentBytes() {
43
+ return this.#sent;
44
+ }
45
+ get paused() {
46
+ return this.#pausedForFlow;
47
+ }
48
+ announce() {
49
+ this.#onLifecycle(this.#event("session.created", { session: this.info }));
50
+ }
51
+ bind(terminal) {
52
+ this.#terminal = terminal;
53
+ this.#info.pid = terminal.pid;
54
+ this.#info.cols = terminal.cols;
55
+ this.#info.rows = terminal.rows;
56
+ terminal.onData((data) => this.#output(data));
57
+ terminal.onExit((exit) => void this.close("the shell exited", exit.exitCode));
58
+ this.#setStatus("running");
59
+ }
60
+ attach(listener, clientId) {
61
+ if (this.closed)
62
+ throw new HostError("conflict", "session is closed");
63
+ this.#listeners.add(listener);
64
+ if (clientId)
65
+ this.#clients.set(clientId, { base: this.#sent, acked: 0, lastAckAt: Date.now() });
66
+ return {
67
+ detach: () => {
68
+ this.#listeners.delete(listener);
69
+ if (clientId)
70
+ this.forgetClient(clientId);
71
+ },
72
+ catchUp: () => this.#catchUp(),
73
+ };
74
+ }
75
+ /** A client left without detaching its attachment (session.detach with a clientId). */
76
+ forgetClient(clientId) {
77
+ if (this.#clients.delete(clientId))
78
+ this.#applyFlow();
79
+ }
80
+ write(data) {
81
+ if (this.closed)
82
+ throw new HostError("conflict", "session is closed");
83
+ this.#terminal?.write(data);
84
+ }
85
+ resize(cols, rows) {
86
+ if (this.closed)
87
+ throw new HostError("conflict", "session is closed");
88
+ if (!this.#terminal)
89
+ throw new HostError("conflict", "session is still starting");
90
+ this.#terminal.resize(cols, rows);
91
+ this.#info.cols = cols;
92
+ this.#info.rows = rows;
93
+ this.#emit("terminal.size", { cols, rows });
94
+ this.#announce();
95
+ }
96
+ ack(clientId, bytes) {
97
+ const client = this.#clients.get(clientId);
98
+ if (!client)
99
+ return; // Attached without a clientId, or already dropped: not part of flow control.
100
+ client.acked = Math.max(client.acked, bytes);
101
+ client.lastAckAt = Date.now();
102
+ this.#applyFlow();
103
+ }
104
+ kill() {
105
+ if (this.closed)
106
+ throw new HostError("conflict", "session is closed");
107
+ this.#terminal?.kill();
108
+ }
109
+ async close(reason, exitCode = null) {
110
+ if (this.closed)
111
+ return;
112
+ if (this.#flowTimer)
113
+ clearTimeout(this.#flowTimer);
114
+ this.#flowTimer = null;
115
+ const terminal = this.#terminal;
116
+ this.#terminal = null;
117
+ if (terminal && !terminal.exit)
118
+ terminal.kill();
119
+ this.#info.status = "closed";
120
+ this.#info.exitCode = exitCode;
121
+ this.#info.updatedAt = Date.now();
122
+ this.#onLifecycle(this.#event("session.closed", { session: this.info, reason, exitCode }));
123
+ this.#listeners.clear();
124
+ this.#clients.clear();
125
+ }
126
+ async #catchUp() {
127
+ const terminal = this.#terminal;
128
+ if (!terminal || this.closed)
129
+ return;
130
+ // Nothing new arrives while the snapshot is taken, so the screen and what follows
131
+ // it never overlap.
132
+ this.#pausedForCatchUp++;
133
+ terminal.pause();
134
+ try {
135
+ this.#emit("terminal.reset", { cols: terminal.cols, rows: terminal.rows });
136
+ const snapshot = await terminal.snapshot();
137
+ if (snapshot.length > 0)
138
+ this.#output(snapshot);
139
+ }
140
+ finally {
141
+ this.#pausedForCatchUp--;
142
+ if (this.#pausedForCatchUp === 0 && !this.#pausedForFlow)
143
+ terminal.resume();
144
+ }
145
+ }
146
+ #output(data) {
147
+ if (this.closed)
148
+ return;
149
+ this.#sent += data.length;
150
+ const frames = encodeTerminalFrames(TERMINAL_FRAME_OUTPUT, this.id, data);
151
+ for (const listener of this.#listeners)
152
+ for (const frame of frames)
153
+ listener.bytes(frame);
154
+ this.#applyFlow();
155
+ }
156
+ #applyFlow() {
157
+ const terminal = this.#terminal;
158
+ if (!terminal)
159
+ return;
160
+ const now = Date.now();
161
+ let worstLag = 0;
162
+ for (const [clientId, client] of this.#clients) {
163
+ const lag = this.#sent - client.base - client.acked;
164
+ if (lag > 0 && now - client.lastAckAt > this.#flow.ackTimeoutMs) {
165
+ this.#clients.delete(clientId); // Gone, or too slow to matter: the relay has dropped it by now.
166
+ continue;
167
+ }
168
+ worstLag = Math.max(worstLag, lag);
169
+ }
170
+ const shouldPause = this.#pausedForFlow ? worstLag > this.#flow.lowWaterBytes : worstLag > this.#flow.highWaterBytes;
171
+ if (shouldPause !== this.#pausedForFlow) {
172
+ this.#pausedForFlow = shouldPause;
173
+ if (this.#pausedForCatchUp === 0) {
174
+ if (shouldPause)
175
+ terminal.pause();
176
+ else
177
+ terminal.resume();
178
+ }
179
+ }
180
+ // A paused shell with a silent client would wait forever; look again after the timeout.
181
+ if (this.#flowTimer)
182
+ clearTimeout(this.#flowTimer);
183
+ this.#flowTimer = null;
184
+ if (shouldPause) {
185
+ this.#flowTimer = setTimeout(() => this.#applyFlow(), this.#flow.ackTimeoutMs + 50);
186
+ this.#flowTimer.unref();
187
+ }
188
+ }
189
+ #event(type, payload) {
190
+ return { v: PROTOCOL_VERSION, kind: "evt", type, ts: Date.now(), sessionId: this.id, payload };
191
+ }
192
+ #emit(type, payload) {
193
+ if (this.closed)
194
+ return;
195
+ const event = this.#event(type, payload);
196
+ for (const listener of this.#listeners)
197
+ listener.event(event);
198
+ }
199
+ #setStatus(status) {
200
+ if (this.closed || this.#info.status === status)
201
+ return;
202
+ this.#info.status = status;
203
+ this.#announce();
204
+ }
205
+ #announce() {
206
+ this.#info.updatedAt = Date.now();
207
+ this.#onLifecycle(this.#event("session.updated", { session: this.info }));
208
+ }
209
+ }
210
+ //# sourceMappingURL=terminal-session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"terminal-session.js","sourceRoot":"","sources":["../../src/session/terminal-session.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function newId(prefix: string): string;
2
+ //# sourceMappingURL=id.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"id.d.ts","sourceRoot":"","sources":["../../src/util/id.ts"],"names":[],"mappings":"AAEA,wBAAgB,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAE5C"}
@@ -0,0 +1,5 @@
1
+ import { randomBytes } from "node:crypto";
2
+ export function newId(prefix) {
3
+ return `${prefix}_${randomBytes(6).toString("base64url")}`;
4
+ }
5
+ //# sourceMappingURL=id.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"id.js","sourceRoot":"","sources":["../../src/util/id.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,MAAM,UAAU,KAAK,CAAC,MAAc;IAClC,OAAO,GAAG,MAAM,IAAI,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;AAC7D,CAAC"}
@@ -0,0 +1,12 @@
1
+ /** Another live process holds the lock. */
2
+ export declare class LockHeldError extends Error {
3
+ readonly pid: number;
4
+ constructor(file: string, pid: number);
5
+ }
6
+ /**
7
+ * Takes a lock file holding this process's pid. A lock left behind by a process that is
8
+ * gone (killed, crashed) is taken over. Returns a release that removes the file only while
9
+ * it is still ours.
10
+ */
11
+ export declare function acquirePidLock(file: string, pid?: number): Promise<() => Promise<void>>;
12
+ //# sourceMappingURL=lock.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lock.d.ts","sourceRoot":"","sources":["../../src/util/lock.ts"],"names":[],"mappings":"AAGA,2CAA2C;AAC3C,qBAAa,aAAc,SAAQ,KAAK;IACtC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IAErB,YAAY,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAIpC;CACF;AAiBD;;;;GAIG;AACH,wBAAsB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,SAAc,GAAG,OAAO,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,CAgBlG"}
@@ -0,0 +1,52 @@
1
+ import { mkdir, readFile, rm, writeFile } from "node:fs/promises";
2
+ import path from "node:path";
3
+ /** Another live process holds the lock. */
4
+ export class LockHeldError extends Error {
5
+ pid;
6
+ constructor(file, pid) {
7
+ super(`${file} is held by process ${pid}`);
8
+ this.name = "LockHeldError";
9
+ this.pid = pid;
10
+ }
11
+ }
12
+ function alive(pid) {
13
+ try {
14
+ process.kill(pid, 0);
15
+ return true;
16
+ }
17
+ catch (err) {
18
+ // EPERM: the process exists but belongs to someone else.
19
+ return err.code === "EPERM";
20
+ }
21
+ }
22
+ async function holder(file) {
23
+ const pid = Number.parseInt(await readFile(file, "utf8").catch(() => ""), 10);
24
+ return Number.isInteger(pid) && pid > 0 ? pid : null;
25
+ }
26
+ /**
27
+ * Takes a lock file holding this process's pid. A lock left behind by a process that is
28
+ * gone (killed, crashed) is taken over. Returns a release that removes the file only while
29
+ * it is still ours.
30
+ */
31
+ export async function acquirePidLock(file, pid = process.pid) {
32
+ await mkdir(path.dirname(file), { recursive: true });
33
+ for (let attempt = 0; attempt < 2; attempt++) {
34
+ try {
35
+ await writeFile(file, `${pid}\n`, { flag: "wx", mode: 0o600 });
36
+ return async () => {
37
+ if ((await holder(file)) === pid)
38
+ await rm(file, { force: true });
39
+ };
40
+ }
41
+ catch (err) {
42
+ if (err.code !== "EEXIST")
43
+ throw err;
44
+ const current = await holder(file);
45
+ if (current !== null && current !== pid && alive(current))
46
+ throw new LockHeldError(file, current);
47
+ await rm(file, { force: true });
48
+ }
49
+ }
50
+ throw new Error(`could not take the lock ${file}`);
51
+ }
52
+ //# sourceMappingURL=lock.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lock.js","sourceRoot":"","sources":["../../src/util/lock.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAClE,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,2CAA2C;AAC3C,MAAM,OAAO,aAAc,SAAQ,KAAK;IAC7B,GAAG,CAAS;IAErB,YAAY,IAAY,EAAE,GAAW;QACnC,KAAK,CAAC,GAAG,IAAI,uBAAuB,GAAG,EAAE,CAAC,CAAC;QAC3C,IAAI,CAAC,IAAI,GAAG,eAAe,CAAC;QAC5B,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;IACjB,CAAC;CACF;AAED,SAAS,KAAK,CAAC,GAAW;IACxB,IAAI,CAAC;QACH,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QACrB,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,yDAAyD;QACzD,OAAQ,GAA6B,CAAC,IAAI,KAAK,OAAO,CAAC;IACzD,CAAC;AACH,CAAC;AAED,KAAK,UAAU,MAAM,CAAC,IAAY;IAChC,MAAM,GAAG,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;IAC9E,OAAO,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;AACvD,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,IAAY,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG;IAClE,MAAM,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACrD,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,GAAG,CAAC,EAAE,OAAO,EAAE,EAAE,CAAC;QAC7C,IAAI,CAAC;YACH,MAAM,SAAS,CAAC,IAAI,EAAE,GAAG,GAAG,IAAI,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;YAC/D,OAAO,KAAK,IAAI,EAAE;gBAChB,IAAI,CAAC,MAAM,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,GAAG;oBAAE,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;YACpE,CAAC,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAK,GAA6B,CAAC,IAAI,KAAK,QAAQ;gBAAE,MAAM,GAAG,CAAC;YAChE,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,CAAC;YACnC,IAAI,OAAO,KAAK,IAAI,IAAI,OAAO,KAAK,GAAG,IAAI,KAAK,CAAC,OAAO,CAAC;gBAAE,MAAM,IAAI,aAAa,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;YAClG,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QAClC,CAAC;IACH,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,2BAA2B,IAAI,EAAE,CAAC,CAAC;AACrD,CAAC"}
@@ -0,0 +1,3 @@
1
+ /** Absolute path of `binary` in the first PATH folder that has it, or null. */
2
+ export declare function findOnPath(binary: string, env?: NodeJS.ProcessEnv): string | null;
3
+ //# sourceMappingURL=which.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"which.d.ts","sourceRoot":"","sources":["../../src/util/which.ts"],"names":[],"mappings":"AAGA,+EAA+E;AAC/E,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,GAAG,IAAI,CAM9F"}
@@ -0,0 +1,12 @@
1
+ import { existsSync } from "node:fs";
2
+ import path from "node:path";
3
+ /** Absolute path of `binary` in the first PATH folder that has it, or null. */
4
+ export function findOnPath(binary, env = process.env) {
5
+ for (const dir of (env.PATH ?? env.Path ?? "").split(path.delimiter).filter(Boolean)) {
6
+ const candidate = path.join(dir, binary);
7
+ if (existsSync(candidate))
8
+ return path.resolve(candidate);
9
+ }
10
+ return null;
11
+ }
12
+ //# sourceMappingURL=which.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"which.js","sourceRoot":"","sources":["../../src/util/which.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,+EAA+E;AAC/E,MAAM,UAAU,UAAU,CAAC,MAAc,EAAE,GAAG,GAAsB,OAAO,CAAC,GAAG;IAC7E,KAAK,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;QACrF,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QACzC,IAAI,UAAU,CAAC,SAAS,CAAC;YAAE,OAAO,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAC5D,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare const VERSION: string;
2
+ //# sourceMappingURL=version.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,OAAO,EAAE,MAAgB,CAAC"}
@@ -0,0 +1,5 @@
1
+ import { createRequire } from "node:module";
2
+ // The package's own version, so `termlink --version` and host.ready say what npm installed.
3
+ const { version } = createRequire(import.meta.url)("../package.json");
4
+ export const VERSION = version;
5
+ //# sourceMappingURL=version.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.js","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,4FAA4F;AAC5F,MAAM,EAAE,OAAO,EAAE,GAAG,aAAa,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,iBAAiB,CAAwB,CAAC;AAE7F,MAAM,CAAC,MAAM,OAAO,GAAW,OAAO,CAAC"}
package/package.json ADDED
@@ -0,0 +1,56 @@
1
+ {
2
+ "name": "@termlink/cli",
3
+ "version": "0.1.0",
4
+ "description": "TermLink: terminals, Claude Code and Codex sessions on your machine, reachable from the TermLink web app",
5
+ "type": "module",
6
+ "bin": {
7
+ "termlink": "./dist/cli.js"
8
+ },
9
+ "exports": {
10
+ ".": {
11
+ "source": "./src/index.ts",
12
+ "types": "./dist/index.d.ts",
13
+ "default": "./dist/index.js"
14
+ }
15
+ },
16
+ "files": [
17
+ "dist"
18
+ ],
19
+ "scripts": {
20
+ "build": "tsc -b",
21
+ "dev": "node --conditions=source --import tsx src/cli.ts start",
22
+ "demo": "node --conditions=source --import tsx scripts/demo-client.ts",
23
+ "relay-smoke": "node --conditions=source --import tsx scripts/relay-smoke.ts",
24
+ "test": "node --conditions=source --import tsx --test \"test/**/*.test.ts\"",
25
+ "codex:types": "codex app-server generate-ts --out node_modules/.codex-types",
26
+ "bundle": "node scripts/build.mjs",
27
+ "prepublishOnly": "tsc -b && node scripts/bake-oauth.mjs"
28
+ },
29
+ "dependencies": {
30
+ "@anthropic-ai/claude-agent-sdk": "^0.3.268",
31
+ "@termlink/protocol": "^0.1.0",
32
+ "@termlink/terminal": "^0.1.0",
33
+ "diff": "^9.0.0",
34
+ "ws": "^8.21.3"
35
+ },
36
+ "devDependencies": {
37
+ "esbuild": "^0.28.2"
38
+ },
39
+ "license": "MIT",
40
+ "author": "Bert Shim",
41
+ "homepage": "https://getterm.link",
42
+ "publishConfig": {
43
+ "access": "public"
44
+ },
45
+ "keywords": [
46
+ "termlink",
47
+ "terminal",
48
+ "claude",
49
+ "codex",
50
+ "pty",
51
+ "remote"
52
+ ],
53
+ "engines": {
54
+ "node": ">=22"
55
+ }
56
+ }