tmux-ide 2.9.2 → 2.9.3

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 (263) hide show
  1. package/README.md +1 -1
  2. package/bin/cli.js +2071 -625
  3. package/package.json +14 -5
  4. package/packages/contracts/src/desktop-host.ts +3 -0
  5. package/packages/contracts/src/saved-machines.ts +19 -0
  6. package/packages/contracts/src/terminal-replica.ts +1 -1
  7. package/packages/core/package.json +3 -2
  8. package/packages/core/src/terminal-delivery.ts +51 -3
  9. package/packages/core/src/terminal-fnv64-wasm.ts +4 -3
  10. package/packages/core/src/terminal-replica-hash-cache.ts +129 -31
  11. package/packages/core/src/terminal-replica-owned-row.ts +27 -0
  12. package/packages/core/src/terminal-replica.ts +13 -28
  13. package/packages/daemon/dist/command-center/daemon-fleet-facts-observer.js +96 -10
  14. package/packages/daemon/dist/command-center/resources/saved-machine-route.js +40 -1
  15. package/packages/daemon/dist/command-center/ws-events.js +5 -24
  16. package/packages/daemon/dist/lib/canonical-daemon-bootstrap.js +8 -0
  17. package/packages/daemon/dist/lib/canonical-daemon.js +28 -2
  18. package/packages/daemon/dist/lib/daemon-embed.js +1 -1
  19. package/packages/daemon/dist/lib/daemon-service-manager.js +122 -0
  20. package/packages/daemon/dist/lib/daemon-service-plan.js +127 -0
  21. package/packages/daemon/dist/lib/daemon-service.js +259 -0
  22. package/packages/daemon/dist/lib/install-origin.js +2 -0
  23. package/packages/daemon/dist/lib/local-fleet-request.js +9 -3
  24. package/packages/daemon/dist/lib/log.js +6 -10
  25. package/packages/daemon/dist/lib/managed-installer-update.js +67 -0
  26. package/packages/daemon/dist/lib/{tui-download-lock.js → private-operation-lock.js} +11 -11
  27. package/packages/daemon/dist/lib/remote-daemon-info.js +3 -2
  28. package/packages/daemon/dist/lib/remote-daemon-lifecycle.js +4 -4
  29. package/packages/daemon/dist/lib/remote-tmux-command.js +10 -0
  30. package/packages/daemon/dist/lib/runtime-namespace.js +28 -16
  31. package/packages/daemon/dist/lib/saved-machines.js +40 -2
  32. package/packages/daemon/dist/lib/ssh-daemon-transport.js +24 -9
  33. package/packages/daemon/dist/lib/tmux-server-owner.js +1 -1
  34. package/packages/daemon/dist/lib/tmux-server-registration.js +21 -3
  35. package/packages/daemon/dist/lib/tui-binary.js +2 -2
  36. package/packages/daemon/dist/lib/update.js +18 -0
  37. package/packages/daemon/dist/lib/workspace-multiplexer-verbs.js +24 -1
  38. package/packages/daemon/dist/machines.js +40 -4
  39. package/packages/daemon/dist/native/TmuxIdeNotifier.app/Contents/Info.plist +2 -2
  40. package/packages/daemon/dist/native/TmuxIdeNotifier.app/Contents/MacOS/tmux-ide-notifier +0 -0
  41. package/packages/daemon/dist/native/TmuxIdeNotifier.app/Contents/Resources/Assets.car +0 -0
  42. package/packages/daemon/dist/native/TmuxIdeNotifier.app/Contents/_CodeSignature/CodeResources +2 -2
  43. package/packages/daemon/dist/terminal/attachments/direct-websocket.js +4 -1
  44. package/packages/daemon/dist/terminal/attachments/native-runtime.js +22 -13
  45. package/packages/daemon/dist/terminal/mirror/mirror-service.js +101 -3
  46. package/packages/daemon/dist/terminal/mirror/registered-window-guard.js +62 -0
  47. package/packages/daemon/dist/terminal/mirror/session-channel.js +75 -4
  48. package/packages/daemon/dist/terminal/mirror/shared-window-index.js +45 -0
  49. package/packages/daemon/dist/terminal/pane-stream/pane-stream-websocket.js +11 -1
  50. package/packages/daemon/dist/terminal/session-runtime/multiplexer-backend.js +1 -0
  51. package/packages/daemon/dist/terminal/session-runtime/registry.js +56 -7
  52. package/packages/daemon/dist/terminal/session-runtime/semantic-mutation-executor.js +3 -1
  53. package/packages/daemon/dist/tui/mirror/dialog-model.js +2 -35
  54. package/packages/daemon/dist/tui/mirror/runtime/application-daemon-authority-owner.js +8 -0
  55. package/packages/daemon/dist/tui/mirror/runtime/application-home-fleet.js +20 -2
  56. package/packages/daemon/dist/tui/mirror/runtime/application-machine-agents.js +7 -1
  57. package/packages/daemon/dist/tui/mirror/runtime/application-machine-authority.js +59 -9
  58. package/packages/daemon/dist/tui/mirror/runtime/application-machine-navigation.js +27 -19
  59. package/packages/daemon/dist/tui/mirror/runtime/application-machine-sidebar.jsx +23 -18
  60. package/packages/daemon/dist/tui/mirror/runtime/application-machine-startup.js +31 -2
  61. package/packages/daemon/dist/tui/mirror/runtime/application-palette-search-owner.js +7 -3
  62. package/packages/daemon/dist/tui/mirror/runtime/application-performance-log.js +3 -0
  63. package/packages/daemon/dist/tui/mirror/runtime/application-terminal-input-ingress.js +146 -2
  64. package/packages/daemon/dist/tui/mirror/runtime/application-terminal-interaction-controller.js +201 -50
  65. package/packages/daemon/dist/tui/mirror/runtime/bounded-performance-record-writer.js +50 -10
  66. package/packages/daemon/dist/tui/mirror/runtime/terminal-fast-lane-renderer-adapter.js +6 -5
  67. package/packages/daemon/dist/tui/mirror/runtime/terminal-pane-input-router.js +3 -0
  68. package/packages/daemon/dist/tui/mirror/runtime/workspace-terminal-fast-lane.js +8 -2
  69. package/packages/daemon/dist/tui/mirror/terminal-text.js +35 -0
  70. package/packages/daemon/dist/tui/mirror/workspace/connection-feedback.js +5 -3
  71. package/packages/daemon/src/command-center/daemon-fleet-facts-observer.ts +100 -10
  72. package/packages/daemon/src/command-center/resources/saved-machine-route.ts +48 -1
  73. package/packages/daemon/src/command-center/ws-events.ts +5 -25
  74. package/packages/daemon/src/lib/canonical-daemon-bootstrap.ts +12 -0
  75. package/packages/daemon/src/lib/canonical-daemon.ts +44 -2
  76. package/packages/daemon/src/lib/daemon-embed.ts +1 -0
  77. package/packages/daemon/src/lib/daemon-service-manager.ts +152 -0
  78. package/packages/daemon/src/lib/daemon-service-plan.ts +153 -0
  79. package/packages/daemon/src/lib/daemon-service.ts +301 -0
  80. package/packages/daemon/src/lib/install-origin.ts +5 -0
  81. package/packages/daemon/src/lib/local-fleet-request.ts +19 -3
  82. package/packages/daemon/src/lib/log.ts +13 -9
  83. package/packages/daemon/src/lib/managed-installer-update.ts +79 -0
  84. package/packages/daemon/src/lib/{tui-download-lock.ts → private-operation-lock.ts} +15 -11
  85. package/packages/daemon/src/lib/remote-daemon-info.ts +3 -3
  86. package/packages/daemon/src/lib/remote-daemon-lifecycle.ts +4 -4
  87. package/packages/daemon/src/lib/remote-tmux-command.ts +12 -0
  88. package/packages/daemon/src/lib/runtime-namespace.ts +27 -18
  89. package/packages/daemon/src/lib/saved-machines.ts +40 -1
  90. package/packages/daemon/src/lib/ssh-daemon-transport.ts +25 -7
  91. package/packages/daemon/src/lib/tmux-server-owner.ts +1 -0
  92. package/packages/daemon/src/lib/tmux-server-registration.ts +21 -3
  93. package/packages/daemon/src/lib/tui-binary.ts +2 -2
  94. package/packages/daemon/src/lib/update.ts +24 -0
  95. package/packages/daemon/src/lib/workspace-multiplexer-verbs.ts +22 -0
  96. package/packages/daemon/src/machines.ts +53 -5
  97. package/packages/daemon/src/terminal/attachments/direct-websocket.ts +8 -2
  98. package/packages/daemon/src/terminal/attachments/native-runtime.ts +28 -13
  99. package/packages/daemon/src/terminal/mirror/mirror-service.ts +105 -3
  100. package/packages/daemon/src/terminal/mirror/registered-window-guard.ts +66 -0
  101. package/packages/daemon/src/terminal/mirror/session-channel.ts +92 -4
  102. package/packages/daemon/src/terminal/mirror/shared-window-index.ts +42 -0
  103. package/packages/daemon/src/terminal/pane-stream/pane-stream-websocket.ts +12 -1
  104. package/packages/daemon/src/terminal/session-runtime/multiplexer-backend.ts +2 -0
  105. package/packages/daemon/src/terminal/session-runtime/registry.ts +70 -8
  106. package/packages/daemon/src/terminal/session-runtime/semantic-mutation-executor.ts +3 -1
  107. package/packages/daemon/src/tui/mirror/dialog-model.ts +2 -32
  108. package/packages/daemon/src/tui/mirror/runtime/application-daemon-authority-owner.ts +8 -0
  109. package/packages/daemon/src/tui/mirror/runtime/application-home-fleet.ts +19 -2
  110. package/packages/daemon/src/tui/mirror/runtime/application-machine-agents.ts +6 -1
  111. package/packages/daemon/src/tui/mirror/runtime/application-machine-authority.ts +60 -11
  112. package/packages/daemon/src/tui/mirror/runtime/application-machine-navigation.ts +39 -33
  113. package/packages/daemon/src/tui/mirror/runtime/application-machine-sidebar.tsx +31 -23
  114. package/packages/daemon/src/tui/mirror/runtime/application-machine-startup.ts +38 -2
  115. package/packages/daemon/src/tui/mirror/runtime/application-palette-search-owner.ts +7 -4
  116. package/packages/daemon/src/tui/mirror/runtime/application-performance-log.ts +3 -0
  117. package/packages/daemon/src/tui/mirror/runtime/application-root-v2.tsx +1 -1
  118. package/packages/daemon/src/tui/mirror/runtime/application-shell-view.tsx +47 -46
  119. package/packages/daemon/src/tui/mirror/runtime/application-terminal-input-ingress.ts +165 -2
  120. package/packages/daemon/src/tui/mirror/runtime/application-terminal-interaction-controller.ts +207 -53
  121. package/packages/daemon/src/tui/mirror/runtime/bounded-performance-record-writer.ts +49 -9
  122. package/packages/daemon/src/tui/mirror/runtime/terminal-fast-lane-renderer-adapter.ts +6 -5
  123. package/packages/daemon/src/tui/mirror/runtime/terminal-pane-input-router.ts +4 -0
  124. package/packages/daemon/src/tui/mirror/runtime/workspace-terminal-fast-lane.ts +8 -3
  125. package/packages/daemon/src/tui/mirror/terminal-text.ts +32 -0
  126. package/packages/daemon/src/tui/mirror/workspace/connection-feedback.ts +6 -3
  127. package/packages/daemon-client/src/fleet-connection-status.ts +10 -1
  128. package/packages/daemon-client/src/workspace-client.ts +4 -1
  129. package/packages/contracts/src/__tests__/actions-contract.test.ts +0 -119
  130. package/packages/contracts/src/__tests__/agent-graph-overlay.test.ts +0 -428
  131. package/packages/contracts/src/__tests__/app-window-mutation.test.ts +0 -51
  132. package/packages/contracts/src/__tests__/app-window-state.test.ts +0 -34
  133. package/packages/contracts/src/__tests__/application-shell.test.ts +0 -645
  134. package/packages/contracts/src/__tests__/automation-operations.test.ts +0 -78
  135. package/packages/contracts/src/__tests__/causal-cell.test.ts +0 -47
  136. package/packages/contracts/src/__tests__/client-view-state.test.ts +0 -115
  137. package/packages/contracts/src/__tests__/cohesion-fixture.test.ts +0 -106
  138. package/packages/contracts/src/__tests__/commands.test.ts +0 -86
  139. package/packages/contracts/src/__tests__/control.test.ts +0 -154
  140. package/packages/contracts/src/__tests__/daemon-events.test.ts +0 -405
  141. package/packages/contracts/src/__tests__/daemon-resources.test.ts +0 -143
  142. package/packages/contracts/src/__tests__/daemon-wire.test.ts +0 -149
  143. package/packages/contracts/src/__tests__/desktop-host.test.ts +0 -269
  144. package/packages/contracts/src/__tests__/desktop-missions.test.ts +0 -215
  145. package/packages/contracts/src/__tests__/experience-conformance.test.ts +0 -153
  146. package/packages/contracts/src/__tests__/experience-kernel-boundary.test.ts +0 -113
  147. package/packages/contracts/src/__tests__/experience-shell.test.ts +0 -65
  148. package/packages/contracts/src/__tests__/fixtures/daemon-wire-v2.json +0 -35
  149. package/packages/contracts/src/__tests__/fixtures/daemon-wire-v3.json +0 -35
  150. package/packages/contracts/src/__tests__/fixtures/daemon-wire-v4.json +0 -35
  151. package/packages/contracts/src/__tests__/fixtures/scoped-receipt.ts +0 -62
  152. package/packages/contracts/src/__tests__/fleet-agent-graph.test.ts +0 -231
  153. package/packages/contracts/src/__tests__/fleet-catalog.test.ts +0 -270
  154. package/packages/contracts/src/__tests__/fleet-lifecycle.test.ts +0 -62
  155. package/packages/contracts/src/__tests__/focus-overlay.test.ts +0 -110
  156. package/packages/contracts/src/__tests__/ide-config.test.ts +0 -64
  157. package/packages/contracts/src/__tests__/interaction-evidence.test.ts +0 -288
  158. package/packages/contracts/src/__tests__/interaction-receipt-v2.test.ts +0 -72
  159. package/packages/contracts/src/__tests__/issue-error.test.ts +0 -78
  160. package/packages/contracts/src/__tests__/mission-projections.test.ts +0 -186
  161. package/packages/contracts/src/__tests__/missions.test.ts +0 -272
  162. package/packages/contracts/src/__tests__/multiplexer-verbs.test.ts +0 -242
  163. package/packages/contracts/src/__tests__/pane-appearance.test.ts +0 -146
  164. package/packages/contracts/src/__tests__/pane-read-result.test.ts +0 -55
  165. package/packages/contracts/src/__tests__/pane-stream.test.ts +0 -536
  166. package/packages/contracts/src/__tests__/pane-widget-marker.test.ts +0 -327
  167. package/packages/contracts/src/__tests__/performance-metrics.test.ts +0 -73
  168. package/packages/contracts/src/__tests__/performance-qualification.test.ts +0 -137
  169. package/packages/contracts/src/__tests__/rich-card-widget.test.ts +0 -29
  170. package/packages/contracts/src/__tests__/session-runtime.test.ts +0 -512
  171. package/packages/contracts/src/__tests__/startup-readiness.test.ts +0 -409
  172. package/packages/contracts/src/__tests__/terminal-attachment-stream.test.ts +0 -72
  173. package/packages/contracts/src/__tests__/terminal-attachments.test.ts +0 -329
  174. package/packages/contracts/src/__tests__/terminal-delivery.test.ts +0 -88
  175. package/packages/contracts/src/__tests__/terminal-runtime-inventory.test.ts +0 -68
  176. package/packages/contracts/src/__tests__/terminals.test.ts +0 -87
  177. package/packages/contracts/src/__tests__/tmux-server-scope.test.ts +0 -166
  178. package/packages/contracts/src/__tests__/transport-contract-loading.test.ts +0 -91
  179. package/packages/contracts/src/__tests__/visual-tokens.test.ts +0 -224
  180. package/packages/contracts/src/__tests__/window-links.test.ts +0 -243
  181. package/packages/contracts/src/__tests__/workspace-changes-resource.test.ts +0 -317
  182. package/packages/contracts/src/__tests__/workspace-changes-view.test.ts +0 -122
  183. package/packages/contracts/src/__tests__/workspace-config.test.ts +0 -294
  184. package/packages/contracts/src/__tests__/workspace-files-resource.test.ts +0 -261
  185. package/packages/contracts/src/__tests__/workspace-files-tree.test.ts +0 -147
  186. package/packages/contracts/src/__tests__/workspace-pane-creation.test.ts +0 -249
  187. package/packages/contracts/src/__tests__/workspace-promotion.test.ts +0 -94
  188. package/packages/contracts/src/__tests__/workspace-resource-identity.test.ts +0 -90
  189. package/packages/contracts/src/daemon-resource-request.test.ts +0 -192
  190. package/packages/contracts/src/native-operation-identity.test.ts +0 -23
  191. package/packages/contracts/src/workspace-admission.test.ts +0 -21
  192. package/packages/contracts/src/workspace-catalog-resource.test.ts +0 -146
  193. package/packages/core/src/agent-provisioning.test.ts +0 -42
  194. package/packages/core/src/application-shell-session.test.ts +0 -105
  195. package/packages/core/src/interaction-evidence.test.ts +0 -134
  196. package/packages/core/src/interaction-flow.test.ts +0 -66
  197. package/packages/core/src/interaction-receipts.test.ts +0 -671
  198. package/packages/core/src/navigator.test.ts +0 -34
  199. package/packages/core/src/optimistic-projection-conformance.test.ts +0 -75
  200. package/packages/core/src/optimistic-projection.test.ts +0 -118
  201. package/packages/core/src/performance-metrics.test.ts +0 -121
  202. package/packages/core/src/performance-qualification.test.ts +0 -283
  203. package/packages/core/src/saved-machines.test.ts +0 -80
  204. package/packages/core/src/terminal-compact-cold.test.ts +0 -87
  205. package/packages/core/src/terminal-conformance.test.ts +0 -48
  206. package/packages/core/src/terminal-delivery-cache-lifetime.test.ts +0 -167
  207. package/packages/core/src/terminal-delivery-encode-cooperative.test.ts +0 -140
  208. package/packages/core/src/terminal-delivery-representation-hash.test.ts +0 -77
  209. package/packages/core/src/terminal-delivery.test.ts +0 -1471
  210. package/packages/core/src/terminal-fnv64-wasm.test.ts +0 -61
  211. package/packages/core/src/terminal-replica-cold.test.ts +0 -31
  212. package/packages/core/src/terminal-replica-cooperative.test.ts +0 -170
  213. package/packages/core/src/terminal-replica-hash-cache.test.ts +0 -283
  214. package/packages/core/src/terminal-replica.test.ts +0 -347
  215. package/packages/core/src/workspace-selection.test.ts +0 -63
  216. package/packages/daemon/dist/__tests__/support.js +0 -33
  217. package/packages/daemon/dist/lib/__tests__/fixtures/workspace-state-writer.js +0 -58
  218. package/packages/daemon/dist/lib/__tests__/installed-recovery-fixture.js +0 -400
  219. package/packages/daemon/dist/terminal/__tests__/MockPtyAdapter.js +0 -182
  220. package/packages/daemon/dist/terminal/mirror/__tests__/scripted-channel.js +0 -98
  221. package/packages/daemon/dist/terminal/mirror/__tests__/simulated-channel.js +0 -156
  222. package/packages/daemon/src/tui/mirror/__snapshots__/activity-surface-renderer.test.tsx.snap +0 -42
  223. package/packages/daemon/src/tui/mirror/__snapshots__/changes-terminal-surface-renderer.test.tsx.snap +0 -267
  224. package/packages/daemon/src/tui/mirror/__snapshots__/home-files-surface-renderer.test.tsx.snap +0 -267
  225. package/packages/daemon/src/tui/mirror/__snapshots__/missions-surface-renderer.test.tsx.snap +0 -134
  226. package/packages/daemon/src/tui/mirror/__snapshots__/recipes-gallery-renderer.test.tsx.snap +0 -141
  227. package/packages/daemon/src/tui/mirror/__snapshots__/shell-chrome-renderer.test.tsx.snap +0 -134
  228. package/packages/daemon/src/tui/mirror/runtime/__snapshots__/application-shell-view-renderer.test.tsx.snap +0 -87
  229. package/packages/daemon/src/tui/mirror/workspace/__snapshots__/agent-terminal-canvas-renderer.test.tsx.snap +0 -348
  230. package/packages/daemon/src/tui/mirror/workspace/__snapshots__/application-shell-renderer.test.tsx.snap +0 -134
  231. package/packages/daemon/src/tui/mirror/workspace/__snapshots__/command-palette-surface-renderer.test.tsx.snap +0 -255
  232. package/packages/daemon/src/tui/mirror/workspace/__snapshots__/pane-frame-renderer.test.tsx.snap +0 -525
  233. package/packages/daemon/src/tui/mirror/workspace/__snapshots__/terminal-pane-header-polish-renderer.test.tsx.snap +0 -31
  234. package/packages/daemon/src/tui/mirror/workspace/__snapshots__/workbench-shell-renderer.test.tsx.snap +0 -134
  235. package/packages/daemon-client/src/application-shell-session.test.ts +0 -196
  236. package/packages/daemon-client/src/automation-client.test.ts +0 -214
  237. package/packages/daemon-client/src/bootstrap-coordinator.test.ts +0 -145
  238. package/packages/daemon-client/src/connection-supervisor.test.ts +0 -109
  239. package/packages/daemon-client/src/direct-application-shell-transport.test.ts +0 -941
  240. package/packages/daemon-client/src/first-latest-coordinator.test.ts +0 -175
  241. package/packages/daemon-client/src/fleet-dial-scheduler.test.ts +0 -114
  242. package/packages/daemon-client/src/fleet-environments.test.ts +0 -40
  243. package/packages/daemon-client/src/generation-bound-store-timers.test.ts +0 -74
  244. package/packages/daemon-client/src/owner-action-client.test.ts +0 -245
  245. package/packages/daemon-client/src/pane-stream-client.test.ts +0 -2841
  246. package/packages/daemon-client/src/pane-stream-clock-calibration.test.ts +0 -207
  247. package/packages/daemon-client/src/pane-stream-loopback-benchmark.test.ts +0 -51
  248. package/packages/daemon-client/src/push-resource-session.test.ts +0 -509
  249. package/packages/daemon-client/src/resource-replica.test.ts +0 -186
  250. package/packages/daemon-client/src/runtime-resource-ledger.test.ts +0 -18
  251. package/packages/daemon-client/src/scoped-tmux-server-transport.test.ts +0 -114
  252. package/packages/daemon-client/src/terminal-fast-lane.test.ts +0 -835
  253. package/packages/daemon-client/src/tmux-server-client.test.ts +0 -279
  254. package/packages/daemon-client/src/tmux-server-interaction-events.test.ts +0 -230
  255. package/packages/daemon-client/src/workspace-catalog-v2.test.ts +0 -109
  256. package/packages/daemon-client/src/workspace-client-boundaries.test.ts +0 -59
  257. package/packages/daemon-client/src/workspace-client-operations.test.ts +0 -96
  258. package/packages/daemon-client/src/workspace-client.test.ts +0 -2912
  259. package/packages/daemon-client/src/workspace-event-supervisor.test.ts +0 -1086
  260. package/packages/daemon-client/src/workspace-pane-client.test.ts +0 -80
  261. package/packages/presentation/src/presentation-contract.test.ts +0 -63
  262. package/packages/tmux-bridge/src/runner.test.ts +0 -614
  263. package/packages/tmux-bridge/src/targeting.test.ts +0 -107
