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
|
@@ -1,4 +1,24 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createNativeTmuxSessionCreator } from "./tmux-server-session-create.ts";
|
|
2
|
+
import { createTmuxSessionMutationFence } from "./tmux-session-mutation-fence.ts";
|
|
3
|
+
import { createNativeTmuxSessionOpener } from "./tmux-server-session-open.ts";
|
|
4
|
+
import {
|
|
5
|
+
createServerGenerationFencedTmuxRunner,
|
|
6
|
+
createServerGenerationFencedTmuxAsyncRunner,
|
|
7
|
+
} from "./tmux-server-generation-runner.ts";
|
|
8
|
+
import { createNativeTmuxServerCatalog } from "./tmux-server-owner.ts";
|
|
9
|
+
import { createEmbeddedTmuxServerOwners } from "./embedded-tmux-server-owners.ts";
|
|
10
|
+
import {
|
|
11
|
+
captureTmuxServerProofAsync,
|
|
12
|
+
captureTmuxServerProof,
|
|
13
|
+
captureUnboundTmuxSelectorProof,
|
|
14
|
+
type TmuxServerProof,
|
|
15
|
+
} from "./tmux-server-proof.ts";
|
|
16
|
+
import { assertCanonicalDaemonServerIntent } from "./canonical-daemon-bootstrap.ts";
|
|
17
|
+
import {
|
|
18
|
+
runtimeTmuxArgs,
|
|
19
|
+
resolveTmuxServerIntent,
|
|
20
|
+
resolveRuntimeNamespace,
|
|
21
|
+
} from "./runtime-namespace.ts";
|
|
2
22
|
import { createFleetPreviewCapture } from "../command-center/resources/fleet-preview-route.ts";
|
|
3
23
|
import { mountTerminalNativeBackingRoute } from "../command-center/resources/terminal-native-backing-route.ts";
|
|
4
24
|
import { startOwnedEmbeddedDaemon } from "./embedded-daemon-lifecycle.ts";
|
|
@@ -34,7 +54,6 @@ import {
|
|
|
34
54
|
import {
|
|
35
55
|
classifySessionInspectionError,
|
|
36
56
|
DaemonSessionMonitor,
|
|
37
|
-
execTmuxAsync,
|
|
38
57
|
isConfirmedMissingTmuxTarget,
|
|
39
58
|
parseDaemonMonitorPanes,
|
|
40
59
|
readPortProcessFactsAsync,
|
|
@@ -221,14 +240,6 @@ function tmux(...args: string[]): string {
|
|
|
221
240
|
}).trim();
|
|
222
241
|
}
|
|
223
242
|
|
|
224
|
-
function tmuxSilent(...args: string[]): string {
|
|
225
|
-
try {
|
|
226
|
-
return tmux(...args);
|
|
227
|
-
} catch {
|
|
228
|
-
return "";
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
|
|
232
243
|
function assertTmuxSession(
|
|
233
244
|
sessionName: string,
|
|
234
245
|
runTmux: (args: readonly string[]) => string = (args) => tmux(...args),
|
|
@@ -549,6 +560,7 @@ function sameCanonicalInstance(left: CanonicalDaemonInfo, right: CanonicalDaemon
|
|
|
549
560
|
async function requestValidatedDaemonShutdown(
|
|
550
561
|
info: CanonicalDaemonInfo,
|
|
551
562
|
deadline: TakeoverDeadline,
|
|
563
|
+
intent: ReturnType<typeof resolveTmuxServerIntent>,
|
|
552
564
|
): Promise<void> {
|
|
553
565
|
if (info.supervisionId)
|
|
554
566
|
throw new DaemonStartupError(
|
|
@@ -573,6 +585,8 @@ async function requestValidatedDaemonShutdown(
|
|
|
573
585
|
"canonical_takeover_identity_mismatch",
|
|
574
586
|
);
|
|
575
587
|
}
|
|
588
|
+
await assertCanonicalDaemonServerIntent(info, intent);
|
|
589
|
+
assertTakeoverDeadline(deadline, "Tmux server intent proof exceeded the takeover deadline");
|
|
576
590
|
const health = await probeCanonicalDaemonHealth(info, deadline.signal);
|
|
577
591
|
assertTakeoverDeadline(
|
|
578
592
|
deadline,
|
|
@@ -757,6 +771,7 @@ async function startHttpServer({
|
|
|
757
771
|
localBypassToken,
|
|
758
772
|
silent,
|
|
759
773
|
readProjectAuth,
|
|
774
|
+
tmuxServerProof,
|
|
760
775
|
daemonIdentity,
|
|
761
776
|
workspacePaneCreationBackend,
|
|
762
777
|
workspaceOpenBackend,
|
|
@@ -774,7 +789,9 @@ async function startHttpServer({
|
|
|
774
789
|
catalogFleet,
|
|
775
790
|
fleetPreviewCapture,
|
|
776
791
|
sessionRuntimeRegistry,
|
|
792
|
+
serverOwners,
|
|
777
793
|
}: {
|
|
794
|
+
serverOwners: Awaited<ReturnType<typeof createEmbeddedTmuxServerOwners>>;
|
|
778
795
|
sessionName: string;
|
|
779
796
|
requestedPort: number;
|
|
780
797
|
bindHostname: string;
|
|
@@ -783,6 +800,7 @@ async function startHttpServer({
|
|
|
783
800
|
localBypassToken?: string | null;
|
|
784
801
|
silent?: boolean;
|
|
785
802
|
readProjectAuth?: boolean;
|
|
803
|
+
tmuxServerProof: () => Promise<TmuxServerProof | null>;
|
|
786
804
|
daemonIdentity: {
|
|
787
805
|
productVersion: string;
|
|
788
806
|
instanceId: string;
|
|
@@ -839,6 +857,7 @@ async function startHttpServer({
|
|
|
839
857
|
const authService = new AuthService(authConfig.secret);
|
|
840
858
|
|
|
841
859
|
const app = createApp({
|
|
860
|
+
tmuxServerOwners: serverOwners.owners,
|
|
842
861
|
authService,
|
|
843
862
|
authConfig,
|
|
844
863
|
remoteAccess: {
|
|
@@ -848,6 +867,7 @@ async function startHttpServer({
|
|
|
848
867
|
ownerToken: localBypassToken ?? null,
|
|
849
868
|
},
|
|
850
869
|
daemonIdentity,
|
|
870
|
+
tmuxServerProof,
|
|
851
871
|
workspacePaneCreationBackend,
|
|
852
872
|
workspaceOpenBackend,
|
|
853
873
|
workspaceOpenHandoffBackend,
|
|
@@ -914,7 +934,13 @@ async function startHttpServer({
|
|
|
914
934
|
(create ? getTerminalAttachmentRuntime() : peekTerminalAttachmentRuntime())?.admission ??
|
|
915
935
|
null,
|
|
916
936
|
);
|
|
917
|
-
const paneStreamBoundary = attachPaneStreamWebSocket(
|
|
937
|
+
const paneStreamBoundary = attachPaneStreamWebSocket(
|
|
938
|
+
server,
|
|
939
|
+
paneStreamRuntime.coordinator,
|
|
940
|
+
PANE_STREAM_REDEEM_PATH,
|
|
941
|
+
() => serverOwners.isDefaultCurrent(),
|
|
942
|
+
);
|
|
943
|
+
serverOwners.attach(server);
|
|
918
944
|
|
|
919
945
|
try {
|
|
920
946
|
await new Promise<void>((resolve, reject) => {
|
|
@@ -987,6 +1013,7 @@ export async function startEmbeddedDaemon(
|
|
|
987
1013
|
async function startEmbeddedDaemonGeneration(
|
|
988
1014
|
opts: EmbeddedDaemonOptions,
|
|
989
1015
|
): Promise<EmbeddedDaemonHandle> {
|
|
1016
|
+
const tmuxServerIntent = resolveTmuxServerIntent();
|
|
990
1017
|
const sessionName = opts.sessionName ?? EMBEDDED_SESSION_NAME;
|
|
991
1018
|
const sessionless = opts.sessionName == null;
|
|
992
1019
|
const appSettings = readAppSettings();
|
|
@@ -1026,7 +1053,7 @@ async function startEmbeddedDaemonGeneration(
|
|
|
1026
1053
|
if (state.status === "valid" && (await isCanonicalDaemonAlive(state.info))) {
|
|
1027
1054
|
const takeoverDeadline = createTakeoverDeadline(takeoverTimeoutMs());
|
|
1028
1055
|
try {
|
|
1029
|
-
await requestValidatedDaemonShutdown(state.info, takeoverDeadline);
|
|
1056
|
+
await requestValidatedDaemonShutdown(state.info, takeoverDeadline, tmuxServerIntent);
|
|
1030
1057
|
claim = await acquireCanonicalDaemonClaimAfterTakeover(state.info, takeoverDeadline);
|
|
1031
1058
|
} finally {
|
|
1032
1059
|
takeoverDeadline.dispose();
|
|
@@ -1084,7 +1111,22 @@ async function startEmbeddedDaemonGeneration(
|
|
|
1084
1111
|
// caller's ambient TMUX/PATH happens to select.
|
|
1085
1112
|
const tmuxAuthority = resolveWorkspacePaneTmuxAuthority();
|
|
1086
1113
|
const catalogTmuxRunner = createPinnedWorkspaceTmuxRunner(tmuxAuthority);
|
|
1087
|
-
const
|
|
1114
|
+
const initialTmuxProof = captureTmuxServerProof(catalogTmuxRunner);
|
|
1115
|
+
const initialNativeIdentityParts = initialTmuxProof
|
|
1116
|
+
? catalogTmuxRunner(["display-message", "-p", "#{pid}\t#{start_time}"]).split("\t")
|
|
1117
|
+
: null;
|
|
1118
|
+
const initialNativeServerIdentity = initialNativeIdentityParts
|
|
1119
|
+
? { pid: initialNativeIdentityParts[0]!, startTime: initialNativeIdentityParts[1]! }
|
|
1120
|
+
: undefined;
|
|
1121
|
+
const sessionMutationFence = createTmuxSessionMutationFence();
|
|
1122
|
+
const nativeGenerationTmuxRunner = sessionMutationFence.wrap(
|
|
1123
|
+
initialNativeServerIdentity
|
|
1124
|
+
? createServerGenerationFencedTmuxRunner(tmuxAuthority, initialNativeServerIdentity)
|
|
1125
|
+
: catalogTmuxRunner,
|
|
1126
|
+
);
|
|
1127
|
+
const fleetFactsTmuxRunner = initialNativeServerIdentity
|
|
1128
|
+
? createServerGenerationFencedTmuxAsyncRunner(tmuxAuthority, initialNativeServerIdentity)
|
|
1129
|
+
: createPinnedWorkspaceTmuxAsyncRunner(tmuxAuthority);
|
|
1088
1130
|
const tmuxAuthorityReplaced = createTmuxAuthorityReplacementProbe(
|
|
1089
1131
|
tmuxAuthority,
|
|
1090
1132
|
catalogTmuxRunner,
|
|
@@ -1110,8 +1152,8 @@ async function startEmbeddedDaemonGeneration(
|
|
|
1110
1152
|
const workspaceRegistry = getDefaultWorkspaceRegistry();
|
|
1111
1153
|
await workspaceRegistry.load(() => readWorkspaceRegistrySessionInventory(registryTmuxRunner));
|
|
1112
1154
|
const paneSourceCredentials = new PaneSourceCredentialAuthority({
|
|
1113
|
-
run: (args) =>
|
|
1114
|
-
runAsync: (args, signal) =>
|
|
1155
|
+
run: (args) => nativeGenerationTmuxRunner(args),
|
|
1156
|
+
runAsync: (args, signal) => fleetFactsTmuxRunner(args, signal),
|
|
1115
1157
|
});
|
|
1116
1158
|
const legacySession = process.env.TMUX_IDE_SESSION;
|
|
1117
1159
|
if (legacySession && !workspaceRegistry.has(legacySession)) {
|
|
@@ -1153,16 +1195,19 @@ async function startEmbeddedDaemonGeneration(
|
|
|
1153
1195
|
daemonInstanceId: instanceId,
|
|
1154
1196
|
registry: workspaceRegistry,
|
|
1155
1197
|
tmuxAuthority,
|
|
1198
|
+
io: { runTmux: nativeGenerationTmuxRunner },
|
|
1156
1199
|
});
|
|
1157
1200
|
const workspaceOpen = new WorkspaceOpenAuthority({
|
|
1158
1201
|
daemonInstanceId: instanceId,
|
|
1159
1202
|
registry: workspaceRegistry,
|
|
1160
1203
|
tmuxAuthority,
|
|
1204
|
+
io: { runTmux: nativeGenerationTmuxRunner },
|
|
1161
1205
|
});
|
|
1162
1206
|
const workspacePromotion = new WorkspacePromotionAuthority({
|
|
1163
1207
|
daemonInstanceId: instanceId,
|
|
1164
1208
|
registry: workspaceRegistry,
|
|
1165
1209
|
tmuxAuthority,
|
|
1210
|
+
io: { runTmux: fleetFactsTmuxRunner },
|
|
1166
1211
|
});
|
|
1167
1212
|
if (opts.restoreTmuxWorkspaces) {
|
|
1168
1213
|
for (const workspace of workspaceRegistry.list()) {
|
|
@@ -1178,7 +1223,7 @@ async function startEmbeddedDaemonGeneration(
|
|
|
1178
1223
|
productVersion,
|
|
1179
1224
|
startedAt,
|
|
1180
1225
|
registry: workspaceRegistry,
|
|
1181
|
-
runTmux:
|
|
1226
|
+
runTmux: nativeGenerationTmuxRunner,
|
|
1182
1227
|
readFleet: () => readAdoptedFleet(workspaceRegistry, catalogTmuxRunner),
|
|
1183
1228
|
});
|
|
1184
1229
|
const appWindowMutation = new AppWindowMutationAuthority({
|
|
@@ -1189,13 +1234,22 @@ async function startEmbeddedDaemonGeneration(
|
|
|
1189
1234
|
daemonInstanceId: instanceId,
|
|
1190
1235
|
registry: workspaceRegistry,
|
|
1191
1236
|
tmuxAuthority,
|
|
1237
|
+
...(initialTmuxProof
|
|
1238
|
+
? {
|
|
1239
|
+
io: {
|
|
1240
|
+
runTmux: nativeGenerationTmuxRunner,
|
|
1241
|
+
},
|
|
1242
|
+
}
|
|
1243
|
+
: {}),
|
|
1192
1244
|
});
|
|
1193
1245
|
let sessionRuntimeRegistry: SessionRuntimeRegistry | null = null;
|
|
1194
1246
|
let workspaceOpenHandoff: WorkspaceOpenHandoffCoordinator | null = null;
|
|
1195
1247
|
let terminalInventoryRuntime: WorkspaceTerminalInventoryRuntime | null = null;
|
|
1248
|
+
let sessionMonitor: DaemonSessionMonitor | null = null;
|
|
1196
1249
|
const externalInteractionObserver = new TmuxExternalInteractionObserver({
|
|
1197
1250
|
daemonInstanceId: instanceId,
|
|
1198
1251
|
internalReadOwnerToken: localBypassToken,
|
|
1252
|
+
io: { runTmux: fleetFactsTmuxRunner },
|
|
1199
1253
|
registry: workspaceRegistry,
|
|
1200
1254
|
tmuxAuthority,
|
|
1201
1255
|
// A gap cannot reconstruct historical interactions. Refresh inventory
|
|
@@ -1238,6 +1292,23 @@ async function startEmbeddedDaemonGeneration(
|
|
|
1238
1292
|
});
|
|
1239
1293
|
let terminalAttachmentRuntime: NativeTerminalAttachmentRuntime | null = null;
|
|
1240
1294
|
let paneStreamRuntime: PaneStreamRuntime | null = null;
|
|
1295
|
+
let serverOwners: Awaited<ReturnType<typeof createEmbeddedTmuxServerOwners>> | null = null;
|
|
1296
|
+
const defaultSessionCreator = createNativeTmuxSessionCreator({
|
|
1297
|
+
generation: instanceId,
|
|
1298
|
+
registry: workspaceRegistry,
|
|
1299
|
+
run: nativeGenerationTmuxRunner,
|
|
1300
|
+
assertOpen: () => {
|
|
1301
|
+
if (serverOwners?.defaultRetired) throw new Error("Default tmux owner is retired");
|
|
1302
|
+
},
|
|
1303
|
+
});
|
|
1304
|
+
const defaultSessionOpener = createNativeTmuxSessionOpener({
|
|
1305
|
+
generation: instanceId,
|
|
1306
|
+
registry: workspaceRegistry,
|
|
1307
|
+
run: fleetFactsTmuxRunner,
|
|
1308
|
+
assertOpen: () => {
|
|
1309
|
+
if (serverOwners?.defaultRetired) throw new Error("Default tmux owner is retired");
|
|
1310
|
+
},
|
|
1311
|
+
});
|
|
1241
1312
|
let runtimeTraceStream: ReturnType<typeof createWriteStream> | null = null;
|
|
1242
1313
|
const closeRuntimeTraceStream = async (): Promise<void> => {
|
|
1243
1314
|
externalInteractionObserver.setDiagnostics(null);
|
|
@@ -1259,6 +1330,19 @@ async function startEmbeddedDaemonGeneration(
|
|
|
1259
1330
|
workspaceMultiplexer.readPane(operationId, intent);
|
|
1260
1331
|
return;
|
|
1261
1332
|
}
|
|
1333
|
+
if (
|
|
1334
|
+
intent.verb === "workspace.window.link.select" ||
|
|
1335
|
+
intent.verb === "workspace.window.link.unlink" ||
|
|
1336
|
+
intent.verb === "workspace.pane.select"
|
|
1337
|
+
) {
|
|
1338
|
+
return workspaceMultiplexer.mutateWindowLink(
|
|
1339
|
+
{ operationId, expectedDaemonInstanceId: instanceId, intent },
|
|
1340
|
+
(session, action) => {
|
|
1341
|
+
if (!sessionRuntimeRegistry) throw new Error("Session runtime unavailable");
|
|
1342
|
+
return sessionRuntimeRegistry.executeWindowLinkAction(session, action);
|
|
1343
|
+
},
|
|
1344
|
+
);
|
|
1345
|
+
}
|
|
1262
1346
|
return workspaceMultiplexer.mutate(
|
|
1263
1347
|
{ operationId, expectedDaemonInstanceId: instanceId, intent },
|
|
1264
1348
|
timing,
|
|
@@ -1326,8 +1410,10 @@ async function startEmbeddedDaemonGeneration(
|
|
|
1326
1410
|
publishResourceChange: (change) => broadcastResourceChanged(change, instanceId),
|
|
1327
1411
|
},
|
|
1328
1412
|
mirror: {
|
|
1413
|
+
nativeServerIdentity: initialNativeServerIdentity,
|
|
1329
1414
|
executable: tmuxAuthority.executablePath,
|
|
1330
|
-
resolveSocketPath: () =>
|
|
1415
|
+
resolveSocketPath: () =>
|
|
1416
|
+
nativeGenerationTmuxRunner(["display-message", "-p", "#{socket_path}"]),
|
|
1331
1417
|
internalReadHookEmission: (runtimePaneId, marker) =>
|
|
1332
1418
|
externalInteractionObserver.internalReadHookEmission(runtimePaneId, marker),
|
|
1333
1419
|
...(selector.kind === "path" ? { socketPath: selector.path } : {}),
|
|
@@ -1403,6 +1489,7 @@ async function startEmbeddedDaemonGeneration(
|
|
|
1403
1489
|
sessionRuntimeRegistry,
|
|
1404
1490
|
tmuxAuthority: {
|
|
1405
1491
|
executablePath: tmuxAuthority.executablePath,
|
|
1492
|
+
nativeServerIdentity: initialNativeServerIdentity,
|
|
1406
1493
|
socketSelector: tmuxAuthority.socketSelector,
|
|
1407
1494
|
trustedCwd: dir,
|
|
1408
1495
|
...(tmuxAuthority.socketSelector.kind === "name"
|
|
@@ -1454,8 +1541,93 @@ async function startEmbeddedDaemonGeneration(
|
|
|
1454
1541
|
paneSourceCredentials.resolve(credential, resolvedSession, claimedSource),
|
|
1455
1542
|
});
|
|
1456
1543
|
await externalInteractionObserver.start();
|
|
1544
|
+
serverOwners = await createEmbeddedTmuxServerOwners({
|
|
1545
|
+
defaultAuthority: tmuxAuthority,
|
|
1546
|
+
defaultGeneration: instanceId,
|
|
1547
|
+
expectedDefaultProofDigest: initialTmuxProof?.digest ?? null,
|
|
1548
|
+
stateDirectory: resolveRuntimeNamespace().runtimeDir,
|
|
1549
|
+
webSocketBaseUrl: canonicalDaemonUrl("ws", bindHostname, port),
|
|
1550
|
+
defaultOwner: {
|
|
1551
|
+
catalog: createNativeTmuxServerCatalog(workspaceRegistry, fleetFactsTmuxRunner),
|
|
1552
|
+
openSession: async (liveSessionId) => {
|
|
1553
|
+
await createNativeTmuxServerCatalog(workspaceRegistry, fleetFactsTmuxRunner)();
|
|
1554
|
+
const result = await defaultSessionOpener.openSession(liveSessionId);
|
|
1555
|
+
terminalInventoryRuntime!.invalidate();
|
|
1556
|
+
return result;
|
|
1557
|
+
},
|
|
1558
|
+
workspaceRegistry,
|
|
1559
|
+
multiplexerBackend: orderedMultiplexerBackend,
|
|
1560
|
+
createSession: defaultSessionCreator.createSession,
|
|
1561
|
+
createSessionPane: async (liveSessionId, request) => {
|
|
1562
|
+
const selectedSession = workspaceRegistry.get(
|
|
1563
|
+
request.intent.workspaceName,
|
|
1564
|
+
)?.sessionName;
|
|
1565
|
+
if (!selectedSession) throw new Error("Selected workspace is unavailable");
|
|
1566
|
+
const result = await sessionMutationFence.execute({
|
|
1567
|
+
liveSessionId,
|
|
1568
|
+
sessionName: selectedSession,
|
|
1569
|
+
run: fleetFactsTmuxRunner,
|
|
1570
|
+
mutate: () => workspacePaneCreation.create(request),
|
|
1571
|
+
});
|
|
1572
|
+
terminalInventoryRuntime!.invalidate();
|
|
1573
|
+
return result;
|
|
1574
|
+
},
|
|
1575
|
+
mutateSession: async (liveSessionId, request, authenticatedHostClientId) => {
|
|
1576
|
+
const selectedSession = workspaceRegistry.get(
|
|
1577
|
+
request.intent.workspaceName,
|
|
1578
|
+
)?.sessionName;
|
|
1579
|
+
if (!selectedSession) throw new Error("Selected workspace is unavailable");
|
|
1580
|
+
return sessionMutationFence.execute({
|
|
1581
|
+
liveSessionId,
|
|
1582
|
+
sessionName: selectedSession,
|
|
1583
|
+
run: fleetFactsTmuxRunner,
|
|
1584
|
+
mutate: () =>
|
|
1585
|
+
orderedMultiplexerBackend.mutate(
|
|
1586
|
+
request,
|
|
1587
|
+
authenticatedHostClientId,
|
|
1588
|
+
undefined,
|
|
1589
|
+
true,
|
|
1590
|
+
),
|
|
1591
|
+
});
|
|
1592
|
+
},
|
|
1593
|
+
sessionRuntimeRegistry,
|
|
1594
|
+
terminalInventoryRuntime,
|
|
1595
|
+
paneStreamRuntime,
|
|
1596
|
+
dispose: async () => {
|
|
1597
|
+
sessionMonitor?.stop();
|
|
1598
|
+
paneSourceCredentials.dispose();
|
|
1599
|
+
const transportResults = await Promise.allSettled([
|
|
1600
|
+
Promise.resolve().then(() => terminalAttachmentRuntime?.dispose()),
|
|
1601
|
+
Promise.resolve().then(() => paneStreamRuntime!.dispose()),
|
|
1602
|
+
]);
|
|
1603
|
+
const authorityResults = await Promise.allSettled([
|
|
1604
|
+
Promise.resolve().then(() => terminalInventoryRuntime!.dispose()),
|
|
1605
|
+
Promise.resolve().then(() => workspacePaneCreation.dispose()),
|
|
1606
|
+
Promise.resolve().then(() => workspaceOpen.dispose()),
|
|
1607
|
+
Promise.resolve().then(() => workspaceOpenHandoff?.dispose()),
|
|
1608
|
+
Promise.resolve().then(() =>
|
|
1609
|
+
Promise.all([
|
|
1610
|
+
workspacePromotion.dispose(),
|
|
1611
|
+
defaultSessionOpener.dispose(),
|
|
1612
|
+
defaultSessionCreator.dispose(),
|
|
1613
|
+
]).then(() => {}),
|
|
1614
|
+
),
|
|
1615
|
+
Promise.resolve().then(() => appWindowMutation.dispose()),
|
|
1616
|
+
Promise.resolve().then(() => workspaceMultiplexer.dispose()),
|
|
1617
|
+
Promise.resolve().then(() => externalInteractionObserver.dispose()),
|
|
1618
|
+
]);
|
|
1619
|
+
await sessionRuntimeRegistry!.dispose();
|
|
1620
|
+
const failures = [...transportResults, ...authorityResults].flatMap((result) =>
|
|
1621
|
+
result.status === "rejected" ? [result.reason] : [],
|
|
1622
|
+
);
|
|
1623
|
+
if (failures.length)
|
|
1624
|
+
throw new AggregateError(failures, "Default tmux owner retirement failed");
|
|
1625
|
+
},
|
|
1626
|
+
},
|
|
1627
|
+
});
|
|
1457
1628
|
setFleetFactsTmuxRunner(fleetFactsTmuxRunner);
|
|
1458
1629
|
startedServer = await startHttpServer({
|
|
1630
|
+
serverOwners,
|
|
1459
1631
|
sessionName,
|
|
1460
1632
|
requestedPort: port,
|
|
1461
1633
|
bindHostname,
|
|
@@ -1465,6 +1637,13 @@ async function startEmbeddedDaemonGeneration(
|
|
|
1465
1637
|
silent: opts.silent,
|
|
1466
1638
|
readProjectAuth: !sessionless,
|
|
1467
1639
|
daemonIdentity: { productVersion, instanceId, startedAt, environmentId },
|
|
1640
|
+
tmuxServerProof: async () => {
|
|
1641
|
+
const deadline = AbortSignal.timeout(500);
|
|
1642
|
+
return (
|
|
1643
|
+
(await captureTmuxServerProofAsync((args) => fleetFactsTmuxRunner(args, deadline))) ??
|
|
1644
|
+
captureUnboundTmuxSelectorProof(tmuxAuthority)
|
|
1645
|
+
);
|
|
1646
|
+
},
|
|
1468
1647
|
workspacePaneCreationBackend: workspacePaneCreation,
|
|
1469
1648
|
workspaceOpenBackend: workspaceOpen,
|
|
1470
1649
|
workspaceOpenHandoffBackend: workspaceOpenHandoff,
|
|
@@ -1485,6 +1664,7 @@ async function startEmbeddedDaemonGeneration(
|
|
|
1485
1664
|
sessionRuntimeRegistry,
|
|
1486
1665
|
});
|
|
1487
1666
|
} catch (error) {
|
|
1667
|
+
await serverOwners?.dispose();
|
|
1488
1668
|
setFleetFactsTmuxRunner(null);
|
|
1489
1669
|
await Promise.allSettled([
|
|
1490
1670
|
Promise.resolve().then(() => terminalAttachmentRuntime?.dispose()),
|
|
@@ -1493,7 +1673,11 @@ async function startEmbeddedDaemonGeneration(
|
|
|
1493
1673
|
workspacePaneCreation.dispose(),
|
|
1494
1674
|
workspaceOpen.dispose(),
|
|
1495
1675
|
Promise.resolve().then(() => workspaceOpenHandoff?.dispose()),
|
|
1496
|
-
|
|
1676
|
+
Promise.all([
|
|
1677
|
+
workspacePromotion.dispose(),
|
|
1678
|
+
defaultSessionOpener.dispose(),
|
|
1679
|
+
defaultSessionCreator.dispose(),
|
|
1680
|
+
]).then(() => {}),
|
|
1497
1681
|
appWindowMutation.dispose(),
|
|
1498
1682
|
workspaceMultiplexer.dispose(),
|
|
1499
1683
|
externalInteractionObserver.dispose(),
|
|
@@ -1526,6 +1710,7 @@ async function startEmbeddedDaemonGeneration(
|
|
|
1526
1710
|
);
|
|
1527
1711
|
};
|
|
1528
1712
|
const abortStartedServer = async (): Promise<void> => {
|
|
1713
|
+
await serverOwners?.dispose();
|
|
1529
1714
|
setFleetFactsTmuxRunner(null);
|
|
1530
1715
|
const terminalFailures = [
|
|
1531
1716
|
...(await retireTerminalAttachmentTransport(
|
|
@@ -1540,7 +1725,13 @@ async function startEmbeddedDaemonGeneration(
|
|
|
1540
1725
|
const workspaceOpenHandoffDisposal = Promise.resolve().then(() =>
|
|
1541
1726
|
workspaceOpenHandoff?.dispose(),
|
|
1542
1727
|
);
|
|
1543
|
-
const workspacePromotionDisposal = Promise.resolve().then(() =>
|
|
1728
|
+
const workspacePromotionDisposal = Promise.resolve().then(() =>
|
|
1729
|
+
Promise.all([
|
|
1730
|
+
workspacePromotion.dispose(),
|
|
1731
|
+
defaultSessionOpener.dispose(),
|
|
1732
|
+
defaultSessionCreator.dispose(),
|
|
1733
|
+
]).then(() => {}),
|
|
1734
|
+
);
|
|
1544
1735
|
const appWindowMutationDisposal = Promise.resolve().then(() => appWindowMutation.dispose());
|
|
1545
1736
|
const workspaceMultiplexerDisposal = Promise.resolve().then(() =>
|
|
1546
1737
|
workspaceMultiplexer.dispose(),
|
|
@@ -1600,6 +1791,7 @@ async function startEmbeddedDaemonGeneration(
|
|
|
1600
1791
|
environmentId,
|
|
1601
1792
|
bindHostname,
|
|
1602
1793
|
authToken: localBypassToken,
|
|
1794
|
+
tmuxServerProofVersion: 1,
|
|
1603
1795
|
provenance,
|
|
1604
1796
|
},
|
|
1605
1797
|
claim,
|
|
@@ -1658,14 +1850,14 @@ async function startEmbeddedDaemonGeneration(
|
|
|
1658
1850
|
},
|
|
1659
1851
|
});
|
|
1660
1852
|
|
|
1661
|
-
|
|
1853
|
+
sessionMonitor = sessionless
|
|
1662
1854
|
? null
|
|
1663
1855
|
: new DaemonSessionMonitor({
|
|
1664
1856
|
sessionName,
|
|
1665
1857
|
backend: {
|
|
1666
1858
|
inspectSession: async (candidate, signal) => {
|
|
1667
1859
|
try {
|
|
1668
|
-
await
|
|
1860
|
+
await fleetFactsTmuxRunner(["has-session", "-t", candidate], signal);
|
|
1669
1861
|
return "yes";
|
|
1670
1862
|
} catch (error) {
|
|
1671
1863
|
if (signal.aborted) return "unknown";
|
|
@@ -1685,14 +1877,14 @@ async function startEmbeddedDaemonGeneration(
|
|
|
1685
1877
|
},
|
|
1686
1878
|
hasClients: async (signal) => {
|
|
1687
1879
|
try {
|
|
1688
|
-
return (await
|
|
1880
|
+
return (await fleetFactsTmuxRunner(["list-clients"], signal)).length > 0;
|
|
1689
1881
|
} catch {
|
|
1690
1882
|
return null;
|
|
1691
1883
|
}
|
|
1692
1884
|
},
|
|
1693
1885
|
listPanes: async (candidate, signal) => {
|
|
1694
1886
|
try {
|
|
1695
|
-
const raw = await
|
|
1887
|
+
const raw = await fleetFactsTmuxRunner(
|
|
1696
1888
|
[
|
|
1697
1889
|
"list-panes",
|
|
1698
1890
|
"-t",
|
|
@@ -1716,21 +1908,21 @@ async function startEmbeddedDaemonGeneration(
|
|
|
1716
1908
|
},
|
|
1717
1909
|
setPaneOption: async (paneId, option, value, signal) => {
|
|
1718
1910
|
try {
|
|
1719
|
-
await
|
|
1911
|
+
await fleetFactsTmuxRunner(["set-option", "-pt", paneId, option, value], signal);
|
|
1720
1912
|
} catch (error) {
|
|
1721
1913
|
if (!isConfirmedMissingTmuxTarget(error)) throw error;
|
|
1722
1914
|
}
|
|
1723
1915
|
},
|
|
1724
1916
|
setPaneTitle: async (paneId, title, signal) => {
|
|
1725
1917
|
try {
|
|
1726
|
-
await
|
|
1918
|
+
await fleetFactsTmuxRunner(["select-pane", "-t", paneId, "-T", title], signal);
|
|
1727
1919
|
} catch (error) {
|
|
1728
1920
|
if (!isConfirmedMissingTmuxTarget(error)) throw error;
|
|
1729
1921
|
}
|
|
1730
1922
|
},
|
|
1731
1923
|
refreshClients: async (signal) => {
|
|
1732
1924
|
try {
|
|
1733
|
-
await
|
|
1925
|
+
await fleetFactsTmuxRunner(["refresh-client", "-S"], signal);
|
|
1734
1926
|
} catch (error) {
|
|
1735
1927
|
if (!isConfirmedMissingTmuxTarget(error)) throw error;
|
|
1736
1928
|
}
|
|
@@ -1744,7 +1936,21 @@ async function startEmbeddedDaemonGeneration(
|
|
|
1744
1936
|
const wsUrl = canonicalDaemonUrl("ws", bindHostname, port, "/ws/events");
|
|
1745
1937
|
|
|
1746
1938
|
const handle: EmbeddedDaemonHandle = {
|
|
1747
|
-
tmuxAuthorityReplaced
|
|
1939
|
+
tmuxAuthorityReplaced: async () => {
|
|
1940
|
+
if (serverOwners?.defaultRetired) return false;
|
|
1941
|
+
const replaced = await tmuxAuthorityReplaced();
|
|
1942
|
+
// A native server replacement cannot restart unrelated server owners.
|
|
1943
|
+
// Legacy default-only callers retain the established restart adapter.
|
|
1944
|
+
if (
|
|
1945
|
+
replaced &&
|
|
1946
|
+
serverOwners &&
|
|
1947
|
+
(serverOwners.owners.list().length > 1 || serverOwners.defaultRetired)
|
|
1948
|
+
) {
|
|
1949
|
+
await serverOwners.owners.refresh();
|
|
1950
|
+
return false;
|
|
1951
|
+
}
|
|
1952
|
+
return replaced;
|
|
1953
|
+
},
|
|
1748
1954
|
instanceId,
|
|
1749
1955
|
pid: process.pid,
|
|
1750
1956
|
port,
|
|
@@ -1769,6 +1975,7 @@ async function startEmbeddedDaemonGeneration(
|
|
|
1769
1975
|
await capture(() => setActivationBackend(null));
|
|
1770
1976
|
await capture(() => sessionMonitor?.stop());
|
|
1771
1977
|
paneSourceCredentials.dispose();
|
|
1978
|
+
await capture(() => serverOwners?.dispose());
|
|
1772
1979
|
|
|
1773
1980
|
// Retire direct-ticket admission, live PTYs, and the direct upgrade
|
|
1774
1981
|
// listener before touching the legacy WS or HTTP surfaces.
|
|
@@ -1783,7 +1990,13 @@ async function startEmbeddedDaemonGeneration(
|
|
|
1783
1990
|
await capture(() => workspacePaneCreation.dispose());
|
|
1784
1991
|
await capture(() => workspaceOpen.dispose());
|
|
1785
1992
|
await capture(() => workspaceOpenHandoff?.dispose());
|
|
1786
|
-
await capture(() =>
|
|
1993
|
+
await capture(() =>
|
|
1994
|
+
Promise.all([
|
|
1995
|
+
workspacePromotion.dispose(),
|
|
1996
|
+
defaultSessionOpener.dispose(),
|
|
1997
|
+
defaultSessionCreator.dispose(),
|
|
1998
|
+
]).then(() => {}),
|
|
1999
|
+
);
|
|
1787
2000
|
await capture(() => appWindowMutation.dispose());
|
|
1788
2001
|
await capture(() => workspaceMultiplexer.dispose());
|
|
1789
2002
|
await capture(() => externalInteractionObserver.dispose());
|