tmux-ide 2.9.6 → 2.9.7

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 (80) hide show
  1. package/bin/cli.js +2597 -1322
  2. package/package.json +1 -1
  3. package/packages/contracts/src/index.ts +5 -0
  4. package/packages/contracts/src/pane-stream.ts +37 -0
  5. package/packages/contracts/src/terminal-graphics.ts +92 -0
  6. package/packages/contracts/src/terminal-history-anchor.ts +61 -0
  7. package/packages/contracts/src/tmux-server-diagnostics.ts +16 -0
  8. package/packages/core/src/index.ts +1 -0
  9. package/packages/core/src/kitty-placeholders.ts +190 -0
  10. package/packages/daemon/dist/command-center/tmux-server-diagnostics.js +24 -0
  11. package/packages/daemon/dist/command-center/tmux-server-history-anchor.js +48 -0
  12. package/packages/daemon/dist/command-center/tmux-servers.js +11 -0
  13. package/packages/daemon/dist/lib/canonical-daemon-bootstrap.js +23 -1
  14. package/packages/daemon/dist/lib/daemon-embed.js +21 -0
  15. package/packages/daemon/dist/lib/tmux-server-owner.js +10 -1
  16. package/packages/daemon/dist/lib/tmux-session-mutation-fence.js +2 -1
  17. package/packages/daemon/dist/native/TmuxIdeNotifier.app/Contents/Info.plist +2 -2
  18. package/packages/daemon/dist/native/TmuxIdeNotifier.app/Contents/MacOS/tmux-ide-notifier +0 -0
  19. package/packages/daemon/dist/native/TmuxIdeNotifier.app/Contents/Resources/Assets.car +0 -0
  20. package/packages/daemon/dist/native/TmuxIdeNotifier.app/Contents/_CodeSignature/CodeResources +2 -2
  21. package/packages/daemon/dist/native/tmux/darwin-arm64/lib/libevent_core-2.1.7.dylib +0 -0
  22. package/packages/daemon/dist/native/tmux/darwin-arm64/lib/libutf8proc.3.3.0.dylib +0 -0
  23. package/packages/daemon/dist/native/tmux/darwin-arm64/manifest.json +8 -4
  24. package/packages/daemon/dist/native/tmux/darwin-arm64/tmux +0 -0
  25. package/packages/daemon/dist/native/tmux/linux-arm64/manifest.json +5 -1
  26. package/packages/daemon/dist/native/tmux/linux-arm64/tmux +0 -0
  27. package/packages/daemon/dist/native/tmux/linux-x64/manifest.json +5 -1
  28. package/packages/daemon/dist/native/tmux/linux-x64/tmux +0 -0
  29. package/packages/daemon/dist/terminal/graphics/kitty-graphics.js +578 -0
  30. package/packages/daemon/dist/terminal/mirror/control-channel.js +17 -1
  31. package/packages/daemon/dist/terminal/mirror/mirror-service.js +1 -0
  32. package/packages/daemon/dist/terminal/mirror/native-grid-capture.js +8 -0
  33. package/packages/daemon/dist/terminal/mirror/native-grid-reader.js +6 -1
  34. package/packages/daemon/dist/terminal/mirror/session-channel.js +11 -2
  35. package/packages/daemon/dist/terminal/pane-stream/pane-stream-websocket.js +78 -1
  36. package/packages/daemon/dist/terminal/protocol/session-descriptor-discovery.js +3 -2
  37. package/packages/daemon/dist/terminal/session-runtime/history-anchor-owner.js +171 -0
  38. package/packages/daemon/dist/terminal/session-runtime/registry.js +20 -0
  39. package/packages/daemon/dist/terminal/session-runtime/terminal-delivery-hub.js +20 -1
  40. package/packages/daemon/dist/terminal/session-runtime/terminal-replica-interpreter.js +68 -1
  41. package/packages/daemon/dist/terminal/session-runtime/terminal-replica-owner.js +30 -0
  42. package/packages/daemon/dist/terminal/session-runtime/transport-binding.js +49 -21
  43. package/packages/daemon/dist/terminal/session-runtime/xterm-terminal-interpreter-backend.js +11 -0
  44. package/packages/daemon/dist/tui/mirror/runtime/application-home-agents-owner.js +7 -1
  45. package/packages/daemon/dist/tui/mirror/runtime/application-terminal-input-ingress.js +35 -5
  46. package/packages/daemon/dist/tui/mirror/runtime/application-terminal-paste.js +2 -2
  47. package/packages/daemon/dist/tui/mirror/runtime/terminal-input-adapter.js +2 -2
  48. package/packages/daemon/src/command-center/tmux-server-diagnostics.ts +38 -0
  49. package/packages/daemon/src/command-center/tmux-server-history-anchor.ts +69 -0
  50. package/packages/daemon/src/command-center/tmux-servers.ts +11 -0
  51. package/packages/daemon/src/lib/canonical-daemon-bootstrap.ts +20 -2
  52. package/packages/daemon/src/lib/daemon-embed.ts +26 -0
  53. package/packages/daemon/src/lib/tmux-server-owner.ts +10 -0
  54. package/packages/daemon/src/lib/tmux-session-mutation-fence.ts +2 -1
  55. package/packages/daemon/src/terminal/graphics/kitty-graphics.ts +641 -0
  56. package/packages/daemon/src/terminal/mirror/control-channel.ts +18 -1
  57. package/packages/daemon/src/terminal/mirror/mirror-service.ts +3 -0
  58. package/packages/daemon/src/terminal/mirror/native-grid-capture.ts +11 -0
  59. package/packages/daemon/src/terminal/mirror/native-grid-reader.ts +10 -1
  60. package/packages/daemon/src/terminal/mirror/session-channel.ts +14 -1
  61. package/packages/daemon/src/terminal/pane-stream/pane-stream-websocket.ts +82 -0
  62. package/packages/daemon/src/terminal/protocol/session-descriptor-discovery.ts +3 -2
  63. package/packages/daemon/src/terminal/session-runtime/history-anchor-owner.ts +190 -0
  64. package/packages/daemon/src/terminal/session-runtime/registry.ts +20 -0
  65. package/packages/daemon/src/terminal/session-runtime/terminal-delivery-hub.ts +38 -0
  66. package/packages/daemon/src/terminal/session-runtime/terminal-interpreter-backend.ts +4 -0
  67. package/packages/daemon/src/terminal/session-runtime/terminal-replica-interpreter.ts +83 -1
  68. package/packages/daemon/src/terminal/session-runtime/terminal-replica-owner.ts +39 -0
  69. package/packages/daemon/src/terminal/session-runtime/transport-binding.ts +53 -24
  70. package/packages/daemon/src/terminal/session-runtime/xterm-terminal-interpreter-backend.ts +13 -0
  71. package/packages/daemon/src/tui/mirror/runtime/application-home-agents-owner.ts +6 -1
  72. package/packages/daemon/src/tui/mirror/runtime/application-terminal-input-ingress.ts +44 -9
  73. package/packages/daemon/src/tui/mirror/runtime/application-terminal-paste.ts +2 -1
  74. package/packages/daemon/src/tui/mirror/runtime/terminal-input-adapter.ts +5 -2
  75. package/packages/daemon-client/src/fleet-connection-status.ts +1 -1
  76. package/packages/daemon-client/src/pane-creation-refusal.ts +48 -0
  77. package/packages/daemon-client/src/pane-stream-client.ts +29 -0
  78. package/packages/daemon-client/src/tmux-server-client.ts +133 -6
  79. package/packages/daemon/dist/native/tmux/darwin-arm64/lib/libutf8proc.3.2.3.dylib +0 -0
  80. /package/packages/daemon/dist/native/tmux/darwin-arm64/licenses/{libutf8proc.3.2.3.dylib.txt → libutf8proc.3.3.0.dylib.txt} +0 -0