@@ -1,61 +0,0 @@
1
- import { afterEach, expect, it, vi } from "vitest";
2
- import { createBufferedFnv64 } from "./terminal-fnv64-wasm.ts";
3
-
4
- const reference = (bytes: Uint8Array): string => {
5
- let state = 0xcbf29ce484222325n;
6
- for (const byte of bytes) state = BigInt.asUintN(64, (state ^ BigInt(byte)) * 0x100000001b3n);
7
- return state.toString(16).padStart(16, "0");
8
- };
9
-
10
- afterEach(() => {
11
- vi.unstubAllGlobals();
12
- vi.resetModules();
13
- });
14
-
15
- it("matches exact FNV across scratch boundaries, UTF-8 and every byte value", () => {
16
- for (const length of [0, 1, 4095, 4096, 4097, 16385]) {
17
- const bytes = Uint8Array.from({ length }, (_, index) => index % 256);
18
- const writer = createBufferedFnv64();
19
- expect(writer).not.toBeNull();
20
- writer!.bytes(bytes);
21
- expect(writer!.digest()).toBe(reference(bytes));
22
- expect(writer!.digest()).toBe(reference(bytes));
23
- }
24
- for (const text of ["é", "😀", "\ud800", "a\udc00z"]) {
25
- const writer = createBufferedFnv64()!;
26
- const bytes = new TextEncoder().encode(text);
27
- writer.ascii("prefix");
28
- writer.bytes(bytes);
29
- writer.boolean(true);
30
- expect(writer.digest()).toBe(reference(new TextEncoder().encode(`prefix${text}b1;`)));
31
- }
32
- });
33
-
34
- it("keeps concurrent partially buffered writers independent across async yields", async () => {
35
- await Promise.all(
36
- Array.from({ length: 16 }, async (_, index) => {
37
- const writer = createBufferedFnv64()!;
38
- const parts = Array.from({ length: 20 }, (_, part) => `${index}:${part}:`.repeat(150));
39
- for (const part of parts) {
40
- expect(writer.ascii(part)).toBe(part.length);
41
- await Promise.resolve();
42
- }
43
- expect(writer.digest()).toBe(reference(new TextEncoder().encode(parts.join(""))));
44
- }),
45
- );
46
- });
47
-
48
- it("returns the JS-fallback signal when WASM is unavailable or initialization is blocked", async () => {
49
- vi.stubGlobal("WebAssembly", undefined);
50
- vi.resetModules();
51
- expect((await import("./terminal-fnv64-wasm.ts")).createBufferedFnv64()).toBeNull();
52
- const blocked = vi.fn(function () {
53
- throw new Error("WASM blocked");
54
- });
55
- vi.stubGlobal("WebAssembly", { Module: blocked });
56
- vi.resetModules();
57
- const module = await import("./terminal-fnv64-wasm.ts");
58
- expect(module.createBufferedFnv64()).toBeNull();
59
- expect(module.createBufferedFnv64()).toBeNull();
60
- expect(blocked).toHaveBeenCalledTimes(1);
61
- });
@@ -1,31 +0,0 @@
1
- import { spawnSync } from "node:child_process";
2
- import { fileURLToPath } from "node:url";
3
- import { describe, expect, it } from "vitest";
4
-
5
- describe("terminal replica cold Bun process", () => {
6
- it("applies the first 132x41 last-column patch inside one frame", () => {
7
- const fixture = fileURLToPath(
8
- new URL("../test-support/terminal-replica-cold-process.ts", import.meta.url),
9
- );
10
- const result = spawnSync("bun", [fixture], { encoding: "utf8", timeout: 10_000 });
11
- expect(result.status, result.stderr).toBe(0);
12
- const measurement = JSON.parse(result.stdout.trim()) as {
13
- durationMs: number;
14
- profile: {
15
- reusedAuthenticatedFrameHash: boolean;
16
- phaseMicros: Record<string, number>;
17
- counts: Record<string, number>;
18
- };
19
- };
20
- expect(measurement.durationMs).toBeLessThanOrEqual(16.67);
21
- expect(measurement.profile.reusedAuthenticatedFrameHash).toBe(true);
22
- expect(measurement.profile.phaseMicros.updateHash).toBe(0);
23
- expect(measurement.profile.counts).toMatchObject({
24
- patchedRows: 1,
25
- validatedCells: 132,
26
- frozenCells: 132,
27
- comparedCells: 132,
28
- rowHashMisses: 1,
29
- });
30
- });
31
- });
@@ -1,170 +0,0 @@
1
- import { describe, expect, it } from "vitest";
2
- import type { CanonicalTerminalReplicaSeed } from "@tmux-ide/contracts";
3
- import {
4
- applyTerminalReplicaUpdate,
5
- applyTerminalReplicaUpdateCooperatively,
6
- blankTerminalReplicaSnapshot,
7
- hashTerminalReplicaSnapshot,
8
- terminalReplicaUpdateNeedsCooperativeReduction,
9
- } from "./terminal-replica.ts";
10
- import {
11
- decodeVerifiedCompactSemanticTerminalUpdate,
12
- encodeCompactSemanticTerminalUpdate,
13
- } from "./terminal-delivery.ts";
14
-
15
- function seed(cols = 128, rows = 64): CanonicalTerminalReplicaSeed {
16
- const snapshot = blankTerminalReplicaSnapshot(cols, rows);
17
- return {
18
- type: "terminal.seed",
19
- workspaceName: "workspace",
20
- semanticPaneId: "pane",
21
- generation: "00000000-0000-4000-8000-000000000001",
22
- incarnation: "00000000-0000-4000-8000-000000000001:0",
23
- revision: 0,
24
- cols,
25
- rows,
26
- snapshot,
27
- stateHash: hashTerminalReplicaSnapshot(snapshot),
28
- hashAlgorithm: "fnv1a64-v1",
29
- };
30
- }
31
- const yielding = { yieldControl: async () => {} };
32
- describe("cooperative terminal seed reduction", () => {
33
- it("matches ordinary state and exact frame hash for large seeds and replay", async () => {
34
- const update = seed();
35
- const sync = applyTerminalReplicaUpdate(null, update);
36
- const asyncResult = await applyTerminalReplicaUpdateCooperatively(null, update, yielding);
37
- expect(asyncResult).toEqual(sync);
38
- expect(Object.isFrozen(asyncResult.state!.snapshot!.grid[0]!.cells[0])).toBe(true);
39
- expect(
40
- await applyTerminalReplicaUpdateCooperatively(asyncResult.state, update, yielding),
41
- ).toEqual(applyTerminalReplicaUpdate(sync.state, update));
42
- });
43
- it.each([
44
- "hash",
45
- "dimensions",
46
- "cursor",
47
- "wide",
48
- "placement",
49
- "generation",
50
- "incarnation",
51
- "stale",
52
- ])("preserves %s rejection/order semantics", async (kind) => {
53
- const initial = seed();
54
- const current = applyTerminalReplicaUpdate(null, initial).state;
55
- const update = { ...structuredClone(initial) };
56
- update.revision = 1;
57
- if (kind === "hash") update.stateHash = "0000000000000000";
58
- if (kind === "dimensions") update.cols++;
59
- if (kind === "cursor") update.snapshot.cursor.x = update.cols;
60
- if (kind === "wide") update.snapshot.grid[0]!.cells[0]!.width = 2;
61
- if (kind === "placement")
62
- update.snapshot.placements.push({
63
- id: "p",
64
- kind: "test",
65
- row: 1000,
66
- column: 0,
67
- rows: 1,
68
- columns: 1,
69
- contentDigest: "x",
70
- });
71
- if (kind === "generation") update.generation = "00000000-0000-4000-8000-000000000002";
72
- if (kind === "incarnation") update.incarnation = "other";
73
- const baseline = kind === "stale" ? { ...current!, revision: 5 } : current;
74
- expect(await applyTerminalReplicaUpdateCooperatively(baseline, update, yielding)).toEqual(
75
- applyTerminalReplicaUpdate(baseline, update),
76
- );
77
- });
78
- it("preserves existing upstream-validated boundary rather than silently changing schemas", async () => {
79
- const update = { ...structuredClone(seed()) };
80
- update.snapshot.cursor.x = -1;
81
- update.stateHash = hashTerminalReplicaSnapshot(update.snapshot);
82
- expect(await applyTerminalReplicaUpdateCooperatively(null, update, yielding)).toEqual(
83
- applyTerminalReplicaUpdate(null, update),
84
- );
85
- });
86
- it("yields during cell copying before traversing the complete snapshot and aborts cleanly", async () => {
87
- const update = { ...structuredClone(seed()) };
88
- let reads = 0;
89
- for (const row of update.snapshot.grid)
90
- for (const cell of row.cells)
91
- Object.defineProperty(cell, "grapheme", {
92
- enumerable: true,
93
- get: () => {
94
- reads++;
95
- return "";
96
- },
97
- });
98
- update.stateHash = hashTerminalReplicaSnapshot(update.snapshot);
99
- reads = 0;
100
- const controller = new AbortController();
101
- const reason = new Error("owner retired");
102
- await expect(
103
- applyTerminalReplicaUpdateCooperatively(null, update, {
104
- signal: controller.signal,
105
- yieldControl: async () => {
106
- expect(reads).toBe(256);
107
- controller.abort(reason);
108
- },
109
- }),
110
- ).rejects.toBe(reason);
111
- expect(reads).toBe(256);
112
- });
113
- it("permits actual I/O turns while reducing wide rows and supports cancellation during hashing", async () => {
114
- const update = seed(4096, 2);
115
- let turns = 0;
116
- const result = await applyTerminalReplicaUpdateCooperatively(null, update, {
117
- yieldControl: () =>
118
- new Promise<void>((resolve) =>
119
- setImmediate(() => {
120
- turns++;
121
- resolve();
122
- }),
123
- ),
124
- });
125
- expect(result.status).toBe("applied");
126
- expect(turns).toBeGreaterThan(32);
127
- const controller = new AbortController();
128
- let slices = 0;
129
- await expect(
130
- applyTerminalReplicaUpdateCooperatively(null, update, {
131
- signal: controller.signal,
132
- yieldControl: async () => {
133
- if (++slices === 40) controller.abort();
134
- },
135
- }),
136
- ).rejects.toMatchObject({ name: "AbortError" });
137
- });
138
- it("keeps small seed/patch reduction synchronous within the wrapper", async () => {
139
- const update = seed(4, 2);
140
- let yields = 0;
141
- expect(terminalReplicaUpdateNeedsCooperativeReduction(update)).toBe(false);
142
- const result = await applyTerminalReplicaUpdateCooperatively(null, update, {
143
- yieldControl: async () => {
144
- yields++;
145
- },
146
- });
147
- expect(result).toEqual(applyTerminalReplicaUpdate(null, update));
148
- expect(yields).toBe(0);
149
- });
150
- it("preserves verified compact adoption and authenticated frame hash", async () => {
151
- const original = seed();
152
- const verified = decodeVerifiedCompactSemanticTerminalUpdate(
153
- encodeCompactSemanticTerminalUpdate({
154
- frame: "seed",
155
- revision: 0,
156
- snapshot: original.snapshot,
157
- }),
158
- null,
159
- original.stateHash,
160
- { grantReducerAdoption: true },
161
- );
162
- const update = { ...original, snapshot: verified.canonicalSnapshot! };
163
- const result = await applyTerminalReplicaUpdateCooperatively(null, update, {
164
- ...yielding,
165
- authenticatedFrameHash: "1234567890abcdef",
166
- });
167
- expect(result.state!.snapshot).toBe(verified.canonicalSnapshot);
168
- expect(result.state!.frameHash).toBe("1234567890abcdef");
169
- });
170
- });
@@ -1,283 +0,0 @@
1
- import { describe, expect, it, vi } from "vitest";
2
- import * as bufferedHash from "./terminal-fnv64-wasm.ts";
3
- import type { TerminalReplicaRow, TerminalReplicaSnapshot } from "@tmux-ide/contracts";
4
- import { blankTerminalReplicaSnapshot, hashTerminalReplicaSnapshot } from "./terminal-replica.ts";
5
- import {
6
- hashCanonicalTerminalValue,
7
- hashTerminalReplicaRowCached,
8
- hashTerminalReplicaRowRunsCooperatively,
9
- TerminalReplicaRunEncodingCache,
10
- } from "./terminal-replica-hash-cache.ts";
11
-
12
- const canonicalEncode = (value: unknown): string => {
13
- if (value === null) return "n;";
14
- if (typeof value === "boolean") return value ? "b1;" : "b0;";
15
- if (typeof value === "number") return `d${String(value).length}:${String(value)};`;
16
- if (typeof value === "string") {
17
- const length = new TextEncoder().encode(value).length;
18
- return `s${length}:${value};`;
19
- }
20
- if (Array.isArray(value)) return `a${value.length}:${value.map(canonicalEncode).join("")};`;
21
- const record = value as Record<string, unknown>;
22
- const keys = Object.keys(record).sort();
23
- return `o${keys.length}:${keys
24
- .map((key) => `${canonicalEncode(key)}${canonicalEncode(record[key])}`)
25
- .join("")};`;
26
- };
27
-
28
- const referenceHash = (value: unknown): string => {
29
- const bytes = new TextEncoder().encode(canonicalEncode(value));
30
- let hash = 0xcbf29ce484222325n;
31
- for (const byte of bytes) {
32
- hash ^= BigInt(byte);
33
- hash = BigInt.asUintN(64, hash * 0x100000001b3n);
34
- }
35
- return hash.toString(16).padStart(16, "0");
36
- };
37
-
38
- describe("terminal canonical hash cache", () => {
39
- it("accelerates substantial transactions without changing hashes or cooperative checkpoints", async () => {
40
- const cache = new TerminalReplicaRunEncodingCache();
41
- const factory = vi.spyOn(bufferedHash, "createBufferedFnv64");
42
- const cell = {
43
- ...blankTerminalReplicaSnapshot(1, 1).grid[0]!.cells[0]!,
44
- grapheme: "界e\u0301\ud800",
45
- };
46
- const row = { wrapped: true, cells: Array.from({ length: 1_024 }, () => cell) };
47
- const expected = hashTerminalReplicaRowCached(row);
48
- const decode = async (encodingCache: TerminalReplicaRunEncodingCache) => {
49
- let checkpoints = 0;
50
- const digest = await hashTerminalReplicaRowRunsCooperatively(
51
- true,
52
- row.cells.length,
53
- [[row.cells.length, cell]],
54
- async () => {
55
- checkpoints += 1;
56
- },
57
- 64,
58
- undefined,
59
- encodingCache,
60
- );
61
- expect(digest).toBe(expected);
62
- expect(checkpoints).toBe(16);
63
- };
64
- try {
65
- await decode(cache);
66
- expect(factory).not.toHaveBeenCalled();
67
- await Promise.all([decode(cache), decode(cache)]);
68
- expect(factory).toHaveBeenCalledTimes(2);
69
- expect(factory.mock.results.every((result) => result.value !== null)).toBe(true);
70
- // A separate client/delivery does not inherit another transaction's work.
71
- await decode(new TerminalReplicaRunEncodingCache());
72
- expect(factory).toHaveBeenCalledTimes(2);
73
- factory.mockReturnValue(null);
74
- await decode(cache);
75
- expect(factory).toHaveBeenCalledTimes(3);
76
- } finally {
77
- factory.mockRestore();
78
- }
79
- });
80
-
81
- it("preserves carries and wraparound over every indexed color and RGB byte extreme", () => {
82
- const colors = [
83
- { kind: "default" },
84
- ...Array.from({ length: 256 }, (_, index) => ({ kind: "indexed", index })),
85
- ...[0, 0xff, 0xff00, 0xff0000, 0xffffff].map((value) => ({ kind: "rgb", value })),
86
- ];
87
- const values = colors.map((foreground, index) => [
88
- String.fromCharCode(index % 128),
89
- index % 3,
90
- foreground,
91
- colors[colors.length - index - 1],
92
- index * 257,
93
- ]);
94
- expect(hashCanonicalTerminalValue([true, values])).toBe(referenceHash([true, values]));
95
- });
96
-
97
- it("preserves exact UTF-8 hashes across ASCII boundaries and malformed surrogates", () => {
98
- const values = [
99
- "",
100
- " ",
101
- Array.from({ length: 128 }, (_, index) => String.fromCharCode(index)).join(""),
102
- "a".repeat(1024),
103
- "\u007f\u0080",
104
- "ASCII界",
105
- "e\u0301",
106
- "😀",
107
- "\ud800",
108
- "\udc00",
109
- "a\ud800z",
110
- ];
111
- for (const value of values) {
112
- expect(hashCanonicalTerminalValue(value)).toBe(referenceHash(value));
113
- expect(hashCanonicalTerminalValue({ [value]: [value, "", "tail"] })).toBe(
114
- referenceHash({ [value]: [value, "", "tail"] }),
115
- );
116
- }
117
- });
118
-
119
- it("matches the prior canonical BigInt hash for nested UTF-8 values", () => {
120
- const corpus = [
121
- null,
122
- true,
123
- false,
124
- 0,
125
- -17,
126
- "ASCII",
127
- "界e\u0301\ud800",
128
- [null, true, 17, "wide界"],
129
- { z: [1, 2], a: { kind: "rgb", value: 0xff00aa } },
130
- ];
131
- for (const value of corpus)
132
- expect(hashCanonicalTerminalValue(value)).toBe(referenceHash(value));
133
- });
134
-
135
- it("matches the prior row hash for indexed, RGB, wide and combining cells", () => {
136
- const blank = blankTerminalReplicaSnapshot(3, 1);
137
- const row = Object.freeze({
138
- wrapped: true,
139
- cells: Object.freeze([
140
- Object.freeze({
141
- ...blank.grid[0]!.cells[0]!,
142
- grapheme: "界",
143
- width: 2 as const,
144
- foreground: Object.freeze({ kind: "indexed" as const, index: 75 }),
145
- }),
146
- Object.freeze({
147
- ...blank.grid[0]!.cells[1]!,
148
- grapheme: "",
149
- width: 0 as const,
150
- background: Object.freeze({ kind: "rgb" as const, value: 0x112233 }),
151
- }),
152
- Object.freeze({ ...blank.grid[0]!.cells[2]!, grapheme: "e\u0301", attributes: 7 }),
153
- ]),
154
- }) as unknown as TerminalReplicaRow;
155
- const projected = [
156
- row.wrapped,
157
- row.cells.map((cell) => [
158
- cell.grapheme,
159
- cell.width,
160
- cell.foreground,
161
- cell.background,
162
- cell.attributes,
163
- ]),
164
- ];
165
- expect(hashTerminalReplicaRowCached(row)).toBe(referenceHash(projected));
166
- expect(hashTerminalReplicaRowCached(row)).toBe(referenceHash(projected));
167
- });
168
-
169
- it("replays one UTF-8 encoding per compact run with exhaustive row-hash parity", async () => {
170
- const blank = blankTerminalReplicaSnapshot(5, 1);
171
- const cells = [
172
- Object.freeze({
173
- ...blank.grid[0]!.cells[0]!,
174
- grapheme: "界",
175
- width: 2 as const,
176
- foreground: Object.freeze({ kind: "indexed" as const, index: 75 }),
177
- }),
178
- Object.freeze({
179
- ...blank.grid[0]!.cells[0]!,
180
- grapheme: "",
181
- width: 0 as const,
182
- background: Object.freeze({ kind: "rgb" as const, value: 0x112233 }),
183
- }),
184
- Object.freeze({
185
- ...blank.grid[0]!.cells[0]!,
186
- grapheme: "e\u0301",
187
- attributes: 0xff,
188
- }),
189
- ];
190
- const row = Object.freeze({
191
- wrapped: true,
192
- cells: Object.freeze([cells[0]!, cells[1]!, cells[2]!, cells[2]!, cells[2]!]),
193
- }) as unknown as TerminalReplicaRow;
194
- const encodedRuns: number[] = [];
195
- const digest = await hashTerminalReplicaRowRunsCooperatively(
196
- true,
197
- 5,
198
- [
199
- [1, cells[0]!],
200
- [1, cells[1]!],
201
- [3, cells[2]!],
202
- ],
203
- async () => {},
204
- 2,
205
- (bytes) => encodedRuns.push(bytes),
206
- );
207
- expect(digest).toBe(hashTerminalReplicaRowCached(row));
208
- expect(encodedRuns).toEqual([3, 0, 3]);
209
- });
210
-
211
- it("never caches a shallow-frozen snapshot whose nested canonical state remains mutable", () => {
212
- const blank = blankTerminalReplicaSnapshot(2, 1);
213
- const cursor = { ...blank.cursor };
214
- const modes = { ...blank.modes };
215
- const placements = [
216
- {
217
- id: "placement-a",
218
- kind: "image",
219
- row: 0,
220
- column: 0,
221
- columns: 1,
222
- rows: 1,
223
- contentDigest: "digest-a",
224
- },
225
- ];
226
- const history: TerminalReplicaRow[] = [];
227
- const snapshot = Object.freeze({
228
- ...blank,
229
- grid: [...blank.grid],
230
- history,
231
- cursor,
232
- modes,
233
- placements,
234
- }) as unknown as TerminalReplicaSnapshot;
235
- const initial = hashTerminalReplicaSnapshot(snapshot);
236
- cursor.x = 1;
237
- const cursorChanged = hashTerminalReplicaSnapshot(snapshot);
238
- expect(cursorChanged).not.toBe(initial);
239
- modes.insert = true;
240
- const modesChanged = hashTerminalReplicaSnapshot(snapshot);
241
- expect(modesChanged).not.toBe(cursorChanged);
242
- placements[0]!.contentDigest = "digest-b";
243
- const placementChanged = hashTerminalReplicaSnapshot(snapshot);
244
- expect(placementChanged).not.toBe(modesChanged);
245
- history.push(blank.grid[0]!);
246
- expect(hashTerminalReplicaSnapshot(snapshot)).not.toBe(placementChanged);
247
- });
248
-
249
- it("never caches frozen row arrays or rows with mutable nested cells and colors", () => {
250
- const blank = blankTerminalReplicaSnapshot(1, 1);
251
- const foreground = { kind: "rgb" as const, value: 0x112233 };
252
- const background = { kind: "rgb" as const, value: 0x445566 };
253
- const cell = {
254
- ...blank.grid[0]!.cells[0]!,
255
- foreground,
256
- background,
257
- };
258
- const row = Object.freeze({ wrapped: false, cells: Object.freeze([cell]) });
259
- const snapshot = Object.freeze({
260
- ...blank,
261
- grid: Object.freeze([row]),
262
- }) as unknown as TerminalReplicaSnapshot;
263
- const initial = hashTerminalReplicaSnapshot(snapshot);
264
- cell.grapheme = "x";
265
- const graphemeChanged = hashTerminalReplicaSnapshot(snapshot);
266
- expect(graphemeChanged).not.toBe(initial);
267
- cell.attributes = 7;
268
- const styleChanged = hashTerminalReplicaSnapshot(snapshot);
269
- expect(styleChanged).not.toBe(graphemeChanged);
270
- foreground.value = 0xaabbcc;
271
- const colorChanged = hashTerminalReplicaSnapshot(snapshot);
272
- expect(colorChanged).not.toBe(styleChanged);
273
-
274
- const mutableRow = { wrapped: false, cells: blank.grid[0]!.cells };
275
- const mutableRowSnapshot = Object.freeze({
276
- ...blank,
277
- grid: Object.freeze([mutableRow]),
278
- }) as unknown as TerminalReplicaSnapshot;
279
- const rowInitial = hashTerminalReplicaSnapshot(mutableRowSnapshot);
280
- mutableRow.wrapped = true;
281
- expect(hashTerminalReplicaSnapshot(mutableRowSnapshot)).not.toBe(rowInitial);
282
- });
283
- });