tmux-ide 2.9.2 → 2.9.4
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/LICENSE +1 -1
- package/README.md +121 -140
- package/bin/cli.js +2457 -727
- package/package.json +23 -8
- package/packages/contracts/src/desktop-host.ts +3 -0
- package/packages/contracts/src/saved-machines.ts +19 -0
- package/packages/contracts/src/terminal-replica.ts +1 -1
- package/packages/core/package.json +3 -2
- package/packages/core/src/terminal-delivery.ts +51 -3
- package/packages/core/src/terminal-fnv64-wasm.ts +4 -3
- package/packages/core/src/terminal-replica-hash-cache.ts +129 -31
- package/packages/core/src/terminal-replica-owned-row.ts +27 -0
- package/packages/core/src/terminal-replica.ts +13 -28
- package/packages/daemon/dist/command-center/daemon-fleet-facts-observer.js +96 -10
- package/packages/daemon/dist/command-center/resources/saved-machine-route.js +40 -1
- package/packages/daemon/dist/command-center/ws-events.js +5 -24
- package/packages/daemon/dist/lib/canonical-daemon-bootstrap.js +8 -0
- package/packages/daemon/dist/lib/canonical-daemon.js +28 -2
- package/packages/daemon/dist/lib/daemon-embed.js +1 -1
- package/packages/daemon/dist/lib/daemon-service-manager.js +122 -0
- package/packages/daemon/dist/lib/daemon-service-plan.js +127 -0
- package/packages/daemon/dist/lib/daemon-service.js +259 -0
- package/packages/daemon/dist/lib/install-origin.js +2 -0
- package/packages/daemon/dist/lib/local-fleet-request.js +9 -3
- package/packages/daemon/dist/lib/log.js +6 -10
- package/packages/daemon/dist/lib/managed-installer-update.js +67 -0
- package/packages/daemon/dist/lib/{tui-download-lock.js → private-operation-lock.js} +11 -11
- package/packages/daemon/dist/lib/remote-daemon-info.js +3 -2
- package/packages/daemon/dist/lib/remote-daemon-lifecycle.js +4 -4
- package/packages/daemon/dist/lib/remote-tmux-command.js +10 -0
- package/packages/daemon/dist/lib/runtime-namespace.js +28 -16
- package/packages/daemon/dist/lib/saved-machines.js +40 -2
- package/packages/daemon/dist/lib/ssh-daemon-transport.js +24 -9
- package/packages/daemon/dist/lib/tmux-server-owner.js +1 -1
- package/packages/daemon/dist/lib/tmux-server-registration.js +21 -3
- package/packages/daemon/dist/lib/tui-binary.js +2 -2
- package/packages/daemon/dist/lib/update.js +18 -0
- package/packages/daemon/dist/lib/workspace-multiplexer-verbs.js +24 -1
- package/packages/daemon/dist/machines.js +40 -4
- package/packages/daemon/dist/native/TmuxIdeNotifier.app/Contents/Info.plist +2 -2
- package/packages/daemon/dist/native/TmuxIdeNotifier.app/Contents/MacOS/tmux-ide-notifier +0 -0
- package/packages/daemon/dist/native/TmuxIdeNotifier.app/Contents/Resources/Assets.car +0 -0
- package/packages/daemon/dist/native/TmuxIdeNotifier.app/Contents/_CodeSignature/CodeResources +2 -2
- package/packages/daemon/dist/terminal/attachments/direct-websocket.js +4 -1
- package/packages/daemon/dist/terminal/attachments/native-runtime.js +22 -13
- package/packages/daemon/dist/terminal/mirror/mirror-service.js +101 -3
- package/packages/daemon/dist/terminal/mirror/registered-window-guard.js +62 -0
- package/packages/daemon/dist/terminal/mirror/session-channel.js +75 -4
- package/packages/daemon/dist/terminal/mirror/shared-window-index.js +45 -0
- package/packages/daemon/dist/terminal/pane-stream/pane-stream-websocket.js +11 -1
- package/packages/daemon/dist/terminal/session-runtime/multiplexer-backend.js +1 -0
- package/packages/daemon/dist/terminal/session-runtime/registry.js +56 -7
- package/packages/daemon/dist/terminal/session-runtime/semantic-mutation-executor.js +3 -1
- package/packages/daemon/dist/tui/integrations/claude-agent-teams.js +264 -0
- package/packages/daemon/dist/tui/mirror/dialog-model.js +2 -35
- package/packages/daemon/dist/tui/mirror/runtime/application-daemon-authority-owner.js +8 -0
- package/packages/daemon/dist/tui/mirror/runtime/application-home-fleet.js +20 -2
- package/packages/daemon/dist/tui/mirror/runtime/application-machine-agents.js +7 -1
- package/packages/daemon/dist/tui/mirror/runtime/application-machine-authority.js +59 -9
- package/packages/daemon/dist/tui/mirror/runtime/application-machine-navigation.js +27 -19
- package/packages/daemon/dist/tui/mirror/runtime/application-machine-sidebar.jsx +23 -18
- package/packages/daemon/dist/tui/mirror/runtime/application-machine-startup.js +31 -2
- package/packages/daemon/dist/tui/mirror/runtime/application-palette-search-owner.js +7 -3
- package/packages/daemon/dist/tui/mirror/runtime/application-performance-log.js +3 -0
- package/packages/daemon/dist/tui/mirror/runtime/application-terminal-input-ingress.js +146 -2
- package/packages/daemon/dist/tui/mirror/runtime/application-terminal-interaction-controller.js +201 -50
- package/packages/daemon/dist/tui/mirror/runtime/bounded-performance-record-writer.js +50 -10
- package/packages/daemon/dist/tui/mirror/runtime/terminal-fast-lane-renderer-adapter.js +6 -5
- package/packages/daemon/dist/tui/mirror/runtime/terminal-pane-input-router.js +3 -0
- package/packages/daemon/dist/tui/mirror/runtime/workspace-terminal-fast-lane.js +8 -2
- package/packages/daemon/dist/tui/mirror/terminal-text.js +35 -0
- package/packages/daemon/dist/tui/mirror/workspace/connection-feedback.js +5 -3
- package/packages/daemon/src/command-center/daemon-fleet-facts-observer.ts +100 -10
- package/packages/daemon/src/command-center/resources/saved-machine-route.ts +48 -1
- package/packages/daemon/src/command-center/ws-events.ts +5 -25
- package/packages/daemon/src/lib/canonical-daemon-bootstrap.ts +12 -0
- package/packages/daemon/src/lib/canonical-daemon.ts +44 -2
- package/packages/daemon/src/lib/daemon-embed.ts +1 -0
- package/packages/daemon/src/lib/daemon-service-manager.ts +152 -0
- package/packages/daemon/src/lib/daemon-service-plan.ts +153 -0
- package/packages/daemon/src/lib/daemon-service.ts +301 -0
- package/packages/daemon/src/lib/install-origin.ts +5 -0
- package/packages/daemon/src/lib/local-fleet-request.ts +19 -3
- package/packages/daemon/src/lib/log.ts +13 -9
- package/packages/daemon/src/lib/managed-installer-update.ts +79 -0
- package/packages/daemon/src/lib/{tui-download-lock.ts → private-operation-lock.ts} +15 -11
- package/packages/daemon/src/lib/remote-daemon-info.ts +3 -3
- package/packages/daemon/src/lib/remote-daemon-lifecycle.ts +4 -4
- package/packages/daemon/src/lib/remote-tmux-command.ts +12 -0
- package/packages/daemon/src/lib/runtime-namespace.ts +27 -18
- package/packages/daemon/src/lib/saved-machines.ts +40 -1
- package/packages/daemon/src/lib/ssh-daemon-transport.ts +25 -7
- package/packages/daemon/src/lib/tmux-server-owner.ts +1 -0
- package/packages/daemon/src/lib/tmux-server-registration.ts +21 -3
- package/packages/daemon/src/lib/tui-binary.ts +2 -2
- package/packages/daemon/src/lib/update.ts +24 -0
- package/packages/daemon/src/lib/workspace-multiplexer-verbs.ts +22 -0
- package/packages/daemon/src/machines.ts +53 -5
- package/packages/daemon/src/terminal/attachments/direct-websocket.ts +8 -2
- package/packages/daemon/src/terminal/attachments/native-runtime.ts +28 -13
- package/packages/daemon/src/terminal/mirror/mirror-service.ts +105 -3
- package/packages/daemon/src/terminal/mirror/registered-window-guard.ts +66 -0
- package/packages/daemon/src/terminal/mirror/session-channel.ts +92 -4
- package/packages/daemon/src/terminal/mirror/shared-window-index.ts +42 -0
- package/packages/daemon/src/terminal/pane-stream/pane-stream-websocket.ts +12 -1
- package/packages/daemon/src/terminal/session-runtime/multiplexer-backend.ts +2 -0
- package/packages/daemon/src/terminal/session-runtime/registry.ts +70 -8
- package/packages/daemon/src/terminal/session-runtime/semantic-mutation-executor.ts +3 -1
- package/packages/daemon/src/tui/integrations/claude-agent-teams.ts +334 -0
- package/packages/daemon/src/tui/mirror/dialog-model.ts +2 -32
- package/packages/daemon/src/tui/mirror/runtime/application-daemon-authority-owner.ts +8 -0
- package/packages/daemon/src/tui/mirror/runtime/application-home-fleet.ts +19 -2
- package/packages/daemon/src/tui/mirror/runtime/application-machine-agents.ts +6 -1
- package/packages/daemon/src/tui/mirror/runtime/application-machine-authority.ts +60 -11
- package/packages/daemon/src/tui/mirror/runtime/application-machine-navigation.ts +39 -33
- package/packages/daemon/src/tui/mirror/runtime/application-machine-sidebar.tsx +31 -23
- package/packages/daemon/src/tui/mirror/runtime/application-machine-startup.ts +38 -2
- package/packages/daemon/src/tui/mirror/runtime/application-palette-search-owner.ts +7 -4
- package/packages/daemon/src/tui/mirror/runtime/application-performance-log.ts +3 -0
- package/packages/daemon/src/tui/mirror/runtime/application-root-v2.tsx +1 -1
- package/packages/daemon/src/tui/mirror/runtime/application-shell-view.tsx +47 -46
- package/packages/daemon/src/tui/mirror/runtime/application-terminal-input-ingress.ts +165 -2
- package/packages/daemon/src/tui/mirror/runtime/application-terminal-interaction-controller.ts +207 -53
- package/packages/daemon/src/tui/mirror/runtime/bounded-performance-record-writer.ts +49 -9
- package/packages/daemon/src/tui/mirror/runtime/terminal-fast-lane-renderer-adapter.ts +6 -5
- package/packages/daemon/src/tui/mirror/runtime/terminal-pane-input-router.ts +4 -0
- package/packages/daemon/src/tui/mirror/runtime/workspace-terminal-fast-lane.ts +8 -3
- package/packages/daemon/src/tui/mirror/terminal-text.ts +32 -0
- package/packages/daemon/src/tui/mirror/workspace/connection-feedback.ts +6 -3
- package/packages/daemon-client/src/fleet-connection-status.ts +10 -1
- package/packages/daemon-client/src/workspace-client.ts +4 -1
- package/skill/SKILL.md +30 -30
- package/packages/contracts/src/__tests__/actions-contract.test.ts +0 -119
- package/packages/contracts/src/__tests__/agent-graph-overlay.test.ts +0 -428
- package/packages/contracts/src/__tests__/app-window-mutation.test.ts +0 -51
- package/packages/contracts/src/__tests__/app-window-state.test.ts +0 -34
- package/packages/contracts/src/__tests__/application-shell.test.ts +0 -645
- package/packages/contracts/src/__tests__/automation-operations.test.ts +0 -78
- package/packages/contracts/src/__tests__/causal-cell.test.ts +0 -47
- package/packages/contracts/src/__tests__/client-view-state.test.ts +0 -115
- package/packages/contracts/src/__tests__/cohesion-fixture.test.ts +0 -106
- package/packages/contracts/src/__tests__/commands.test.ts +0 -86
- package/packages/contracts/src/__tests__/control.test.ts +0 -154
- package/packages/contracts/src/__tests__/daemon-events.test.ts +0 -405
- package/packages/contracts/src/__tests__/daemon-resources.test.ts +0 -143
- package/packages/contracts/src/__tests__/daemon-wire.test.ts +0 -149
- package/packages/contracts/src/__tests__/desktop-host.test.ts +0 -269
- package/packages/contracts/src/__tests__/desktop-missions.test.ts +0 -215
- package/packages/contracts/src/__tests__/experience-conformance.test.ts +0 -153
- package/packages/contracts/src/__tests__/experience-kernel-boundary.test.ts +0 -113
- package/packages/contracts/src/__tests__/experience-shell.test.ts +0 -65
- package/packages/contracts/src/__tests__/fixtures/daemon-wire-v2.json +0 -35
- package/packages/contracts/src/__tests__/fixtures/daemon-wire-v3.json +0 -35
- package/packages/contracts/src/__tests__/fixtures/daemon-wire-v4.json +0 -35
- package/packages/contracts/src/__tests__/fixtures/scoped-receipt.ts +0 -62
- package/packages/contracts/src/__tests__/fleet-agent-graph.test.ts +0 -231
- package/packages/contracts/src/__tests__/fleet-catalog.test.ts +0 -270
- package/packages/contracts/src/__tests__/fleet-lifecycle.test.ts +0 -62
- package/packages/contracts/src/__tests__/focus-overlay.test.ts +0 -110
- package/packages/contracts/src/__tests__/ide-config.test.ts +0 -64
- package/packages/contracts/src/__tests__/interaction-evidence.test.ts +0 -288
- package/packages/contracts/src/__tests__/interaction-receipt-v2.test.ts +0 -72
- package/packages/contracts/src/__tests__/issue-error.test.ts +0 -78
- package/packages/contracts/src/__tests__/mission-projections.test.ts +0 -186
- package/packages/contracts/src/__tests__/missions.test.ts +0 -272
- package/packages/contracts/src/__tests__/multiplexer-verbs.test.ts +0 -242
- package/packages/contracts/src/__tests__/pane-appearance.test.ts +0 -146
- package/packages/contracts/src/__tests__/pane-read-result.test.ts +0 -55
- package/packages/contracts/src/__tests__/pane-stream.test.ts +0 -536
- package/packages/contracts/src/__tests__/pane-widget-marker.test.ts +0 -327
- package/packages/contracts/src/__tests__/performance-metrics.test.ts +0 -73
- package/packages/contracts/src/__tests__/performance-qualification.test.ts +0 -137
- package/packages/contracts/src/__tests__/rich-card-widget.test.ts +0 -29
- package/packages/contracts/src/__tests__/session-runtime.test.ts +0 -512
- package/packages/contracts/src/__tests__/startup-readiness.test.ts +0 -409
- package/packages/contracts/src/__tests__/terminal-attachment-stream.test.ts +0 -72
- package/packages/contracts/src/__tests__/terminal-attachments.test.ts +0 -329
- package/packages/contracts/src/__tests__/terminal-delivery.test.ts +0 -88
- package/packages/contracts/src/__tests__/terminal-runtime-inventory.test.ts +0 -68
- package/packages/contracts/src/__tests__/terminals.test.ts +0 -87
- package/packages/contracts/src/__tests__/tmux-server-scope.test.ts +0 -166
- package/packages/contracts/src/__tests__/transport-contract-loading.test.ts +0 -91
- package/packages/contracts/src/__tests__/visual-tokens.test.ts +0 -224
- package/packages/contracts/src/__tests__/window-links.test.ts +0 -243
- package/packages/contracts/src/__tests__/workspace-changes-resource.test.ts +0 -317
- package/packages/contracts/src/__tests__/workspace-changes-view.test.ts +0 -122
- package/packages/contracts/src/__tests__/workspace-config.test.ts +0 -294
- package/packages/contracts/src/__tests__/workspace-files-resource.test.ts +0 -261
- package/packages/contracts/src/__tests__/workspace-files-tree.test.ts +0 -147
- package/packages/contracts/src/__tests__/workspace-pane-creation.test.ts +0 -249
- package/packages/contracts/src/__tests__/workspace-promotion.test.ts +0 -94
- package/packages/contracts/src/__tests__/workspace-resource-identity.test.ts +0 -90
- package/packages/contracts/src/daemon-resource-request.test.ts +0 -192
- package/packages/contracts/src/native-operation-identity.test.ts +0 -23
- package/packages/contracts/src/workspace-admission.test.ts +0 -21
- package/packages/contracts/src/workspace-catalog-resource.test.ts +0 -146
- package/packages/core/src/agent-provisioning.test.ts +0 -42
- package/packages/core/src/application-shell-session.test.ts +0 -105
- package/packages/core/src/interaction-evidence.test.ts +0 -134
- package/packages/core/src/interaction-flow.test.ts +0 -66
- package/packages/core/src/interaction-receipts.test.ts +0 -671
- package/packages/core/src/navigator.test.ts +0 -34
- package/packages/core/src/optimistic-projection-conformance.test.ts +0 -75
- package/packages/core/src/optimistic-projection.test.ts +0 -118
- package/packages/core/src/performance-metrics.test.ts +0 -121
- package/packages/core/src/performance-qualification.test.ts +0 -283
- package/packages/core/src/saved-machines.test.ts +0 -80
- package/packages/core/src/terminal-compact-cold.test.ts +0 -87
- package/packages/core/src/terminal-conformance.test.ts +0 -48
- package/packages/core/src/terminal-delivery-cache-lifetime.test.ts +0 -167
- package/packages/core/src/terminal-delivery-encode-cooperative.test.ts +0 -140
- package/packages/core/src/terminal-delivery-representation-hash.test.ts +0 -77
- package/packages/core/src/terminal-delivery.test.ts +0 -1471
- package/packages/core/src/terminal-fnv64-wasm.test.ts +0 -61
- package/packages/core/src/terminal-replica-cold.test.ts +0 -31
- package/packages/core/src/terminal-replica-cooperative.test.ts +0 -170
- package/packages/core/src/terminal-replica-hash-cache.test.ts +0 -283
- package/packages/core/src/terminal-replica.test.ts +0 -347
- package/packages/core/src/workspace-selection.test.ts +0 -63
- package/packages/daemon/dist/__tests__/support.js +0 -33
- package/packages/daemon/dist/lib/__tests__/fixtures/workspace-state-writer.js +0 -58
- package/packages/daemon/dist/lib/__tests__/installed-recovery-fixture.js +0 -400
- package/packages/daemon/dist/terminal/__tests__/MockPtyAdapter.js +0 -182
- package/packages/daemon/dist/terminal/mirror/__tests__/scripted-channel.js +0 -98
- package/packages/daemon/dist/terminal/mirror/__tests__/simulated-channel.js +0 -156
- package/packages/daemon/src/tui/mirror/__snapshots__/activity-surface-renderer.test.tsx.snap +0 -42
- package/packages/daemon/src/tui/mirror/__snapshots__/changes-terminal-surface-renderer.test.tsx.snap +0 -267
- package/packages/daemon/src/tui/mirror/__snapshots__/home-files-surface-renderer.test.tsx.snap +0 -267
- package/packages/daemon/src/tui/mirror/__snapshots__/missions-surface-renderer.test.tsx.snap +0 -134
- package/packages/daemon/src/tui/mirror/__snapshots__/recipes-gallery-renderer.test.tsx.snap +0 -141
- package/packages/daemon/src/tui/mirror/__snapshots__/shell-chrome-renderer.test.tsx.snap +0 -134
- package/packages/daemon/src/tui/mirror/runtime/__snapshots__/application-shell-view-renderer.test.tsx.snap +0 -87
- package/packages/daemon/src/tui/mirror/workspace/__snapshots__/agent-terminal-canvas-renderer.test.tsx.snap +0 -348
- package/packages/daemon/src/tui/mirror/workspace/__snapshots__/application-shell-renderer.test.tsx.snap +0 -134
- package/packages/daemon/src/tui/mirror/workspace/__snapshots__/command-palette-surface-renderer.test.tsx.snap +0 -255
- package/packages/daemon/src/tui/mirror/workspace/__snapshots__/pane-frame-renderer.test.tsx.snap +0 -525
- package/packages/daemon/src/tui/mirror/workspace/__snapshots__/terminal-pane-header-polish-renderer.test.tsx.snap +0 -31
- package/packages/daemon/src/tui/mirror/workspace/__snapshots__/workbench-shell-renderer.test.tsx.snap +0 -134
- package/packages/daemon-client/src/application-shell-session.test.ts +0 -196
- package/packages/daemon-client/src/automation-client.test.ts +0 -214
- package/packages/daemon-client/src/bootstrap-coordinator.test.ts +0 -145
- package/packages/daemon-client/src/connection-supervisor.test.ts +0 -109
- package/packages/daemon-client/src/direct-application-shell-transport.test.ts +0 -941
- package/packages/daemon-client/src/first-latest-coordinator.test.ts +0 -175
- package/packages/daemon-client/src/fleet-dial-scheduler.test.ts +0 -114
- package/packages/daemon-client/src/fleet-environments.test.ts +0 -40
- package/packages/daemon-client/src/generation-bound-store-timers.test.ts +0 -74
- package/packages/daemon-client/src/owner-action-client.test.ts +0 -245
- package/packages/daemon-client/src/pane-stream-client.test.ts +0 -2841
- package/packages/daemon-client/src/pane-stream-clock-calibration.test.ts +0 -207
- package/packages/daemon-client/src/pane-stream-loopback-benchmark.test.ts +0 -51
- package/packages/daemon-client/src/push-resource-session.test.ts +0 -509
- package/packages/daemon-client/src/resource-replica.test.ts +0 -186
- package/packages/daemon-client/src/runtime-resource-ledger.test.ts +0 -18
- package/packages/daemon-client/src/scoped-tmux-server-transport.test.ts +0 -114
- package/packages/daemon-client/src/terminal-fast-lane.test.ts +0 -835
- package/packages/daemon-client/src/tmux-server-client.test.ts +0 -279
- package/packages/daemon-client/src/tmux-server-interaction-events.test.ts +0 -230
- package/packages/daemon-client/src/workspace-catalog-v2.test.ts +0 -109
- package/packages/daemon-client/src/workspace-client-boundaries.test.ts +0 -59
- package/packages/daemon-client/src/workspace-client-operations.test.ts +0 -96
- package/packages/daemon-client/src/workspace-client.test.ts +0 -2912
- package/packages/daemon-client/src/workspace-event-supervisor.test.ts +0 -1086
- package/packages/daemon-client/src/workspace-pane-client.test.ts +0 -80
- package/packages/presentation/src/presentation-contract.test.ts +0 -63
- package/packages/tmux-bridge/src/runner.test.ts +0 -614
- package/packages/tmux-bridge/src/targeting.test.ts +0 -107
|
@@ -41,9 +41,9 @@ export interface ApplicationMachineAuthorityManagerDependencies {
|
|
|
41
41
|
}
|
|
42
42
|
interface Machine {
|
|
43
43
|
readonly id: string;
|
|
44
|
-
|
|
44
|
+
label: string;
|
|
45
45
|
readonly kind: "local" | "ssh";
|
|
46
|
-
|
|
46
|
+
profile?: SavedMachine;
|
|
47
47
|
owner: Owner;
|
|
48
48
|
readonly handle: ApplicationMachineAuthorityHandle;
|
|
49
49
|
readonly listeners: Set<GenerationListener>;
|
|
@@ -51,6 +51,7 @@ interface Machine {
|
|
|
51
51
|
stopObserver: (() => void) | null;
|
|
52
52
|
observingOwner: Owner | null;
|
|
53
53
|
stopStatus: (() => void) | null;
|
|
54
|
+
retired: boolean;
|
|
54
55
|
}
|
|
55
56
|
|
|
56
57
|
/** Owns independent transport lifetimes; selecting a machine changes only the active route. */
|
|
@@ -67,6 +68,7 @@ export function createApplicationMachineAuthorityManager(
|
|
|
67
68
|
let selectedId: string = LOCAL_MACHINE_ID;
|
|
68
69
|
let selectedEpoch = 0;
|
|
69
70
|
let disposed = false;
|
|
71
|
+
let stopProfiles: (() => void) | null = null;
|
|
70
72
|
const safe = (callback: () => void) => {
|
|
71
73
|
try {
|
|
72
74
|
callback();
|
|
@@ -81,7 +83,7 @@ export function createApplicationMachineAuthorityManager(
|
|
|
81
83
|
for (const listener of selectedObservers) safe(() => listener(generation));
|
|
82
84
|
};
|
|
83
85
|
const changed = (machine: Machine, generation: string | null) => {
|
|
84
|
-
if (disposed) return;
|
|
86
|
+
if (disposed || machine.retired) return;
|
|
85
87
|
machine.epoch++;
|
|
86
88
|
for (const listener of machine.listeners) safe(() => listener(generation));
|
|
87
89
|
if (machine.id === selectedId) {
|
|
@@ -99,7 +101,7 @@ export function createApplicationMachineAuthorityManager(
|
|
|
99
101
|
})
|
|
100
102
|
.then(
|
|
101
103
|
(stop) => {
|
|
102
|
-
if (disposed || machine.owner !== owner) stop();
|
|
104
|
+
if (disposed || machine.retired || machine.owner !== owner) stop();
|
|
103
105
|
else machine.stopObserver = stop;
|
|
104
106
|
},
|
|
105
107
|
() => {
|
|
@@ -127,25 +129,30 @@ export function createApplicationMachineAuthorityManager(
|
|
|
127
129
|
stopObserver: null,
|
|
128
130
|
observingOwner: null,
|
|
129
131
|
stopStatus: null,
|
|
132
|
+
retired: false,
|
|
130
133
|
} as Machine;
|
|
131
134
|
const handle: ApplicationMachineAuthorityHandle = Object.freeze({
|
|
132
135
|
id,
|
|
133
|
-
label
|
|
136
|
+
get label() {
|
|
137
|
+
return machine.label;
|
|
138
|
+
},
|
|
134
139
|
kind: machine.kind,
|
|
135
140
|
ready,
|
|
136
|
-
read: () => (disposed ? null : machine.owner.read()),
|
|
141
|
+
read: () => (disposed || machine.retired ? null : machine.owner.read()),
|
|
137
142
|
isAlive: (info: CanonicalDaemonInfo) =>
|
|
138
|
-
disposed ? Promise.resolve(false) : machine.owner.isAlive(info),
|
|
143
|
+
disposed || machine.retired ? Promise.resolve(false) : machine.owner.isAlive(info),
|
|
139
144
|
endpoint: () =>
|
|
140
145
|
Object.freeze({
|
|
141
146
|
...machine.owner.endpoint(),
|
|
142
147
|
kind: machine.kind,
|
|
143
|
-
label: profile ? label : null,
|
|
148
|
+
label: machine.profile ? machine.label : null,
|
|
144
149
|
epoch: machine.epoch,
|
|
145
|
-
...(disposed
|
|
150
|
+
...(disposed || machine.retired
|
|
151
|
+
? { state: "disconnected" as const, remote: null, localBaseUrl: null }
|
|
152
|
+
: {}),
|
|
146
153
|
}),
|
|
147
154
|
observe: async (listener: GenerationListener) => {
|
|
148
|
-
if (disposed) return () => {};
|
|
155
|
+
if (disposed || machine.retired) return () => {};
|
|
149
156
|
if (machine.kind === "local") observe(machine, machine.owner);
|
|
150
157
|
listeners.add(listener);
|
|
151
158
|
return () => {
|
|
@@ -166,7 +173,7 @@ export function createApplicationMachineAuthorityManager(
|
|
|
166
173
|
observe(machine, owner);
|
|
167
174
|
publish();
|
|
168
175
|
void initializing.then(
|
|
169
|
-
() => settle(!disposed),
|
|
176
|
+
() => settle(!disposed && !machine.retired),
|
|
170
177
|
() => settle(false),
|
|
171
178
|
);
|
|
172
179
|
return machine;
|
|
@@ -255,6 +262,46 @@ export function createApplicationMachineAuthorityManager(
|
|
|
255
262
|
SavedMachineRegistrySchema.parse({ version: 1, machines: profiles });
|
|
256
263
|
for (const profile of profiles) if (profile.enabled) manager.add(profile);
|
|
257
264
|
},
|
|
265
|
+
reconcile(profiles: readonly SavedMachine[]): void {
|
|
266
|
+
if (disposed) return;
|
|
267
|
+
const next = SavedMachineRegistrySchema.parse({ version: 1, machines: profiles });
|
|
268
|
+
const previousSelection = selectedId;
|
|
269
|
+
for (const machine of [...machines.values()]) {
|
|
270
|
+
if (!machine.profile) continue;
|
|
271
|
+
const profile = next.machines.find(
|
|
272
|
+
(candidate) => candidate.id === machine.id && candidate.enabled,
|
|
273
|
+
);
|
|
274
|
+
if (
|
|
275
|
+
profile &&
|
|
276
|
+
profile.sshTarget === machine.profile.sshTarget &&
|
|
277
|
+
profile.expectedEnvironmentId === machine.profile.expectedEnvironmentId
|
|
278
|
+
) {
|
|
279
|
+
// Labels are presentation metadata, not transport identity. Preserve
|
|
280
|
+
// the connected owner and every consumer holding its stable handle.
|
|
281
|
+
machine.label = profile.label;
|
|
282
|
+
machine.profile = profile;
|
|
283
|
+
continue;
|
|
284
|
+
}
|
|
285
|
+
if (selectedId === machine.id) manager.select(LOCAL_MACHINE_ID);
|
|
286
|
+
machine.retired = true;
|
|
287
|
+
machine.stopStatus?.();
|
|
288
|
+
machine.stopObserver?.();
|
|
289
|
+
for (const listener of machine.listeners) safe(() => listener(null));
|
|
290
|
+
machine.owner.dispose();
|
|
291
|
+
machine.listeners.clear();
|
|
292
|
+
machines.delete(machine.id);
|
|
293
|
+
}
|
|
294
|
+
for (const profile of next.machines) if (profile.enabled) manager.add(profile);
|
|
295
|
+
if (machines.has(previousSelection)) manager.select(previousSelection);
|
|
296
|
+
publish();
|
|
297
|
+
},
|
|
298
|
+
followProfiles(
|
|
299
|
+
subscribe: (onChange: (profiles: readonly SavedMachine[]) => void) => () => void,
|
|
300
|
+
): void {
|
|
301
|
+
if (disposed) return;
|
|
302
|
+
stopProfiles?.();
|
|
303
|
+
stopProfiles = subscribe(manager.reconcile);
|
|
304
|
+
},
|
|
258
305
|
read: (): CanonicalDaemonInfo | null => machines.get(selectedId)?.handle.read() ?? null,
|
|
259
306
|
isAlive: (info: CanonicalDaemonInfo): Promise<boolean> =>
|
|
260
307
|
machines.get(selectedId)?.handle.isAlive(info) ?? Promise.resolve(false),
|
|
@@ -272,6 +319,8 @@ export function createApplicationMachineAuthorityManager(
|
|
|
272
319
|
dispose(): void {
|
|
273
320
|
if (disposed) return;
|
|
274
321
|
disposed = true;
|
|
322
|
+
stopProfiles?.();
|
|
323
|
+
stopProfiles = null;
|
|
275
324
|
lifetime.abort();
|
|
276
325
|
selectedEpoch++;
|
|
277
326
|
selectedGeneration(null);
|
|
@@ -157,7 +157,10 @@ export function createApplicationMachineNavigation(options: {
|
|
|
157
157
|
return false;
|
|
158
158
|
}
|
|
159
159
|
const selected = candidates[0]!;
|
|
160
|
-
const sameSelection =
|
|
160
|
+
const sameSelection =
|
|
161
|
+
manager.snapshot().selectedMachineId === id &&
|
|
162
|
+
activeSessionKey() === selected.id &&
|
|
163
|
+
options.sessionName() === name;
|
|
161
164
|
setActiveSessionKey(selected.id);
|
|
162
165
|
expectedLiveSessionId = selected.liveSessionId;
|
|
163
166
|
server = selected.server;
|
|
@@ -269,25 +272,27 @@ export function createApplicationMachineNavigation(options: {
|
|
|
269
272
|
for (const tab of tabs.snapshot().tabs) tabs.observe(tab.key, tabAgents(tab));
|
|
270
273
|
});
|
|
271
274
|
const sidebar: ApplicationMachineSidebarModel = {
|
|
272
|
-
groups: () =>
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
275
|
+
groups: () => {
|
|
276
|
+
const groupsById = new Map(agentGroups().map((group) => [group.machineId, group]));
|
|
277
|
+
return snapshot().groups.map((group) => {
|
|
278
|
+
// Read once per projection: local authority reads validate the record on disk.
|
|
279
|
+
// The next projection (and action admission) still observes replacement immediately.
|
|
280
|
+
const instanceId = manager.getMachine(group.id)?.read()?.instanceId;
|
|
281
|
+
const defaultSessions = group.sessions.filter(
|
|
282
|
+
(session) => !session.server || session.server.generation === instanceId,
|
|
283
|
+
);
|
|
284
|
+
const agents = defaultSessions.length ? groupsById.get(group.id) : undefined;
|
|
285
|
+
return {
|
|
286
|
+
...group,
|
|
287
|
+
agentsAvailable: agents?.available ?? false,
|
|
288
|
+
agents: (agents?.agents ?? []).map((agent) => ({
|
|
289
|
+
...agent,
|
|
290
|
+
server: defaultSessions.find((session) => session.liveSessionId === agent.liveSessionId)
|
|
291
|
+
?.server,
|
|
292
|
+
})),
|
|
293
|
+
};
|
|
294
|
+
});
|
|
295
|
+
},
|
|
291
296
|
tabs: () => {
|
|
292
297
|
tabRevision();
|
|
293
298
|
const value = tabs.snapshot();
|
|
@@ -479,7 +484,10 @@ export function createApplicationMachineNavigation(options: {
|
|
|
479
484
|
paletteCommands(): readonly ApplicationPaletteCommand[] {
|
|
480
485
|
const groupsById = new Map(agentGroups().map((group) => [group.machineId, group]));
|
|
481
486
|
return snapshot().groups.flatMap((group) => {
|
|
482
|
-
const
|
|
487
|
+
const daemon = manager.getMachine(group.id)?.read();
|
|
488
|
+
const isDefault = (session: { server?: TmuxServerScope }) =>
|
|
489
|
+
!session.server || session.server.generation === daemon?.instanceId;
|
|
490
|
+
const agentGroup = !group.sessions.some((session) => isDefault(session))
|
|
483
491
|
? undefined
|
|
484
492
|
: groupsById.get(group.id);
|
|
485
493
|
const agentsBySession = new Map<string, ApplicationMachineAgent[]>();
|
|
@@ -489,7 +497,6 @@ export function createApplicationMachineNavigation(options: {
|
|
|
489
497
|
list.push(agent);
|
|
490
498
|
agentsBySession.set(agent.liveSessionId, list);
|
|
491
499
|
}
|
|
492
|
-
const daemon = manager.getMachine(group.id)?.read();
|
|
493
500
|
const sessions = group.sessions.flatMap((session): ApplicationPaletteCommand[] => {
|
|
494
501
|
if (!session.liveSessionId) return [];
|
|
495
502
|
const fleet = {
|
|
@@ -502,7 +509,7 @@ export function createApplicationMachineNavigation(options: {
|
|
|
502
509
|
server: session.server,
|
|
503
510
|
hostLabel: `${group.label}${session.serverLabel ? ` / ${session.serverLabel}` : ""}`,
|
|
504
511
|
agentActivities:
|
|
505
|
-
|
|
512
|
+
isDefault(session) && agentGroup?.available
|
|
506
513
|
? (agentsBySession.get(session.liveSessionId) ?? []).map((a) => ({
|
|
507
514
|
paneId: a.paneId!,
|
|
508
515
|
attention: a.attention,
|
|
@@ -514,16 +521,15 @@ export function createApplicationMachineNavigation(options: {
|
|
|
514
521
|
};
|
|
515
522
|
return [
|
|
516
523
|
{ kind: "open-session", sessionName: session.name, label: session.name, fleet },
|
|
517
|
-
...(
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
})),
|
|
524
|
+
...(isDefault(session) ? (agentsBySession.get(session.liveSessionId) ?? []) : []).map(
|
|
525
|
+
(a) => ({
|
|
526
|
+
kind: "jump-agent" as const,
|
|
527
|
+
sessionName: session.name,
|
|
528
|
+
paneId: a.paneId!,
|
|
529
|
+
label: a.name,
|
|
530
|
+
fleet: { ...fleet, disabled: fleet.disabled || a.disabled },
|
|
531
|
+
}),
|
|
532
|
+
),
|
|
527
533
|
];
|
|
528
534
|
});
|
|
529
535
|
return [
|
|
@@ -25,7 +25,7 @@ import {
|
|
|
25
25
|
type Accessor,
|
|
26
26
|
type JSX,
|
|
27
27
|
} from "solid-js";
|
|
28
|
-
import { friendlySessionLabel } from "../terminal-text.ts";
|
|
28
|
+
import { friendlySessionLabel, wrapText } from "../terminal-text.ts";
|
|
29
29
|
import type { SemanticThemeSnapshot } from "../theme.ts";
|
|
30
30
|
import { KeyHint } from "../ui/key-hint.tsx";
|
|
31
31
|
import { NavigationRow } from "../ui/navigation-row.tsx";
|
|
@@ -124,6 +124,9 @@ export function ApplicationMachineSidebar(props: {
|
|
|
124
124
|
readonly agentRows?: number;
|
|
125
125
|
readonly onHelp?: (source: "keyboard" | "mouse") => void;
|
|
126
126
|
}) {
|
|
127
|
+
// All visible sections share one projection for the current reactive inputs.
|
|
128
|
+
// Event handlers retain the model's fresh authority checks at action time.
|
|
129
|
+
const groups = createMemo(() => props.model.groups());
|
|
127
130
|
const [localFocused, setLocalFocused] = createSignal(false);
|
|
128
131
|
const focused = () => props.model.focused?.() ?? localFocused();
|
|
129
132
|
const [localCollapsed, setCollapsed] = createSignal<ReadonlySet<string>>(new Set());
|
|
@@ -133,22 +136,22 @@ export function ApplicationMachineSidebar(props: {
|
|
|
133
136
|
let scroll: ScrollBoxRenderable | undefined;
|
|
134
137
|
const agentHeight = () =>
|
|
135
138
|
(props.agentRows ?? 0) > 0
|
|
136
|
-
? Math.min(
|
|
139
|
+
? Math.min(
|
|
140
|
+
(props.agentRows ?? 0) + 2,
|
|
141
|
+
Math.max(0, Math.floor(props.height / 2)),
|
|
142
|
+
Math.max(0, props.height - fixedHeight() - controlsHeight() - 2),
|
|
143
|
+
)
|
|
137
144
|
: 0;
|
|
138
|
-
const controlsHeight = () => (props.height >= 8 && controlGroup() ?
|
|
145
|
+
const controlsHeight = () => (props.height >= 8 && controlGroup() ? controlTextHeight() + 2 : 0);
|
|
139
146
|
const searchHeight = () =>
|
|
140
147
|
(props.model.onOpenSwitcher ? 1 : 0) + (props.model.onOpenAttention ? 1 : 0);
|
|
148
|
+
const fixedHeight = () => 1 + (props.model.onAddMachine ? 1 : 0) + searchHeight();
|
|
149
|
+
// Keep both action rows and at least two machine rows available on short terminals.
|
|
150
|
+
const controlTextHeight = () =>
|
|
151
|
+
Math.min(controlTextLines().length, Math.max(1, props.height - fixedHeight() - 4));
|
|
141
152
|
|
|
142
153
|
const machineHeight = () =>
|
|
143
|
-
Math.max(
|
|
144
|
-
0,
|
|
145
|
-
props.height -
|
|
146
|
-
1 -
|
|
147
|
-
(props.model.onAddMachine ? 1 : 0) -
|
|
148
|
-
agentHeight() -
|
|
149
|
-
controlsHeight() -
|
|
150
|
-
searchHeight(),
|
|
151
|
-
);
|
|
154
|
+
Math.max(0, props.height - fixedHeight() - agentHeight() - controlsHeight());
|
|
152
155
|
const active = (row: Row) =>
|
|
153
156
|
row.group.id === props.model.activeMachineId() &&
|
|
154
157
|
(row.agent
|
|
@@ -170,7 +173,7 @@ export function ApplicationMachineSidebar(props: {
|
|
|
170
173
|
: row.session?.name === props.model.activeSessionName());
|
|
171
174
|
const preferenceKey = (group: ApplicationMachineGroup) => group.environmentId ?? group.id;
|
|
172
175
|
const rows = createMemo<readonly Row[]>(() => [
|
|
173
|
-
...
|
|
176
|
+
...groups().flatMap((group) =>
|
|
174
177
|
groupApplicationTeamRows(group.agents ?? []).map((agent) => ({
|
|
175
178
|
key: JSON.stringify([
|
|
176
179
|
group.id,
|
|
@@ -183,7 +186,7 @@ export function ApplicationMachineSidebar(props: {
|
|
|
183
186
|
agent,
|
|
184
187
|
})),
|
|
185
188
|
),
|
|
186
|
-
...
|
|
189
|
+
...groups().flatMap((group) => [
|
|
187
190
|
{ key: JSON.stringify([group.id]), group },
|
|
188
191
|
...group.sessions
|
|
189
192
|
.filter(
|
|
@@ -255,6 +258,15 @@ export function ApplicationMachineSidebar(props: {
|
|
|
255
258
|
: "disconnected"
|
|
256
259
|
: diagnostic.phase;
|
|
257
260
|
};
|
|
261
|
+
const controlTextLines = createMemo(() => {
|
|
262
|
+
const group = controlGroup();
|
|
263
|
+
return group
|
|
264
|
+
? wrapText(
|
|
265
|
+
group.diagnostic ? fleetConnectionMessage(group.diagnostic) : connectionDetail(group),
|
|
266
|
+
Math.max(1, props.width),
|
|
267
|
+
)
|
|
268
|
+
: [];
|
|
269
|
+
});
|
|
258
270
|
const toggle = (
|
|
259
271
|
group: ApplicationMachineGroup,
|
|
260
272
|
value = !collapsed().has(preferenceKey(group)),
|
|
@@ -303,7 +315,7 @@ export function ApplicationMachineSidebar(props: {
|
|
|
303
315
|
const rowHeight = (row: Row) =>
|
|
304
316
|
(row.agent ? 2 : row.serverHeading ? 2 : 1) +
|
|
305
317
|
sectionGap(row) +
|
|
306
|
-
(hasAgents() && row.key === JSON.stringify([
|
|
318
|
+
(hasAgents() && row.key === JSON.stringify([groups()[0]?.id]) ? 1 : 0);
|
|
307
319
|
const revealFocusedRow = () => {
|
|
308
320
|
if (!focused() || !scroll) return;
|
|
309
321
|
const y = rows()
|
|
@@ -528,9 +540,7 @@ export function ApplicationMachineSidebar(props: {
|
|
|
528
540
|
}}
|
|
529
541
|
/>
|
|
530
542
|
</Show>
|
|
531
|
-
<Show
|
|
532
|
-
when={hasAgents() && row.key === JSON.stringify([props.model.groups()[0]?.id])}
|
|
533
|
-
>
|
|
543
|
+
<Show when={hasAgents() && row.key === JSON.stringify([groups()[0]?.id])}>
|
|
534
544
|
<text height={1} fg={props.theme.roles.text.secondary}>
|
|
535
545
|
{" "}
|
|
536
546
|
Machines
|
|
@@ -646,7 +656,7 @@ export function ApplicationMachineSidebar(props: {
|
|
|
646
656
|
<KeyHint
|
|
647
657
|
theme={props.theme}
|
|
648
658
|
keys={CHROME_ACTIONS.attention.keys}
|
|
649
|
-
label={`${CHROME_ACTIONS.attention.label} (${
|
|
659
|
+
label={`${CHROME_ACTIONS.attention.label} (${groups().reduce((sum, group) => sum + (group.state === "ready" ? (group.agents ?? []).filter((agent) => agent.attention && !agent.disabled).length : 0), 0)})`}
|
|
650
660
|
width={props.width}
|
|
651
661
|
quiet
|
|
652
662
|
button
|
|
@@ -656,10 +666,8 @@ export function ApplicationMachineSidebar(props: {
|
|
|
656
666
|
<Show when={controlsHeight() > 0 && controlGroup()}>
|
|
657
667
|
{(group) => (
|
|
658
668
|
<>
|
|
659
|
-
<text height={
|
|
660
|
-
{
|
|
661
|
-
? fleetConnectionMessage(group().diagnostic!)
|
|
662
|
-
: connectionDetail(group())}
|
|
669
|
+
<text height={controlTextHeight()} flexShrink={0} fg={props.theme.roles.text.secondary}>
|
|
670
|
+
{controlTextLines().join("\n")}
|
|
663
671
|
</text>
|
|
664
672
|
<KeyHint
|
|
665
673
|
theme={props.theme}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { resolveRuntimeNamespace } from "../../../lib/runtime-namespace.ts";
|
|
2
2
|
import { randomUUID } from "node:crypto";
|
|
3
3
|
import { SavedMachineSchema, type SavedMachine } from "@tmux-ide/contracts";
|
|
4
|
-
import { loadSavedMachines } from "../../../lib/saved-machines.ts";
|
|
4
|
+
import { loadSavedMachines, watchSavedMachines } from "../../../lib/saved-machines.ts";
|
|
5
5
|
import { applicationMachineAuthorityManager } from "./application-machine-authority.ts";
|
|
6
|
+
import { tuiPerfMark } from "./application-performance-log.ts";
|
|
6
7
|
|
|
7
8
|
/** Labels describe access routes; they never become routing identities. */
|
|
8
9
|
export function ephemeralMachineProfile(
|
|
@@ -25,16 +26,51 @@ export function ephemeralMachineProfile(
|
|
|
25
26
|
|
|
26
27
|
/** Local discovery and rendering never wait for any remote handshake. */
|
|
27
28
|
export function initializeApplicationMachines(aliases: readonly string[]): void {
|
|
28
|
-
const
|
|
29
|
+
const development = resolveRuntimeNamespace().development;
|
|
30
|
+
const profiles = development ? [] : [...loadSavedMachines().machines];
|
|
31
|
+
const ephemeral: SavedMachine[] = [];
|
|
29
32
|
let preferred: string | null = null;
|
|
30
33
|
for (const alias of aliases) {
|
|
31
34
|
let profile = profiles.find((p) => p.sshTarget === alias && p.enabled);
|
|
32
35
|
if (!profile) {
|
|
33
36
|
profile = ephemeralMachineProfile(alias, profiles);
|
|
34
37
|
profiles.push(profile);
|
|
38
|
+
ephemeral.push(profile);
|
|
35
39
|
}
|
|
36
40
|
preferred ??= profile.id;
|
|
37
41
|
}
|
|
38
42
|
applicationMachineAuthorityManager.initialize(profiles);
|
|
39
43
|
if (preferred) applicationMachineAuthorityManager.select(preferred);
|
|
44
|
+
if (!development) {
|
|
45
|
+
const failed = () =>
|
|
46
|
+
tuiPerfMark("machine-registry-error", { reason: "registry-unavailable-or-invalid" });
|
|
47
|
+
try {
|
|
48
|
+
applicationMachineAuthorityManager.followProfiles((onChange) =>
|
|
49
|
+
watchSavedMachines((registry) => {
|
|
50
|
+
const next = [...registry.machines];
|
|
51
|
+
for (let index = 0; index < ephemeral.length; index++) {
|
|
52
|
+
let profile = ephemeral[index]!;
|
|
53
|
+
// A newly saved route may claim an ephemeral display label. Keep the
|
|
54
|
+
// explicit connection's identity while making the label unambiguous.
|
|
55
|
+
if (
|
|
56
|
+
next.some(
|
|
57
|
+
(entry) =>
|
|
58
|
+
entry.label.normalize("NFKC").toLowerCase() ===
|
|
59
|
+
profile.label.normalize("NFKC").toLowerCase(),
|
|
60
|
+
)
|
|
61
|
+
)
|
|
62
|
+
profile = {
|
|
63
|
+
...profile,
|
|
64
|
+
label: ephemeralMachineProfile(profile.sshTarget, next).label,
|
|
65
|
+
};
|
|
66
|
+
ephemeral[index] = profile;
|
|
67
|
+
next.push(profile);
|
|
68
|
+
}
|
|
69
|
+
onChange(next);
|
|
70
|
+
}, failed),
|
|
71
|
+
);
|
|
72
|
+
} catch {
|
|
73
|
+
failed();
|
|
74
|
+
}
|
|
75
|
+
}
|
|
40
76
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createMemo, createSignal } from "solid-js";
|
|
1
|
+
import { createMemo, createSignal, untrack } from "solid-js";
|
|
2
2
|
import {
|
|
3
3
|
applicationCommandDescription,
|
|
4
4
|
filterApplicationCommands,
|
|
@@ -28,7 +28,7 @@ export function createApplicationPaletteSearchOwner(options: {
|
|
|
28
28
|
const [help, setHelp] = createSignal(false);
|
|
29
29
|
const [query, setQuery] = createSignal("");
|
|
30
30
|
const [selectedId, setSelectedId] = createSignal<string | null>(null);
|
|
31
|
-
const
|
|
31
|
+
const readCommands = () =>
|
|
32
32
|
filterApplicationCommands(
|
|
33
33
|
options
|
|
34
34
|
.commands()
|
|
@@ -36,8 +36,11 @@ export function createApplicationPaletteSearchOwner(options: {
|
|
|
36
36
|
(c) => !localOnly() || typeof c === "string" || !c.fleet || c.fleet.machineId === "local",
|
|
37
37
|
),
|
|
38
38
|
query(),
|
|
39
|
-
)
|
|
40
|
-
|
|
39
|
+
);
|
|
40
|
+
// Closed overlays must not subscribe to catalog churn. Explicit reads still
|
|
41
|
+
// resolve current commands, including reset() before the open action commits.
|
|
42
|
+
const activeCommands = createMemo(() => (options.open() ? readCommands() : null));
|
|
43
|
+
const commands = () => activeCommands() ?? untrack(readCommands);
|
|
41
44
|
const selection = () =>
|
|
42
45
|
Math.max(
|
|
43
46
|
0,
|
|
@@ -34,6 +34,8 @@ export const tuiLifecycleStream = stream ? Object.freeze({ enabled: true as cons
|
|
|
34
34
|
export const tuiPerfStream = TUI_PERF_LOG ? tuiLifecycleStream : null;
|
|
35
35
|
|
|
36
36
|
const LIFECYCLE_PHASES = new Set([
|
|
37
|
+
"machine-connection-status",
|
|
38
|
+
"machine-registry-error",
|
|
37
39
|
"generation-status",
|
|
38
40
|
"generation-connection-start",
|
|
39
41
|
"generation-connection-resolved",
|
|
@@ -170,6 +172,7 @@ export function closeTuiPerfMarks(): Promise<void> {
|
|
|
170
172
|
closing = true;
|
|
171
173
|
closePromise = (async () => {
|
|
172
174
|
if (!stream) return;
|
|
175
|
+
await writer?.flush();
|
|
173
176
|
await flushTuiPerfMarks();
|
|
174
177
|
// No drain callback may enqueue another critical record after end().
|
|
175
178
|
stream.off("drain", drain);
|
|
@@ -427,7 +427,7 @@ export async function startApplicationRoot(options: StartApplicationRootOptions
|
|
|
427
427
|
const currentShell = shell();
|
|
428
428
|
semanticViewportResize.adopt(dimensions(), currentShell.semantic, generation());
|
|
429
429
|
focusedPane();
|
|
430
|
-
terminalInputIngress.adopt();
|
|
430
|
+
terminalInputIngress.adopt(activeSurface() === "terminals");
|
|
431
431
|
});
|
|
432
432
|
const sidebarShortcut = createApplicationSidebarShortcuts(
|
|
433
433
|
activeSurface,
|
|
@@ -497,52 +497,53 @@ export function ApplicationShellView(props: ApplicationShellViewProps): JSX.Elem
|
|
|
497
497
|
/>
|
|
498
498
|
}
|
|
499
499
|
>
|
|
500
|
-
{(model) =>
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
.some((group) => group.agents !== undefined)
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
500
|
+
{(model) => {
|
|
501
|
+
// Sizing, rows and pane labels share this render projection.
|
|
502
|
+
// Keep the navigation model and its action-time reads intact.
|
|
503
|
+
const groups = createMemo(() => model().groups());
|
|
504
|
+
return (
|
|
505
|
+
<ApplicationMachineSidebar
|
|
506
|
+
model={{ ...model(), groups }}
|
|
507
|
+
paneName={(endpoint) =>
|
|
508
|
+
nameForCurrentEndpoint(
|
|
509
|
+
groups().flatMap((group) => group.agents ?? []),
|
|
510
|
+
endpoint,
|
|
511
|
+
)
|
|
512
|
+
}
|
|
513
|
+
interactionForAgent={(agent) =>
|
|
514
|
+
interactionForCurrentPane(
|
|
515
|
+
props.paneInteractions?.(),
|
|
516
|
+
agent.interactionEndpoint,
|
|
517
|
+
agent.nativeIdentity,
|
|
518
|
+
)
|
|
519
|
+
}
|
|
520
|
+
onHelp={(source) => {
|
|
521
|
+
props.onSetPaletteOpen(true, source);
|
|
522
|
+
props.onPaletteReferenceChange?.("help");
|
|
523
|
+
}}
|
|
524
|
+
agentRows={
|
|
525
|
+
groups().some((group) => group.agents !== undefined)
|
|
526
|
+
? 0
|
|
527
|
+
: shell.semantic.sidebar.agents.length
|
|
528
|
+
}
|
|
529
|
+
agents={
|
|
530
|
+
<ApplicationSidebarAgents
|
|
531
|
+
shell={shell}
|
|
532
|
+
theme={appearance.theme}
|
|
533
|
+
width={Math.max(1, shell.layout.sidebar.width - 1)}
|
|
534
|
+
onIntent={(intent) => {
|
|
535
|
+
if (intent.type !== "agent.open") return;
|
|
536
|
+
model().onBlur?.();
|
|
537
|
+
props.onOpenAgent?.(intent.sessionName, intent.paneId, intent.source);
|
|
538
|
+
}}
|
|
539
|
+
/>
|
|
540
|
+
}
|
|
541
|
+
width={shell.layout.sidebar.width}
|
|
542
|
+
height={shell.layout.sidebar.height}
|
|
543
|
+
theme={appearance.theme}
|
|
544
|
+
/>
|
|
545
|
+
);
|
|
546
|
+
}}
|
|
546
547
|
</Show>
|
|
547
548
|
}
|
|
548
549
|
>
|