@@ -1,4 +1,9 @@
1
+ import { readPaneCreationRefusal } from "./pane-creation-refusal.ts";
1
2
  import {
3
+ HistoryAnchorRequestSchemaZ,
4
+ HistoryAnchorResponseSchemaZ,
5
+ type HistoryAnchorRequest,
6
+ TmuxServerDiagnosticsSchemaZ,
2
7
  TmuxAgentOpenRequestSchemaZ,
3
8
  TmuxAgentOpenResponseSchemaZ,
4
9
  type TmuxAgentOpenRequest,
@@ -49,6 +54,7 @@ export class TmuxServerClientError extends Error {
49
54
  constructor(
50
55
  readonly code: "disposed" | "scope-mismatch" | "request-failed",
51
56
  readonly status?: number,
57
+ readonly refusalCode?: "harness_unavailable",
52
58
  ) {
53
59
  super(`tmux server client ${code}`);
54
60
  this.name = "TmuxServerClientError";
@@ -61,7 +67,12 @@ async function request(
61
67
  headers?: Record<string, string>,
62
68
  method?: "DELETE",
63
69
  signal?: AbortSignal,
70
+ responseLimit?: number,
71
+ paneCreationRefusal = false,
64
72
  ) {
73
+ const requestSignal = signal
74
+ ? AbortSignal.any([signal, AbortSignal.timeout(options.timeoutMs ?? 5_000)])
75
+ : AbortSignal.timeout(options.timeoutMs ?? 5_000);
65
76
  const response = await (options.fetch ?? fetch)(new URL(path, options.baseUrl), {
66
77
  method: method ?? (body === undefined ? "GET" : "POST"),
67
78
  headers: {
@@ -72,13 +83,45 @@ async function request(
72
83
  ...(body === undefined ? {} : { body: JSON.stringify(body) }),
73
84
  redirect: "error",
74
85
  cache: "no-store",
75
- signal: signal
76
- ? AbortSignal.any([signal, AbortSignal.timeout(options.timeoutMs ?? 5_000)])
77
- : AbortSignal.timeout(options.timeoutMs ?? 5_000),
86
+ signal: requestSignal,
78
87
  });
79
- if (!response.ok) throw new TmuxServerClientError("request-failed", response.status);
80
- const result: unknown = await response.json();
81
- signal?.throwIfAborted();
88
+ if (!response.ok)
89
+ throw new TmuxServerClientError(
90
+ "request-failed",
91
+ response.status,
92
+ paneCreationRefusal ? await readPaneCreationRefusal(response, requestSignal) : undefined,
93
+ );
94
+ let result: unknown;
95
+ if (responseLimit === undefined) result = await response.json();
96
+ else {
97
+ const reader = response.body?.getReader();
98
+ if (!reader) throw new TmuxServerClientError("request-failed");
99
+ const chunks: Uint8Array[] = [];
100
+ let length = 0;
101
+ try {
102
+ for (;;) {
103
+ requestSignal.throwIfAborted();
104
+ const item = await reader.read();
105
+ if (item.done) break;
106
+ length += item.value.byteLength;
107
+ if (length > responseLimit) {
108
+ void reader.cancel().catch(() => undefined);
109
+ throw new TmuxServerClientError("request-failed");
110
+ }
111
+ chunks.push(item.value);
112
+ }
113
+ const bytes = new Uint8Array(length);
114
+ let offset = 0;
115
+ for (const chunk of chunks) {
116
+ bytes.set(chunk, offset);
117
+ offset += chunk.byteLength;
118
+ }
119
+ result = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes));
120
+ } finally {
121
+ reader.releaseLock();
122
+ }
123
+ }
124
+ requestSignal.throwIfAborted();
82
125
  return result;
83
126
  }
84
127
  export async function listTmuxServers(options: TmuxServerClientOptions) {
@@ -140,6 +183,7 @@ export function createTmuxServerClient(
140
183
  headers?: Record<string, string>,
141
184
  signal?: AbortSignal,
142
185
  defaultTimeoutMs?: number,
186
+ paneCreationRefusal = false,
143
187
  ) {
144
188
  assertCurrent();
145
189
  const result = await request(
@@ -151,6 +195,8 @@ export function createTmuxServerClient(
151
195
  headers,
152
196
  undefined,
153
197
  signal,
198
+ undefined,
199
+ paneCreationRefusal,
154
200
  );
155
201
  assertCurrent();
156
202
  return result;
@@ -352,6 +398,10 @@ export function createTmuxServerClient(
352
398
  await scopedRequest(
353
399
  `panes/create?liveSessionId=${encodeURIComponent(liveSessionId)}`,
354
400
  body,
401
+ undefined,
402
+ undefined,
403
+ undefined,
404
+ true,
355
405
  ),
356
406
  );
357
407
  if (
@@ -426,3 +476,80 @@ export function createTmuxServerClient(
426
476
  };
427
477
  }
428
478
  export type TmuxServerClient = ReturnType<typeof createTmuxServerClient>;
479
+
480
+ /** Optional metadata; old servers have no route. Callers own selected-scope currentness. */
481
+ export async function readTmuxServerDiagnostics(
482
+ options: TmuxServerClientOptions,
483
+ scopeInput: TmuxServerScope,
484
+ signal?: AbortSignal,
485
+ ) {
486
+ const scope = TmuxServerScopeSchemaZ.parse(scopeInput);
487
+ signal?.throwIfAborted();
488
+ try {
489
+ const result = TmuxServerDiagnosticsSchemaZ.parse(
490
+ await request(
491
+ options,
492
+ `${TMUX_SERVERS_API_PATH}/${scope.serverId}/${scope.generation}/diagnostics`,
493
+ undefined,
494
+ undefined,
495
+ undefined,
496
+ signal,
497
+ 4096,
498
+ ),
499
+ );
500
+ if (result.server.serverId !== scope.serverId || result.server.generation !== scope.generation)
501
+ throw new TmuxServerClientError("scope-mismatch");
502
+ return result;
503
+ } catch (error) {
504
+ signal?.throwIfAborted();
505
+ if (error instanceof TmuxServerClientError && error.status === 404) return null;
506
+ throw error;
507
+ }
508
+ }
509
+
510
+ /** Optional old-daemon endpoint. Never retries, creates sessions, or admits input. */
511
+ export async function requestHistoryAnchor(
512
+ options: TmuxServerClientOptions,
513
+ scopeInput: TmuxServerScope,
514
+ input: HistoryAnchorRequest,
515
+ signal?: AbortSignal,
516
+ ) {
517
+ const scope = TmuxServerScopeSchemaZ.parse(scopeInput),
518
+ body = HistoryAnchorRequestSchemaZ.parse(input);
519
+ if (body.proof.generation !== scope.generation) throw new TmuxServerClientError("scope-mismatch");
520
+ signal?.throwIfAborted();
521
+ try {
522
+ const value = HistoryAnchorResponseSchemaZ.parse(
523
+ await request(
524
+ options,
525
+ `${TMUX_SERVERS_API_PATH}/${scope.serverId}/${scope.generation}/history-anchor`,
526
+ body,
527
+ undefined,
528
+ undefined,
529
+ signal,
530
+ 4096,
531
+ ),
532
+ );
533
+ if (value.server.serverId !== scope.serverId || value.server.generation !== scope.generation)
534
+ throw new TmuxServerClientError("scope-mismatch");
535
+ if (
536
+ value.result.status === "resolved" &&
537
+ Object.entries(body.proof).some(
538
+ ([key, v]) =>
539
+ value.result.status === "resolved" &&
540
+ value.result.proof[key as keyof typeof body.proof] !== v,
541
+ )
542
+ )
543
+ throw new TmuxServerClientError("scope-mismatch");
544
+ if (
545
+ (body.operation.kind === "capture" && value.result.status === "resolved") ||
546
+ (body.operation.kind === "resolve" && value.result.status === "captured")
547
+ )
548
+ throw new TmuxServerClientError("scope-mismatch");
549
+ return value;
550
+ } catch (error) {
551
+ signal?.throwIfAborted();
552
+ if (error instanceof TmuxServerClientError && error.status === 404) return null;
553
+ throw error;
554
+ }
555
+ }