tmux-ide 2.9.0-beta.21 → 2.9.0-beta.26
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/bin/cli.js +46791 -43589
- package/package.json +2 -2
- package/packages/contracts/src/__tests__/daemon-wire.test.ts +2 -2
- package/packages/contracts/src/__tests__/fixtures/daemon-wire-v3.json +35 -0
- package/packages/contracts/src/__tests__/issue-error.test.ts +1 -1
- package/packages/contracts/src/__tests__/multiplexer-verbs.test.ts +3 -1
- package/packages/contracts/src/__tests__/pane-stream.test.ts +17 -5
- package/packages/contracts/src/__tests__/tmux-server-scope.test.ts +166 -0
- package/packages/contracts/src/__tests__/window-links.test.ts +243 -0
- package/packages/contracts/src/actions-contract.ts +12 -0
- package/packages/contracts/src/daemon-resource-request.test.ts +1 -1
- package/packages/contracts/src/daemon-wire.ts +10 -5
- package/packages/contracts/src/fleet-client-state.ts +3 -0
- package/packages/contracts/src/fleet-lifecycle.ts +5 -0
- package/packages/contracts/src/index.ts +2 -0
- package/packages/contracts/src/interaction-receipts.ts +39 -0
- package/packages/contracts/src/issue-error.ts +1 -1
- package/packages/contracts/src/multiplexer-verbs.ts +25 -1
- package/packages/contracts/src/pane-stream.ts +51 -8
- package/packages/contracts/src/tmux-server-scope.ts +172 -0
- package/packages/contracts/src/window-links.ts +76 -0
- package/packages/contracts/src/workspace-multiplexer.ts +54 -0
- package/packages/core/src/interaction-receipts.ts +4 -0
- package/packages/daemon/dist/command-center/actions/command-definitions.js +6 -0
- package/packages/daemon/dist/command-center/actions/handlers/workspace-multiplexer.js +2 -0
- package/packages/daemon/dist/command-center/actions/registry.js +13 -1
- package/packages/daemon/dist/command-center/discovery.js +2 -9
- package/packages/daemon/dist/command-center/server.js +21 -1
- package/packages/daemon/dist/command-center/tmux-server-native-backing.js +37 -0
- package/packages/daemon/dist/command-center/tmux-servers.js +351 -0
- package/packages/daemon/dist/lib/canonical-daemon-bootstrap.js +64 -8
- package/packages/daemon/dist/lib/canonical-daemon.js +5 -2
- package/packages/daemon/dist/lib/daemon-embed.js +198 -30
- package/packages/daemon/dist/lib/embedded-tmux-server-owners.js +147 -0
- package/packages/daemon/dist/lib/fleet-lifecycle-authority.js +31 -11
- package/packages/daemon/dist/lib/headless-daemon.js +10 -1
- package/packages/daemon/dist/lib/runtime-namespace.js +17 -3
- package/packages/daemon/dist/lib/tmux-client-execution.js +59 -0
- package/packages/daemon/dist/lib/tmux-named-socket-fence.js +4 -0
- package/packages/daemon/dist/lib/tmux-server-generation-runner.js +62 -0
- package/packages/daemon/dist/lib/tmux-server-owner.js +285 -0
- package/packages/daemon/dist/lib/tmux-server-owners.js +192 -0
- package/packages/daemon/dist/lib/tmux-server-proof.js +82 -0
- package/packages/daemon/dist/lib/tmux-server-registration.js +85 -0
- package/packages/daemon/dist/lib/tmux-server-session-create.js +43 -0
- package/packages/daemon/dist/lib/tmux-server-session-open.js +101 -0
- package/packages/daemon/dist/lib/tmux-servers-cli.js +134 -0
- package/packages/daemon/dist/lib/tmux-session-mutation-fence.js +55 -0
- package/packages/daemon/dist/lib/tmux-window-link-guard.js +88 -0
- package/packages/daemon/dist/lib/workspace-config-loader.js +3 -0
- package/packages/daemon/dist/lib/workspace-multiplexer-verbs.js +82 -1
- package/packages/daemon/dist/lib/workspace-pane-creation.js +13 -57
- package/packages/daemon/dist/lib/workspace-promotion.js +91 -12
- package/packages/daemon/dist/lib/workspace-registry.js +4 -0
- package/packages/daemon/dist/server/pane-stream-upgrade.js +20 -6
- package/packages/daemon/dist/terminal/attachments/native-runtime.js +61 -17
- package/packages/daemon/dist/terminal/mirror/__tests__/scripted-channel.js +9 -1
- package/packages/daemon/dist/terminal/mirror/__tests__/simulated-channel.js +11 -2
- package/packages/daemon/dist/terminal/mirror/control-channel.js +65 -6
- package/packages/daemon/dist/terminal/mirror/mirror-service.js +44 -0
- package/packages/daemon/dist/terminal/mirror/session-channel.js +210 -50
- package/packages/daemon/dist/terminal/mirror/window-link-authority.js +160 -0
- package/packages/daemon/dist/terminal/pane-stream/lease-manager.js +3 -3
- package/packages/daemon/dist/terminal/pane-stream/pane-stream-websocket.js +40 -6
- package/packages/daemon/dist/terminal/protocol/live-session-identity.js +9 -0
- package/packages/daemon/dist/terminal/protocol/native-backing-client.js +2 -1
- package/packages/daemon/dist/terminal/session-runtime/interaction-receipt-facts.js +9 -0
- package/packages/daemon/dist/terminal/session-runtime/registry.js +6 -0
- package/packages/daemon/dist/terminal/session-runtime/semantic-mutation-executor.js +1 -1
- package/packages/daemon/dist/terminal/session-runtime/semantic-mutation-resource-changes.js +1 -0
- package/packages/daemon/dist/tui/mirror/application-shell-daemon-connection.js +7 -2
- package/packages/daemon/dist/tui/mirror/application-shell-server-connection.js +114 -0
- package/packages/daemon/dist/tui/mirror/menu-model.js +1 -1
- package/packages/daemon/dist/tui/mirror/open-tui-verified-routing.js +34 -4
- package/packages/daemon/dist/tui/mirror/open-tui-workspace-runtime-port.js +29 -8
- package/packages/daemon/dist/tui/mirror/runtime/application-guided-tour-integration.jsx +119 -0
- package/packages/daemon/dist/tui/mirror/runtime/application-guided-tour-owner.js +132 -0
- package/packages/daemon/dist/tui/mirror/runtime/application-home-agent-roster.jsx +21 -9
- package/packages/daemon/dist/tui/mirror/runtime/application-home-agent-transport.js +63 -1
- package/packages/daemon/dist/tui/mirror/runtime/application-home-agents-owner.js +8 -2
- package/packages/daemon/dist/tui/mirror/runtime/application-home-agents.js +3 -1
- package/packages/daemon/dist/tui/mirror/runtime/application-home-catalog-owner.js +11 -5
- package/packages/daemon/dist/tui/mirror/runtime/application-home-catalog.js +140 -75
- package/packages/daemon/dist/tui/mirror/runtime/application-home-experience.js +40 -0
- package/packages/daemon/dist/tui/mirror/runtime/application-home-fleet.js +132 -0
- package/packages/daemon/dist/tui/mirror/runtime/application-machine-agents.js +9 -0
- package/packages/daemon/dist/tui/mirror/runtime/application-machine-catalog.js +12 -2
- package/packages/daemon/dist/tui/mirror/runtime/application-machine-navigation.js +211 -31
- package/packages/daemon/dist/tui/mirror/runtime/application-machine-sidebar.jsx +91 -37
- package/packages/daemon/dist/tui/mirror/runtime/application-performance-log.js +20 -7
- package/packages/daemon/dist/tui/mirror/runtime/application-root-configuration.js +9 -3
- package/packages/daemon/dist/tui/mirror/runtime/application-route-connection.js +95 -2
- package/packages/daemon/dist/tui/mirror/runtime/application-shell-home.jsx +6 -2
- package/packages/daemon/dist/tui/mirror/runtime/application-terminal-interaction-controller.js +158 -2
- package/packages/daemon/dist/tui/mirror/runtime/application-terminal-workspace-policy.js +43 -0
- package/packages/daemon/dist/tui/mirror/runtime/application-terminal-workspace.jsx +78 -25
- package/packages/daemon/dist/tui/mirror/runtime/application-theme-repaint.js +9 -0
- package/packages/daemon/dist/tui/mirror/runtime/fleet-lifecycle-client.js +44 -1
- package/packages/daemon/dist/tui/mirror/runtime/guided-tour-coach.jsx +54 -0
- package/packages/daemon/dist/tui/mirror/runtime/guided-tour-storage.js +67 -0
- package/packages/daemon/dist/tui/mirror/runtime/guided-tour.js +113 -0
- package/packages/daemon/dist/tui/mirror/runtime/open-tui-generation-host.js +1 -1
- package/packages/daemon/dist/tui/mirror/runtime/resize-terminal-pane.js +4 -0
- package/packages/daemon/dist/tui/mirror/runtime/select-terminal-pane.js +2 -1
- package/packages/daemon/dist/tui/mirror/runtime/semantic-shell-viewport-resize.js +12 -4
- package/packages/daemon/dist/tui/mirror/runtime/terminal-pane-input-router.js +6 -3
- package/packages/daemon/dist/tui/mirror/workspace/application-command-description.js +11 -2
- package/packages/daemon/dist/tui/mirror/workspace/terminal-window-strip.jsx +2 -1
- package/packages/daemon/src/command-center/actions/command-definitions.ts +6 -0
- package/packages/daemon/src/command-center/actions/errors.ts +4 -0
- package/packages/daemon/src/command-center/actions/handlers/workspace-multiplexer.ts +2 -0
- package/packages/daemon/src/command-center/actions/registry.ts +14 -0
- package/packages/daemon/src/command-center/discovery.ts +2 -10
- package/packages/daemon/src/command-center/server.ts +29 -1
- package/packages/daemon/src/command-center/tmux-server-native-backing.ts +49 -0
- package/packages/daemon/src/command-center/tmux-servers.ts +479 -0
- package/packages/daemon/src/lib/canonical-daemon-bootstrap.ts +111 -4
- package/packages/daemon/src/lib/canonical-daemon.ts +15 -3
- package/packages/daemon/src/lib/daemon-embed.ts +241 -28
- package/packages/daemon/src/lib/embedded-tmux-server-owners.ts +190 -0
- package/packages/daemon/src/lib/fleet-lifecycle-authority.ts +33 -9
- package/packages/daemon/src/lib/headless-daemon.ts +18 -1
- package/packages/daemon/src/lib/runtime-namespace.ts +24 -3
- package/packages/daemon/src/lib/tmux-client-execution.ts +56 -0
- package/packages/daemon/src/lib/tmux-named-socket-fence.ts +5 -0
- package/packages/daemon/src/lib/tmux-server-generation-runner.ts +81 -0
- package/packages/daemon/src/lib/tmux-server-owner.ts +336 -0
- package/packages/daemon/src/lib/tmux-server-owners.ts +228 -0
- package/packages/daemon/src/lib/tmux-server-proof.ts +95 -0
- package/packages/daemon/src/lib/tmux-server-registration.ts +105 -0
- package/packages/daemon/src/lib/tmux-server-session-create.ts +52 -0
- package/packages/daemon/src/lib/tmux-server-session-open.ts +106 -0
- package/packages/daemon/src/lib/tmux-servers-cli.ts +186 -0
- package/packages/daemon/src/lib/tmux-session-mutation-fence.ts +62 -0
- package/packages/daemon/src/lib/tmux-window-link-guard.ts +112 -0
- package/packages/daemon/src/lib/workspace-config-loader.ts +3 -0
- package/packages/daemon/src/lib/workspace-multiplexer-verbs.ts +121 -1
- package/packages/daemon/src/lib/workspace-pane-creation.ts +16 -55
- package/packages/daemon/src/lib/workspace-promotion.ts +98 -12
- package/packages/daemon/src/lib/workspace-registry.ts +5 -0
- package/packages/daemon/src/server/pane-stream-upgrade.ts +25 -5
- package/packages/daemon/src/terminal/attachments/native-runtime.ts +70 -16
- package/packages/daemon/src/terminal/mirror/control-channel.ts +64 -7
- package/packages/daemon/src/terminal/mirror/events.ts +2 -0
- package/packages/daemon/src/terminal/mirror/mirror-service.ts +56 -0
- package/packages/daemon/src/terminal/mirror/session-channel.ts +245 -50
- package/packages/daemon/src/terminal/mirror/window-link-authority.ts +203 -0
- package/packages/daemon/src/terminal/pane-stream/lease-manager.ts +3 -3
- package/packages/daemon/src/terminal/pane-stream/pane-stream-websocket.ts +50 -6
- package/packages/daemon/src/terminal/protocol/live-session-identity.ts +14 -0
- package/packages/daemon/src/terminal/protocol/native-backing-client.ts +4 -1
- package/packages/daemon/src/terminal/session-runtime/interaction-receipt-facts.ts +9 -0
- package/packages/daemon/src/terminal/session-runtime/registry.ts +9 -0
- package/packages/daemon/src/terminal/session-runtime/semantic-mutation-executor.ts +2 -2
- package/packages/daemon/src/terminal/session-runtime/semantic-mutation-resource-changes.ts +1 -0
- package/packages/daemon/src/tui/mirror/application-shell-daemon-connection.ts +28 -2
- package/packages/daemon/src/tui/mirror/application-shell-server-connection.ts +154 -0
- package/packages/daemon/src/tui/mirror/menu-model.ts +1 -1
- package/packages/daemon/src/tui/mirror/open-tui-verified-routing.ts +41 -3
- package/packages/daemon/src/tui/mirror/open-tui-workspace-runtime-port.ts +47 -6
- package/packages/daemon/src/tui/mirror/runtime/application-entry.ts +2 -1
- package/packages/daemon/src/tui/mirror/runtime/application-fleet-session-actions.tsx +10 -4
- package/packages/daemon/src/tui/mirror/runtime/application-fleet-tabs.ts +2 -0
- package/packages/daemon/src/tui/mirror/runtime/application-guided-tour-integration.tsx +199 -0
- package/packages/daemon/src/tui/mirror/runtime/application-guided-tour-owner.ts +162 -0
- package/packages/daemon/src/tui/mirror/runtime/application-home-agent-roster.tsx +36 -10
- package/packages/daemon/src/tui/mirror/runtime/application-home-agent-transport.ts +69 -0
- package/packages/daemon/src/tui/mirror/runtime/application-home-agents-owner.ts +12 -2
- package/packages/daemon/src/tui/mirror/runtime/application-home-agents.ts +13 -2
- package/packages/daemon/src/tui/mirror/runtime/application-home-catalog-owner.ts +13 -3
- package/packages/daemon/src/tui/mirror/runtime/application-home-catalog.ts +172 -100
- package/packages/daemon/src/tui/mirror/runtime/application-home-experience.ts +59 -0
- package/packages/daemon/src/tui/mirror/runtime/application-home-fleet.ts +175 -0
- package/packages/daemon/src/tui/mirror/runtime/application-machine-agents.ts +9 -1
- package/packages/daemon/src/tui/mirror/runtime/application-machine-catalog.ts +19 -7
- package/packages/daemon/src/tui/mirror/runtime/application-machine-navigation.ts +285 -36
- package/packages/daemon/src/tui/mirror/runtime/application-machine-overlays.tsx +1 -1
- package/packages/daemon/src/tui/mirror/runtime/application-machine-sidebar.tsx +124 -40
- package/packages/daemon/src/tui/mirror/runtime/application-palette-preview.tsx +3 -0
- package/packages/daemon/src/tui/mirror/runtime/application-performance-log.ts +18 -6
- package/packages/daemon/src/tui/mirror/runtime/application-root-configuration.ts +12 -3
- package/packages/daemon/src/tui/mirror/runtime/application-root-v2.tsx +40 -40
- package/packages/daemon/src/tui/mirror/runtime/application-route-connection.ts +93 -1
- package/packages/daemon/src/tui/mirror/runtime/application-shell-catalog.tsx +4 -0
- package/packages/daemon/src/tui/mirror/runtime/application-shell-home.tsx +20 -1
- package/packages/daemon/src/tui/mirror/runtime/application-shell-view.tsx +10 -0
- package/packages/daemon/src/tui/mirror/runtime/application-terminal-interaction-controller.ts +177 -2
- package/packages/daemon/src/tui/mirror/runtime/application-terminal-workspace-policy.ts +62 -0
- package/packages/daemon/src/tui/mirror/runtime/application-terminal-workspace.tsx +87 -30
- package/packages/daemon/src/tui/mirror/runtime/application-theme-repaint.ts +19 -0
- package/packages/daemon/src/tui/mirror/runtime/fleet-lifecycle-client.ts +55 -0
- package/packages/daemon/src/tui/mirror/runtime/guided-tour-coach.tsx +118 -0
- package/packages/daemon/src/tui/mirror/runtime/guided-tour-storage.ts +72 -0
- package/packages/daemon/src/tui/mirror/runtime/guided-tour.ts +147 -0
- package/packages/daemon/src/tui/mirror/runtime/open-tui-generation-host.ts +1 -1
- package/packages/daemon/src/tui/mirror/runtime/resize-terminal-pane.ts +3 -0
- package/packages/daemon/src/tui/mirror/runtime/select-terminal-pane.ts +3 -0
- package/packages/daemon/src/tui/mirror/runtime/semantic-shell-viewport-resize.ts +11 -4
- package/packages/daemon/src/tui/mirror/runtime/terminal-pane-input-router.ts +15 -4
- package/packages/daemon/src/tui/mirror/workspace/application-command-description.ts +13 -2
- package/packages/daemon/src/tui/mirror/workspace/terminal-window-strip.tsx +5 -1
- package/packages/daemon-client/package.json +3 -1
- package/packages/daemon-client/src/index.ts +2 -0
- package/packages/daemon-client/src/pane-stream-client.test.ts +108 -38
- package/packages/daemon-client/src/pane-stream-client.ts +26 -0
- package/packages/daemon-client/src/scoped-tmux-server-transport.test.ts +114 -0
- package/packages/daemon-client/src/scoped-tmux-server-transport.ts +385 -0
- package/packages/daemon-client/src/tmux-server-client.test.ts +279 -0
- package/packages/daemon-client/src/tmux-server-client.ts +287 -0
|
@@ -41,7 +41,7 @@ export function createSemanticShellViewportResizeOwner(
|
|
|
41
41
|
type ScopedTarget = Readonly<{ cols: number; rows: number; semanticWindowId?: string }>;
|
|
42
42
|
let desired: Readonly<{ identity: ResizeIdentity; targets: readonly ScopedTarget[] }> | null =
|
|
43
43
|
null;
|
|
44
|
-
let scopedFlight =
|
|
44
|
+
let scopedFlight: object | null = null;
|
|
45
45
|
let scopedEpoch = 0;
|
|
46
46
|
let authorityClient: OpenTuiGenerationHostSnapshot["authorityClient"] = null;
|
|
47
47
|
let stopAuthority: (() => void) | null = null;
|
|
@@ -53,7 +53,8 @@ export function createSemanticShellViewportResizeOwner(
|
|
|
53
53
|
const targetSize = (target: ScopedTarget) => `${target.cols}x${target.rows}`;
|
|
54
54
|
const drain = async (): Promise<void> => {
|
|
55
55
|
if (scopedFlight || disposed || authoritySuspended) return;
|
|
56
|
-
|
|
56
|
+
const flight = {};
|
|
57
|
+
scopedFlight = flight;
|
|
57
58
|
try {
|
|
58
59
|
while (desired && !disposed && !authoritySuspended) {
|
|
59
60
|
const owner = desired;
|
|
@@ -70,7 +71,7 @@ export function createSemanticShellViewportResizeOwner(
|
|
|
70
71
|
.resize(target)
|
|
71
72
|
.catch(() => ({ status: "failed" as const }));
|
|
72
73
|
if (disposed || !desired) break;
|
|
73
|
-
if (epoch !== scopedEpoch)
|
|
74
|
+
if (epoch !== scopedEpoch) break;
|
|
74
75
|
const stillDesired = desired.targets.some(
|
|
75
76
|
(entry) =>
|
|
76
77
|
targetKey(entry) === targetKey(target) && targetSize(entry) === targetSize(target),
|
|
@@ -85,7 +86,7 @@ export function createSemanticShellViewportResizeOwner(
|
|
|
85
86
|
scopedApplied.set(targetKey(target), targetSize(target));
|
|
86
87
|
}
|
|
87
88
|
} finally {
|
|
88
|
-
scopedFlight =
|
|
89
|
+
if (scopedFlight === flight) scopedFlight = null;
|
|
89
90
|
}
|
|
90
91
|
};
|
|
91
92
|
const sameAuthority = (left: ResizeIdentity, right: ResizeIdentity): boolean =>
|
|
@@ -122,6 +123,7 @@ export function createSemanticShellViewportResizeOwner(
|
|
|
122
123
|
pending = null;
|
|
123
124
|
desired = null;
|
|
124
125
|
scopedEpoch += 1;
|
|
126
|
+
scopedFlight = null;
|
|
125
127
|
scopedApplied.clear();
|
|
126
128
|
return;
|
|
127
129
|
}
|
|
@@ -150,6 +152,7 @@ export function createSemanticShellViewportResizeOwner(
|
|
|
150
152
|
pending = null;
|
|
151
153
|
scopedApplied.clear();
|
|
152
154
|
scopedEpoch += 1;
|
|
155
|
+
scopedFlight = null;
|
|
153
156
|
if (!authoritySuspended) retry?.();
|
|
154
157
|
}) ?? null;
|
|
155
158
|
}
|
|
@@ -174,6 +177,8 @@ export function createSemanticShellViewportResizeOwner(
|
|
|
174
177
|
pending = null;
|
|
175
178
|
if (!desired || !sameAuthority(desired.identity, target)) {
|
|
176
179
|
scopedEpoch += 1;
|
|
180
|
+
// A retired lane must not hold a replacement lane behind its receipt.
|
|
181
|
+
scopedFlight = null;
|
|
177
182
|
scopedApplied.clear();
|
|
178
183
|
}
|
|
179
184
|
const retainedWindows = new Set(["", ...windows.map((window) => window.semanticWindowId!)]);
|
|
@@ -199,6 +204,7 @@ export function createSemanticShellViewportResizeOwner(
|
|
|
199
204
|
if (desired) {
|
|
200
205
|
desired = null;
|
|
201
206
|
scopedEpoch += 1;
|
|
207
|
+
scopedFlight = null;
|
|
202
208
|
scopedApplied.clear();
|
|
203
209
|
applied = null;
|
|
204
210
|
pending = null;
|
|
@@ -228,6 +234,7 @@ export function createSemanticShellViewportResizeOwner(
|
|
|
228
234
|
stopAuthority = null;
|
|
229
235
|
authorityClient = null;
|
|
230
236
|
desired = null;
|
|
237
|
+
scopedFlight = null;
|
|
231
238
|
scopedApplied.clear();
|
|
232
239
|
applied = null;
|
|
233
240
|
pending = null;
|
|
@@ -44,14 +44,25 @@ export class TerminalPaneInputRouter<Input> {
|
|
|
44
44
|
if (this.#pending?.selected === true) this.#pending = null;
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
-
selectPane(
|
|
48
|
-
|
|
49
|
-
|
|
47
|
+
selectPane(
|
|
48
|
+
paneId: string,
|
|
49
|
+
options: {
|
|
50
|
+
readonly presentOptimistically?: boolean;
|
|
51
|
+
readonly selection?: () => Promise<boolean>;
|
|
52
|
+
} = {},
|
|
53
|
+
): void {
|
|
54
|
+
if (!options.selection && this.#pending?.paneId === paneId) return;
|
|
55
|
+
if (
|
|
56
|
+
!options.selection &&
|
|
57
|
+
this.#pending === null &&
|
|
58
|
+
this.#canonicalPane === paneId &&
|
|
59
|
+
this.#focusedPane === paneId
|
|
60
|
+
)
|
|
50
61
|
return;
|
|
51
62
|
const token = ++this.#selectionToken;
|
|
52
63
|
const presentOptimistically = options.presentOptimistically !== false;
|
|
53
64
|
if (presentOptimistically) this.#setFocusedPane(paneId);
|
|
54
|
-
const settled = this.#options.select(paneId);
|
|
65
|
+
const settled = options.selection ? options.selection() : this.#options.select(paneId);
|
|
55
66
|
this.#pending = { token, paneId, presentOptimistically, settled, selected: null };
|
|
56
67
|
void settled.then((selected) => {
|
|
57
68
|
if (this.#pending?.token !== token) return;
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
import type { TmuxServerScope } from "@tmux-ide/contracts";
|
|
1
2
|
import { fuzzyTermsMatch as commandSearchMatch } from "../../team/fuzzy.ts";
|
|
2
3
|
export { fuzzyTermsMatch as commandSearchMatch } from "../../team/fuzzy.ts";
|
|
3
4
|
import { PANE_ACTION_MENU_ITEMS } from "./pane-action-menu-model.ts";
|
|
4
5
|
export interface FleetPaletteTarget {
|
|
6
|
+
readonly server?: TmuxServerScope;
|
|
5
7
|
readonly machineId: string;
|
|
6
8
|
readonly liveSessionId: string;
|
|
7
9
|
readonly hostLabel: string;
|
|
@@ -51,8 +53,14 @@ export type ApplicationPaletteCommand =
|
|
|
51
53
|
export function applicationCommandDescription(command: ApplicationPaletteCommand) {
|
|
52
54
|
if (typeof command === "object" && command.kind === "open-machine")
|
|
53
55
|
return {
|
|
54
|
-
id: JSON.stringify([
|
|
55
|
-
|
|
56
|
+
id: JSON.stringify([
|
|
57
|
+
command.kind,
|
|
58
|
+
command.fleet.machineId,
|
|
59
|
+
...(command.fleet.server
|
|
60
|
+
? [command.fleet.server.serverId, command.fleet.server.generation]
|
|
61
|
+
: []),
|
|
62
|
+
]),
|
|
63
|
+
label: `${command.fleet.server ? "Server" : "Machine"} · ${command.label}`,
|
|
56
64
|
detail: command.fleet.disabled ? "Unavailable" : "Browse sessions or create on this host",
|
|
57
65
|
};
|
|
58
66
|
if (typeof command === "object") {
|
|
@@ -63,6 +71,9 @@ export function applicationCommandDescription(command: ApplicationPaletteCommand
|
|
|
63
71
|
? [
|
|
64
72
|
command.kind,
|
|
65
73
|
command.fleet.machineId,
|
|
74
|
+
...(command.fleet.server
|
|
75
|
+
? [command.fleet.server.serverId, command.fleet.server.generation]
|
|
76
|
+
: []),
|
|
66
77
|
command.fleet.liveSessionId,
|
|
67
78
|
session ? null : command.paneId,
|
|
68
79
|
]
|
|
@@ -14,6 +14,8 @@ import {
|
|
|
14
14
|
} from "../ui/index.ts";
|
|
15
15
|
|
|
16
16
|
export interface TerminalWindowTab {
|
|
17
|
+
linkId?: string;
|
|
18
|
+
disabled?: boolean;
|
|
17
19
|
index: number;
|
|
18
20
|
name: string;
|
|
19
21
|
active: boolean;
|
|
@@ -414,10 +416,12 @@ function agentStatus(status: string | undefined): AgentBadgeStatus | undefined {
|
|
|
414
416
|
*/
|
|
415
417
|
export function TerminalWindowStrip(props: TerminalWindowStripProps) {
|
|
416
418
|
const tabs = () => (typeof props.tabs === "function" ? props.tabs() : props.tabs);
|
|
417
|
-
const tabId = (tab: TerminalWindowTab) =>
|
|
419
|
+
const tabId = (tab: TerminalWindowTab) =>
|
|
420
|
+
tab.linkId ?? tab.semanticWindowId ?? `window:${tab.index}`;
|
|
418
421
|
const items = createMemo<readonly WindowTabItem[]>(() =>
|
|
419
422
|
tabs().map((tab) => ({
|
|
420
423
|
id: tabId(tab),
|
|
424
|
+
disabled: tab.disabled,
|
|
421
425
|
windowIndex: tab.index,
|
|
422
426
|
title: tab.name,
|
|
423
427
|
agentStatus: agentStatus(tab.status),
|
|
@@ -26,7 +26,9 @@
|
|
|
26
26
|
"./runtime-resource-ledger": "./src/runtime-resource-ledger.ts",
|
|
27
27
|
"./fleet-dial-scheduler": "./src/fleet-dial-scheduler.ts",
|
|
28
28
|
"./fleet-connection-status": "./src/fleet-connection-status.ts",
|
|
29
|
-
"./fleet-environments": "./src/fleet-environments.ts"
|
|
29
|
+
"./fleet-environments": "./src/fleet-environments.ts",
|
|
30
|
+
"./tmux-server-client": "./src/tmux-server-client.ts",
|
|
31
|
+
"./scoped-tmux-server-transport": "./src/scoped-tmux-server-transport.ts"
|
|
30
32
|
},
|
|
31
33
|
"main": "src/index.ts",
|
|
32
34
|
"scripts": {
|
|
@@ -27,3 +27,5 @@ export * from "./first-latest-coordinator.ts";
|
|
|
27
27
|
export * from "./fleet-dial-scheduler.ts";
|
|
28
28
|
export * from "./fleet-connection-status.ts";
|
|
29
29
|
export * from "./fleet-environments.ts";
|
|
30
|
+
export * from "./tmux-server-client.ts";
|
|
31
|
+
export * from "./scoped-tmux-server-transport.ts";
|
|
@@ -13,7 +13,7 @@ const INSTANCE = "11111111-1111-4111-8111-111111111111";
|
|
|
13
13
|
const REQUEST = "22222222-2222-4222-8222-222222222222";
|
|
14
14
|
const TRANSACTION = "33333333-3333-4333-8333-333333333333";
|
|
15
15
|
const OPERATION = "44444444-4444-4444-8444-444444444444";
|
|
16
|
-
const TICKET = `
|
|
16
|
+
const TICKET = `ps2_${"a".repeat(43)}`;
|
|
17
17
|
|
|
18
18
|
class FakeSocket implements PaneStreamClientSocket {
|
|
19
19
|
readyState = 1;
|
|
@@ -51,9 +51,9 @@ class FakeSocket implements PaneStreamClientSocket {
|
|
|
51
51
|
|
|
52
52
|
function descriptor(viewerMode: "interactive" | "read-only" = "interactive") {
|
|
53
53
|
return {
|
|
54
|
-
protocolVersion:
|
|
55
|
-
webSocketUrl: "ws://127.0.0.1:6060/
|
|
56
|
-
subprotocol: "tmux-ide-pane-stream.
|
|
54
|
+
protocolVersion: 2,
|
|
55
|
+
webSocketUrl: "ws://127.0.0.1:6060/v2/terminal/pane-streams/redeem",
|
|
56
|
+
subprotocol: "tmux-ide-pane-stream.v2",
|
|
57
57
|
redemptionTicket: TICKET,
|
|
58
58
|
daemonInstanceId: INSTANCE,
|
|
59
59
|
requestId: REQUEST,
|
|
@@ -72,7 +72,7 @@ function options(socket: FakeSocket, overrides: Record<string, unknown> = {}) {
|
|
|
72
72
|
hostClientId: "tui:one",
|
|
73
73
|
requestId: REQUEST,
|
|
74
74
|
stream: {
|
|
75
|
-
protocolVersion:
|
|
75
|
+
protocolVersion: 2 as const,
|
|
76
76
|
workspaceName: "alpha",
|
|
77
77
|
panes: ["pane.editor"],
|
|
78
78
|
viewerMode: "interactive" as const,
|
|
@@ -114,7 +114,7 @@ function acceptInteractiveHandshake(socket: FakeSocket): void {
|
|
|
114
114
|
queueMicrotask(() =>
|
|
115
115
|
socket.message({
|
|
116
116
|
type: "ready",
|
|
117
|
-
protocolVersion:
|
|
117
|
+
protocolVersion: 2,
|
|
118
118
|
daemonInstanceId: INSTANCE,
|
|
119
119
|
requestId: REQUEST,
|
|
120
120
|
panes: ["pane.editor"],
|
|
@@ -172,6 +172,18 @@ describe("semantic pane-stream runtime client", () => {
|
|
|
172
172
|
const frame = {
|
|
173
173
|
type: "layout-snapshot",
|
|
174
174
|
topologyEpoch: 4,
|
|
175
|
+
windowLinks: {
|
|
176
|
+
liveSessionId: "live-session." + "a".repeat(20),
|
|
177
|
+
linkRevision: 1,
|
|
178
|
+
activeLinkId: "window-link." + "a".repeat(32),
|
|
179
|
+
links: [
|
|
180
|
+
{
|
|
181
|
+
linkId: "window-link." + "a".repeat(32),
|
|
182
|
+
semanticWindowId: "window.one",
|
|
183
|
+
displayIndex: 0,
|
|
184
|
+
},
|
|
185
|
+
],
|
|
186
|
+
},
|
|
175
187
|
layouts: [
|
|
176
188
|
{
|
|
177
189
|
type: "layout",
|
|
@@ -203,6 +215,64 @@ describe("semantic pane-stream runtime client", () => {
|
|
|
203
215
|
expect(socket.closed).toMatchObject({ code: 1008, reason: "protocol-error" });
|
|
204
216
|
});
|
|
205
217
|
|
|
218
|
+
it.each(["session", "revision", "membership", "index"])(
|
|
219
|
+
"rejects %s link authority changes before publication",
|
|
220
|
+
async (change) => {
|
|
221
|
+
const socket = new FakeSocket();
|
|
222
|
+
acceptInteractiveHandshake(socket);
|
|
223
|
+
const published = mock();
|
|
224
|
+
const faults = mock();
|
|
225
|
+
const client = await openPaneStreamRuntimeClient(
|
|
226
|
+
options(socket, { onLayoutSnapshot: published, onFault: faults }),
|
|
227
|
+
);
|
|
228
|
+
const firstId = `window-link.${"a".repeat(32)}`;
|
|
229
|
+
const secondId = `window-link.${"b".repeat(32)}`;
|
|
230
|
+
const windowLinks = {
|
|
231
|
+
liveSessionId: `live-session.${"a".repeat(20)}`,
|
|
232
|
+
linkRevision: 3,
|
|
233
|
+
activeLinkId: firstId,
|
|
234
|
+
links: [
|
|
235
|
+
{ linkId: firstId, semanticWindowId: "window.one", displayIndex: 0 },
|
|
236
|
+
{ linkId: secondId, semanticWindowId: "window.one", displayIndex: 1 },
|
|
237
|
+
],
|
|
238
|
+
};
|
|
239
|
+
const frame = {
|
|
240
|
+
type: "layout-snapshot",
|
|
241
|
+
topologyEpoch: 1,
|
|
242
|
+
windowLinks,
|
|
243
|
+
layouts: [
|
|
244
|
+
{
|
|
245
|
+
type: "layout",
|
|
246
|
+
semanticWindowId: "window.one",
|
|
247
|
+
windowName: "work",
|
|
248
|
+
currentWindow: true,
|
|
249
|
+
cols: 80,
|
|
250
|
+
rows: 24,
|
|
251
|
+
zoomed: false,
|
|
252
|
+
paneBorderStatus: "off",
|
|
253
|
+
panes: [{ pane: "pane.editor", left: 0, top: 0, width: 80, height: 24, active: true }],
|
|
254
|
+
},
|
|
255
|
+
],
|
|
256
|
+
};
|
|
257
|
+
socket.message(frame);
|
|
258
|
+
socket.message({
|
|
259
|
+
...frame,
|
|
260
|
+
topologyEpoch: 2,
|
|
261
|
+
windowLinks: { ...windowLinks, activeLinkId: secondId },
|
|
262
|
+
});
|
|
263
|
+
expect(published).toHaveBeenCalledTimes(2);
|
|
264
|
+
const changed = structuredClone(windowLinks);
|
|
265
|
+
if (change === "session") changed.liveSessionId = `live-session.${"b".repeat(20)}`;
|
|
266
|
+
if (change === "revision") changed.linkRevision = 2;
|
|
267
|
+
if (change === "membership") changed.links.pop();
|
|
268
|
+
if (change === "index") changed.links[1]!.displayIndex = 9;
|
|
269
|
+
socket.message({ ...frame, topologyEpoch: 3, windowLinks: changed });
|
|
270
|
+
expect(published).toHaveBeenCalledTimes(2);
|
|
271
|
+
expect(faults).toHaveBeenCalledTimes(1);
|
|
272
|
+
client.close();
|
|
273
|
+
},
|
|
274
|
+
);
|
|
275
|
+
|
|
206
276
|
it("calibrates five bounded clock probes before readiness and never exposes raw origins", async () => {
|
|
207
277
|
const socket = new FakeSocket();
|
|
208
278
|
const calibrations: unknown[] = [];
|
|
@@ -213,7 +283,7 @@ describe("semantic pane-stream runtime client", () => {
|
|
|
213
283
|
queueMicrotask(() =>
|
|
214
284
|
socket.message({
|
|
215
285
|
type: "ready",
|
|
216
|
-
protocolVersion:
|
|
286
|
+
protocolVersion: 2,
|
|
217
287
|
daemonInstanceId: INSTANCE,
|
|
218
288
|
requestId: REQUEST,
|
|
219
289
|
connectionClientId: "tui:one",
|
|
@@ -311,7 +381,7 @@ describe("semantic pane-stream runtime client", () => {
|
|
|
311
381
|
queueMicrotask(() =>
|
|
312
382
|
socket.message({
|
|
313
383
|
type: "ready",
|
|
314
|
-
protocolVersion:
|
|
384
|
+
protocolVersion: 2,
|
|
315
385
|
daemonInstanceId: INSTANCE,
|
|
316
386
|
requestId: REQUEST,
|
|
317
387
|
panes: ["pane.editor"],
|
|
@@ -367,7 +437,7 @@ describe("semantic pane-stream runtime client", () => {
|
|
|
367
437
|
queueMicrotask(() =>
|
|
368
438
|
socket.message({
|
|
369
439
|
type: "ready",
|
|
370
|
-
protocolVersion:
|
|
440
|
+
protocolVersion: 2,
|
|
371
441
|
daemonInstanceId: INSTANCE,
|
|
372
442
|
requestId: REQUEST,
|
|
373
443
|
panes: ["pane.editor"],
|
|
@@ -431,7 +501,7 @@ describe("semantic pane-stream runtime client", () => {
|
|
|
431
501
|
queueMicrotask(() =>
|
|
432
502
|
socket.message({
|
|
433
503
|
type: "ready",
|
|
434
|
-
protocolVersion:
|
|
504
|
+
protocolVersion: 2,
|
|
435
505
|
daemonInstanceId: INSTANCE,
|
|
436
506
|
requestId: REQUEST,
|
|
437
507
|
panes: ["pane.editor"],
|
|
@@ -478,7 +548,7 @@ describe("semantic pane-stream runtime client", () => {
|
|
|
478
548
|
queueMicrotask(() =>
|
|
479
549
|
socket.message({
|
|
480
550
|
type: "ready",
|
|
481
|
-
protocolVersion:
|
|
551
|
+
protocolVersion: 2,
|
|
482
552
|
daemonInstanceId: INSTANCE,
|
|
483
553
|
requestId: REQUEST,
|
|
484
554
|
panes: ["pane.editor"],
|
|
@@ -527,7 +597,7 @@ describe("semantic pane-stream runtime client", () => {
|
|
|
527
597
|
queueMicrotask(() =>
|
|
528
598
|
socket.message({
|
|
529
599
|
type: "ready",
|
|
530
|
-
protocolVersion:
|
|
600
|
+
protocolVersion: 2,
|
|
531
601
|
daemonInstanceId: INSTANCE,
|
|
532
602
|
requestId: REQUEST,
|
|
533
603
|
panes: ["pane.editor"],
|
|
@@ -578,7 +648,7 @@ describe("semantic pane-stream runtime client", () => {
|
|
|
578
648
|
queueMicrotask(() =>
|
|
579
649
|
failOpenSocket.message({
|
|
580
650
|
type: "ready",
|
|
581
|
-
protocolVersion:
|
|
651
|
+
protocolVersion: 2,
|
|
582
652
|
daemonInstanceId: INSTANCE,
|
|
583
653
|
requestId: REQUEST,
|
|
584
654
|
panes: ["pane.editor"],
|
|
@@ -657,7 +727,7 @@ describe("semantic pane-stream runtime client", () => {
|
|
|
657
727
|
queueMicrotask(() =>
|
|
658
728
|
socket.message({
|
|
659
729
|
type: "ready",
|
|
660
|
-
protocolVersion:
|
|
730
|
+
protocolVersion: 2,
|
|
661
731
|
daemonInstanceId: INSTANCE,
|
|
662
732
|
requestId: REQUEST,
|
|
663
733
|
panes: ["pane.editor"],
|
|
@@ -706,7 +776,7 @@ describe("semantic pane-stream runtime client", () => {
|
|
|
706
776
|
queueMicrotask(() =>
|
|
707
777
|
duplicateSocket.message({
|
|
708
778
|
type: "ready",
|
|
709
|
-
protocolVersion:
|
|
779
|
+
protocolVersion: 2,
|
|
710
780
|
daemonInstanceId: INSTANCE,
|
|
711
781
|
requestId: REQUEST,
|
|
712
782
|
panes: ["pane.editor"],
|
|
@@ -758,7 +828,7 @@ describe("semantic pane-stream runtime client", () => {
|
|
|
758
828
|
queueMicrotask(() =>
|
|
759
829
|
clockSocket.message({
|
|
760
830
|
type: "ready",
|
|
761
|
-
protocolVersion:
|
|
831
|
+
protocolVersion: 2,
|
|
762
832
|
daemonInstanceId: INSTANCE,
|
|
763
833
|
requestId: REQUEST,
|
|
764
834
|
panes: ["pane.editor"],
|
|
@@ -1152,7 +1222,7 @@ describe("semantic pane-stream runtime client", () => {
|
|
|
1152
1222
|
queueMicrotask(() =>
|
|
1153
1223
|
socket.message({
|
|
1154
1224
|
type: "ready",
|
|
1155
|
-
protocolVersion:
|
|
1225
|
+
protocolVersion: 2,
|
|
1156
1226
|
daemonInstanceId: INSTANCE,
|
|
1157
1227
|
requestId: REQUEST,
|
|
1158
1228
|
panes: ["pane.editor"],
|
|
@@ -1200,7 +1270,7 @@ describe("semantic pane-stream runtime client", () => {
|
|
|
1200
1270
|
queueMicrotask(() =>
|
|
1201
1271
|
socket.message({
|
|
1202
1272
|
type: "ready",
|
|
1203
|
-
protocolVersion:
|
|
1273
|
+
protocolVersion: 2,
|
|
1204
1274
|
daemonInstanceId: INSTANCE,
|
|
1205
1275
|
requestId: REQUEST,
|
|
1206
1276
|
connectionClientId: "tui:one",
|
|
@@ -1278,7 +1348,7 @@ describe("semantic pane-stream runtime client", () => {
|
|
|
1278
1348
|
queueMicrotask(() =>
|
|
1279
1349
|
socket.message({
|
|
1280
1350
|
type: "ready",
|
|
1281
|
-
protocolVersion:
|
|
1351
|
+
protocolVersion: 2,
|
|
1282
1352
|
daemonInstanceId: INSTANCE,
|
|
1283
1353
|
requestId: REQUEST,
|
|
1284
1354
|
panes: ["pane.editor"],
|
|
@@ -1324,7 +1394,7 @@ describe("semantic pane-stream runtime client", () => {
|
|
|
1324
1394
|
queueMicrotask(() =>
|
|
1325
1395
|
socket.message({
|
|
1326
1396
|
type: "ready",
|
|
1327
|
-
protocolVersion:
|
|
1397
|
+
protocolVersion: 2,
|
|
1328
1398
|
daemonInstanceId: INSTANCE,
|
|
1329
1399
|
requestId: REQUEST,
|
|
1330
1400
|
panes: ["pane.editor"],
|
|
@@ -1428,7 +1498,7 @@ describe("semantic pane-stream runtime client", () => {
|
|
|
1428
1498
|
queueMicrotask(() =>
|
|
1429
1499
|
socket.message({
|
|
1430
1500
|
type: "ready",
|
|
1431
|
-
protocolVersion:
|
|
1501
|
+
protocolVersion: 2,
|
|
1432
1502
|
daemonInstanceId: INSTANCE,
|
|
1433
1503
|
requestId: REQUEST,
|
|
1434
1504
|
panes: ["pane.editor"],
|
|
@@ -1498,7 +1568,7 @@ describe("semantic pane-stream runtime client", () => {
|
|
|
1498
1568
|
queueMicrotask(() =>
|
|
1499
1569
|
socket.message({
|
|
1500
1570
|
type: "ready",
|
|
1501
|
-
protocolVersion:
|
|
1571
|
+
protocolVersion: 2,
|
|
1502
1572
|
daemonInstanceId: INSTANCE,
|
|
1503
1573
|
requestId: REQUEST,
|
|
1504
1574
|
panes: ["pane.editor"],
|
|
@@ -1587,7 +1657,7 @@ describe("semantic pane-stream runtime client", () => {
|
|
|
1587
1657
|
queueMicrotask(() =>
|
|
1588
1658
|
socket.message({
|
|
1589
1659
|
type: "ready",
|
|
1590
|
-
protocolVersion:
|
|
1660
|
+
protocolVersion: 2,
|
|
1591
1661
|
daemonInstanceId: INSTANCE,
|
|
1592
1662
|
requestId: REQUEST,
|
|
1593
1663
|
panes: ["pane.editor"],
|
|
@@ -1628,7 +1698,7 @@ describe("semantic pane-stream runtime client", () => {
|
|
|
1628
1698
|
queueMicrotask(() =>
|
|
1629
1699
|
socket.message({
|
|
1630
1700
|
type: "ready",
|
|
1631
|
-
protocolVersion:
|
|
1701
|
+
protocolVersion: 2,
|
|
1632
1702
|
daemonInstanceId: INSTANCE,
|
|
1633
1703
|
requestId: REQUEST,
|
|
1634
1704
|
panes: ["pane.editor"],
|
|
@@ -1691,7 +1761,7 @@ describe("semantic pane-stream runtime client", () => {
|
|
|
1691
1761
|
queueMicrotask(() =>
|
|
1692
1762
|
socket.message({
|
|
1693
1763
|
type: "ready",
|
|
1694
|
-
protocolVersion:
|
|
1764
|
+
protocolVersion: 2,
|
|
1695
1765
|
daemonInstanceId: INSTANCE,
|
|
1696
1766
|
requestId: REQUEST,
|
|
1697
1767
|
panes: ["pane.editor"],
|
|
@@ -1733,7 +1803,7 @@ describe("semantic pane-stream runtime client", () => {
|
|
|
1733
1803
|
queueMicrotask(() =>
|
|
1734
1804
|
socket.message({
|
|
1735
1805
|
type: "ready",
|
|
1736
|
-
protocolVersion:
|
|
1806
|
+
protocolVersion: 2,
|
|
1737
1807
|
daemonInstanceId: INSTANCE,
|
|
1738
1808
|
requestId: REQUEST,
|
|
1739
1809
|
panes: ["pane.editor"],
|
|
@@ -1961,7 +2031,7 @@ describe("semantic pane-stream runtime client", () => {
|
|
|
1961
2031
|
queueMicrotask(() =>
|
|
1962
2032
|
socket.message({
|
|
1963
2033
|
type: "ready",
|
|
1964
|
-
protocolVersion:
|
|
2034
|
+
protocolVersion: 2,
|
|
1965
2035
|
daemonInstanceId: INSTANCE,
|
|
1966
2036
|
requestId: REQUEST,
|
|
1967
2037
|
panes: ["pane.editor"],
|
|
@@ -2055,7 +2125,7 @@ describe("semantic pane-stream runtime client", () => {
|
|
|
2055
2125
|
queueMicrotask(() =>
|
|
2056
2126
|
socket.message({
|
|
2057
2127
|
type: "ready",
|
|
2058
|
-
protocolVersion:
|
|
2128
|
+
protocolVersion: 2,
|
|
2059
2129
|
daemonInstanceId: INSTANCE,
|
|
2060
2130
|
requestId: REQUEST,
|
|
2061
2131
|
panes: ["pane.editor"],
|
|
@@ -2202,7 +2272,7 @@ describe("semantic pane-stream runtime client", () => {
|
|
|
2202
2272
|
queueMicrotask(() =>
|
|
2203
2273
|
socket.message({
|
|
2204
2274
|
type: "ready",
|
|
2205
|
-
protocolVersion:
|
|
2275
|
+
protocolVersion: 2,
|
|
2206
2276
|
daemonInstanceId: INSTANCE,
|
|
2207
2277
|
requestId: REQUEST,
|
|
2208
2278
|
panes: ["pane.editor"],
|
|
@@ -2279,7 +2349,7 @@ describe("semantic pane-stream runtime client", () => {
|
|
|
2279
2349
|
queueMicrotask(() =>
|
|
2280
2350
|
socket.message({
|
|
2281
2351
|
type: "ready",
|
|
2282
|
-
protocolVersion:
|
|
2352
|
+
protocolVersion: 2,
|
|
2283
2353
|
daemonInstanceId: INSTANCE,
|
|
2284
2354
|
requestId: REQUEST,
|
|
2285
2355
|
panes: ["pane.editor"],
|
|
@@ -2340,7 +2410,7 @@ describe("semantic pane-stream runtime client", () => {
|
|
|
2340
2410
|
queueMicrotask(() =>
|
|
2341
2411
|
socket.message({
|
|
2342
2412
|
type: "ready",
|
|
2343
|
-
protocolVersion:
|
|
2413
|
+
protocolVersion: 2,
|
|
2344
2414
|
daemonInstanceId: INSTANCE,
|
|
2345
2415
|
requestId: REQUEST,
|
|
2346
2416
|
panes: ["pane.editor"],
|
|
@@ -2420,7 +2490,7 @@ describe("semantic pane-stream runtime client", () => {
|
|
|
2420
2490
|
queueMicrotask(() =>
|
|
2421
2491
|
socket.message({
|
|
2422
2492
|
type: "ready",
|
|
2423
|
-
protocolVersion:
|
|
2493
|
+
protocolVersion: 2,
|
|
2424
2494
|
daemonInstanceId: INSTANCE,
|
|
2425
2495
|
requestId: REQUEST,
|
|
2426
2496
|
panes: ["pane.editor"],
|
|
@@ -2493,7 +2563,7 @@ describe("semantic pane-stream runtime client", () => {
|
|
|
2493
2563
|
queueMicrotask(() =>
|
|
2494
2564
|
socket.message({
|
|
2495
2565
|
type: "ready",
|
|
2496
|
-
protocolVersion:
|
|
2566
|
+
protocolVersion: 2,
|
|
2497
2567
|
daemonInstanceId: INSTANCE,
|
|
2498
2568
|
requestId: REQUEST,
|
|
2499
2569
|
panes: ["pane.editor"],
|
|
@@ -2546,7 +2616,7 @@ describe("semantic pane-stream runtime client", () => {
|
|
|
2546
2616
|
queueMicrotask(() =>
|
|
2547
2617
|
socket.message({
|
|
2548
2618
|
type: "ready",
|
|
2549
|
-
protocolVersion:
|
|
2619
|
+
protocolVersion: 2,
|
|
2550
2620
|
daemonInstanceId: INSTANCE,
|
|
2551
2621
|
requestId: REQUEST,
|
|
2552
2622
|
panes: ["pane.editor"],
|
|
@@ -2567,7 +2637,7 @@ describe("semantic pane-stream runtime client", () => {
|
|
|
2567
2637
|
queueMicrotask(() =>
|
|
2568
2638
|
socket.message({
|
|
2569
2639
|
type: "ready",
|
|
2570
|
-
protocolVersion:
|
|
2640
|
+
protocolVersion: 2,
|
|
2571
2641
|
daemonInstanceId: INSTANCE,
|
|
2572
2642
|
requestId: REQUEST,
|
|
2573
2643
|
connectionClientId: "web:foreign",
|
|
@@ -2589,7 +2659,7 @@ describe("semantic pane-stream runtime client", () => {
|
|
|
2589
2659
|
queueMicrotask(() =>
|
|
2590
2660
|
socket.message({
|
|
2591
2661
|
type: "ready",
|
|
2592
|
-
protocolVersion:
|
|
2662
|
+
protocolVersion: 2,
|
|
2593
2663
|
daemonInstanceId: INSTANCE,
|
|
2594
2664
|
requestId: REQUEST,
|
|
2595
2665
|
panes: ["pane.editor"],
|
|
@@ -2648,7 +2718,7 @@ describe("semantic pane-stream runtime client", () => {
|
|
|
2648
2718
|
|
|
2649
2719
|
socket.message({
|
|
2650
2720
|
type: "error",
|
|
2651
|
-
protocolVersion:
|
|
2721
|
+
protocolVersion: 2,
|
|
2652
2722
|
code: "topology-changed",
|
|
2653
2723
|
retryable: true,
|
|
2654
2724
|
});
|
|
@@ -2669,7 +2739,7 @@ describe("semantic pane-stream runtime client", () => {
|
|
|
2669
2739
|
queueMicrotask(() =>
|
|
2670
2740
|
socket.message({
|
|
2671
2741
|
type: "ready",
|
|
2672
|
-
protocolVersion:
|
|
2742
|
+
protocolVersion: 2,
|
|
2673
2743
|
daemonInstanceId: INSTANCE,
|
|
2674
2744
|
requestId: REQUEST,
|
|
2675
2745
|
panes: ["pane.editor"],
|
|
@@ -32,6 +32,7 @@ import {
|
|
|
32
32
|
type TerminalDeliveryServerMessage,
|
|
33
33
|
type TerminalDeliveryVisibility,
|
|
34
34
|
type WorkspaceMultiplexerMutationResult,
|
|
35
|
+
type WindowLinkTopology,
|
|
35
36
|
} from "@tmux-ide/contracts";
|
|
36
37
|
import {
|
|
37
38
|
calibratePaneStreamClocks,
|
|
@@ -449,6 +450,7 @@ export async function connectIssuedPaneStreamRuntimeClient(
|
|
|
449
450
|
let closed = false;
|
|
450
451
|
let verified = false;
|
|
451
452
|
let layoutTopologyEpoch = -1;
|
|
453
|
+
let windowLinks: WindowLinkTopology | null = null;
|
|
452
454
|
let resolveReady!: (client: PaneStreamRuntimeClient) => void;
|
|
453
455
|
let rejectReady!: (error: Error) => void;
|
|
454
456
|
const ready = new Promise<PaneStreamRuntimeClient>((resolve, reject) => {
|
|
@@ -1446,6 +1448,30 @@ export async function connectIssuedPaneStreamRuntimeClient(
|
|
|
1446
1448
|
if (frame.type === "layout-snapshot") {
|
|
1447
1449
|
if (frame.topologyEpoch <= layoutTopologyEpoch)
|
|
1448
1450
|
return fail("Pane-stream layout topology epoch did not advance");
|
|
1451
|
+
const incoming = frame.windowLinks;
|
|
1452
|
+
if (windowLinks) {
|
|
1453
|
+
if (
|
|
1454
|
+
incoming.liveSessionId !== windowLinks.liveSessionId ||
|
|
1455
|
+
incoming.linkRevision < windowLinks.linkRevision
|
|
1456
|
+
)
|
|
1457
|
+
return fail("Pane-stream window link authority regressed or changed session");
|
|
1458
|
+
if (incoming.linkRevision === windowLinks.linkRevision) {
|
|
1459
|
+
const previous = new Map(windowLinks.links.map((link) => [link.linkId, link]));
|
|
1460
|
+
if (
|
|
1461
|
+
incoming.links.length !== previous.size ||
|
|
1462
|
+
incoming.links.some((link) => {
|
|
1463
|
+
const observed = previous.get(link.linkId);
|
|
1464
|
+
return (
|
|
1465
|
+
!observed ||
|
|
1466
|
+
observed.semanticWindowId !== link.semanticWindowId ||
|
|
1467
|
+
observed.displayIndex !== link.displayIndex
|
|
1468
|
+
);
|
|
1469
|
+
})
|
|
1470
|
+
)
|
|
1471
|
+
return fail("Pane-stream link membership changed without a revision advance");
|
|
1472
|
+
}
|
|
1473
|
+
}
|
|
1474
|
+
windowLinks = incoming;
|
|
1449
1475
|
layoutTopologyEpoch = frame.topologyEpoch;
|
|
1450
1476
|
}
|
|
1451
1477
|
routeFrame(options, frame, fail);
|