tmux-ide 2.9.0-beta.21 → 2.9.0-beta.22
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 +52253 -49070
- package/package.json +1 -1
- 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/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 +345 -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 +16 -10
- 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-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-machine-catalog.js +12 -2
- package/packages/daemon/dist/tui/mirror/runtime/application-machine-navigation.js +190 -31
- package/packages/daemon/dist/tui/mirror/runtime/application-machine-sidebar.jsx +91 -37
- 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-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/fleet-lifecycle-client.js +42 -1
- package/packages/daemon/dist/tui/mirror/runtime/open-tui-generation-host.js +1 -1
- package/packages/daemon/dist/tui/mirror/runtime/select-terminal-pane.js +2 -1
- 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 +468 -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 +16 -8
- 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-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-machine-catalog.ts +19 -7
- package/packages/daemon/src/tui/mirror/runtime/application-machine-navigation.ts +263 -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-root-configuration.ts +12 -3
- package/packages/daemon/src/tui/mirror/runtime/application-root-v2.tsx +24 -24
- package/packages/daemon/src/tui/mirror/runtime/application-route-connection.ts +93 -1
- package/packages/daemon/src/tui/mirror/runtime/application-shell-view.tsx +4 -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/fleet-lifecycle-client.ts +52 -0
- package/packages/daemon/src/tui/mirror/runtime/open-tui-generation-host.ts +1 -1
- package/packages/daemon/src/tui/mirror/runtime/select-terminal-pane.ts +3 -0
- 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
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
import {
|
|
2
|
+
TMUX_SERVERS_API_PATH,
|
|
3
|
+
PANE_STREAM_REDEEM_PATH,
|
|
4
|
+
TmuxServerIdSchemaZ,
|
|
5
|
+
TmuxServerDescriptorSchemaZ,
|
|
6
|
+
TmuxServerRegistrationRequestSchemaZ,
|
|
7
|
+
type TmuxServerRegistrationRequest,
|
|
8
|
+
TmuxServerScopeSchemaZ,
|
|
9
|
+
TmuxServersResourceSchemaZ,
|
|
10
|
+
TmuxServerSessionsResourceSchemaZ,
|
|
11
|
+
TerminalRuntimeInventoryProjectionV1SchemaZ,
|
|
12
|
+
WorkspaceMultiplexerMutationRequestSchemaZ,
|
|
13
|
+
WorkspacePaneCreateMutationRequestSchemaZ,
|
|
14
|
+
WorkspacePaneCreateMutationResultSchemaZ,
|
|
15
|
+
type WorkspacePaneCreateArguments,
|
|
16
|
+
WorkspaceSessionCreateArgumentsSchemaZ,
|
|
17
|
+
WorkspaceSessionCreateResultSchemaZ,
|
|
18
|
+
type WorkspaceSessionCreateArguments,
|
|
19
|
+
WorkspaceMultiplexerMutationResultSchemaZ,
|
|
20
|
+
PaneStreamIssueMutationRequestSchemaZ,
|
|
21
|
+
PaneStreamIssueResultSchemaZ,
|
|
22
|
+
tmuxServerPaneStreamPath,
|
|
23
|
+
tmuxServerScopedResourceKey,
|
|
24
|
+
type TmuxServerScope,
|
|
25
|
+
type WorkspaceMultiplexerIntent,
|
|
26
|
+
type PaneStreamLeaseRequest,
|
|
27
|
+
} from "@tmux-ide/contracts";
|
|
28
|
+
|
|
29
|
+
export interface TmuxServerClientOptions {
|
|
30
|
+
readonly baseUrl: string;
|
|
31
|
+
readonly ownerToken: string;
|
|
32
|
+
readonly hostClientId: string;
|
|
33
|
+
readonly origin: string;
|
|
34
|
+
readonly fetch?: typeof fetch;
|
|
35
|
+
readonly timeoutMs?: number;
|
|
36
|
+
}
|
|
37
|
+
export class TmuxServerClientError extends Error {
|
|
38
|
+
constructor(
|
|
39
|
+
readonly code: "disposed" | "scope-mismatch" | "request-failed",
|
|
40
|
+
readonly status?: number,
|
|
41
|
+
) {
|
|
42
|
+
super(`tmux server client ${code}`);
|
|
43
|
+
this.name = "TmuxServerClientError";
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
async function request(
|
|
47
|
+
options: TmuxServerClientOptions,
|
|
48
|
+
path: string,
|
|
49
|
+
body?: unknown,
|
|
50
|
+
headers?: Record<string, string>,
|
|
51
|
+
method?: "DELETE",
|
|
52
|
+
) {
|
|
53
|
+
const response = await (options.fetch ?? fetch)(new URL(path, options.baseUrl), {
|
|
54
|
+
method: method ?? (body === undefined ? "GET" : "POST"),
|
|
55
|
+
headers: {
|
|
56
|
+
Authorization: `Bearer ${options.ownerToken}`,
|
|
57
|
+
...(body === undefined ? {} : { "Content-Type": "application/json" }),
|
|
58
|
+
...headers,
|
|
59
|
+
},
|
|
60
|
+
...(body === undefined ? {} : { body: JSON.stringify(body) }),
|
|
61
|
+
redirect: "error",
|
|
62
|
+
cache: "no-store",
|
|
63
|
+
signal: AbortSignal.timeout(options.timeoutMs ?? 5_000),
|
|
64
|
+
});
|
|
65
|
+
if (!response.ok) throw new TmuxServerClientError("request-failed", response.status);
|
|
66
|
+
return (await response.json()) as unknown;
|
|
67
|
+
}
|
|
68
|
+
export async function listTmuxServers(options: TmuxServerClientOptions) {
|
|
69
|
+
return TmuxServersResourceSchemaZ.parse(await request(options, TMUX_SERVERS_API_PATH));
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export async function registerTmuxServer(
|
|
73
|
+
options: TmuxServerClientOptions,
|
|
74
|
+
registration: TmuxServerRegistrationRequest,
|
|
75
|
+
) {
|
|
76
|
+
return TmuxServerDescriptorSchemaZ.parse(
|
|
77
|
+
await request(
|
|
78
|
+
options,
|
|
79
|
+
TMUX_SERVERS_API_PATH,
|
|
80
|
+
TmuxServerRegistrationRequestSchemaZ.parse(registration),
|
|
81
|
+
),
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
export async function removeTmuxServer(
|
|
85
|
+
options: TmuxServerClientOptions,
|
|
86
|
+
serverId: string,
|
|
87
|
+
): Promise<void> {
|
|
88
|
+
const response = await request(
|
|
89
|
+
options,
|
|
90
|
+
`${TMUX_SERVERS_API_PATH}/${TmuxServerIdSchemaZ.parse(serverId)}`,
|
|
91
|
+
undefined,
|
|
92
|
+
undefined,
|
|
93
|
+
"DELETE",
|
|
94
|
+
);
|
|
95
|
+
if (
|
|
96
|
+
!response ||
|
|
97
|
+
typeof response !== "object" ||
|
|
98
|
+
!("removed" in response) ||
|
|
99
|
+
response.removed !== true ||
|
|
100
|
+
Object.keys(response).length !== 1
|
|
101
|
+
)
|
|
102
|
+
throw new TypeError("Invalid server removal response");
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/** Bind once. Selection changes dispose this client and create another; no implicit fallback. */
|
|
106
|
+
export function createTmuxServerClient(
|
|
107
|
+
optionsInput: TmuxServerClientOptions,
|
|
108
|
+
scopeInput: TmuxServerScope,
|
|
109
|
+
) {
|
|
110
|
+
const options = Object.freeze({ ...optionsInput });
|
|
111
|
+
const scope = Object.freeze(TmuxServerScopeSchemaZ.parse(scopeInput));
|
|
112
|
+
const base = `${TMUX_SERVERS_API_PATH}/${scope.serverId}/${scope.generation}`;
|
|
113
|
+
let disposed = false;
|
|
114
|
+
function assertCurrent() {
|
|
115
|
+
if (disposed) throw new TmuxServerClientError("disposed");
|
|
116
|
+
}
|
|
117
|
+
function assertScope(candidate: TmuxServerScope) {
|
|
118
|
+
if (candidate.serverId !== scope.serverId || candidate.generation !== scope.generation)
|
|
119
|
+
throw new TmuxServerClientError("scope-mismatch");
|
|
120
|
+
}
|
|
121
|
+
async function scopedRequest(suffix: string, body?: unknown, headers?: Record<string, string>) {
|
|
122
|
+
assertCurrent();
|
|
123
|
+
const result = await request(options, `${base}/${suffix}`, body, headers);
|
|
124
|
+
assertCurrent();
|
|
125
|
+
return result;
|
|
126
|
+
}
|
|
127
|
+
return {
|
|
128
|
+
scope,
|
|
129
|
+
dispose() {
|
|
130
|
+
disposed = true;
|
|
131
|
+
},
|
|
132
|
+
cacheKey(kind: string, resourceId: string) {
|
|
133
|
+
return tmuxServerScopedResourceKey(scope, kind, resourceId);
|
|
134
|
+
},
|
|
135
|
+
async sessions() {
|
|
136
|
+
const response = TmuxServerSessionsResourceSchemaZ.parse(await scopedRequest("sessions"));
|
|
137
|
+
assertScope(response.server);
|
|
138
|
+
return response;
|
|
139
|
+
},
|
|
140
|
+
async openSession(liveSessionId: string) {
|
|
141
|
+
const raw = await scopedRequest(`sessions/${encodeURIComponent(liveSessionId)}/open`, {});
|
|
142
|
+
if (
|
|
143
|
+
!raw ||
|
|
144
|
+
typeof raw !== "object" ||
|
|
145
|
+
!("version" in raw) ||
|
|
146
|
+
raw.version !== 1 ||
|
|
147
|
+
!("server" in raw) ||
|
|
148
|
+
!("workspaceName" in raw) ||
|
|
149
|
+
typeof raw.workspaceName !== "string" ||
|
|
150
|
+
!raw.workspaceName ||
|
|
151
|
+
!("liveSessionId" in raw) ||
|
|
152
|
+
raw.liveSessionId !== liveSessionId ||
|
|
153
|
+
Object.keys(raw).length !== 4
|
|
154
|
+
)
|
|
155
|
+
throw new TypeError("Invalid scoped session-open response");
|
|
156
|
+
assertScope(TmuxServerScopeSchemaZ.parse(raw.server));
|
|
157
|
+
return {
|
|
158
|
+
version: 1 as const,
|
|
159
|
+
server: scope,
|
|
160
|
+
workspaceName: raw.workspaceName,
|
|
161
|
+
liveSessionId,
|
|
162
|
+
};
|
|
163
|
+
},
|
|
164
|
+
async inventory(workspaceName: string) {
|
|
165
|
+
const raw = await scopedRequest(`inventory/${encodeURIComponent(workspaceName)}`);
|
|
166
|
+
if (
|
|
167
|
+
!raw ||
|
|
168
|
+
typeof raw !== "object" ||
|
|
169
|
+
!("version" in raw) ||
|
|
170
|
+
raw.version !== 1 ||
|
|
171
|
+
!("server" in raw) ||
|
|
172
|
+
!("resource" in raw) ||
|
|
173
|
+
Object.keys(raw).length !== 3
|
|
174
|
+
)
|
|
175
|
+
throw new TypeError("Invalid scoped inventory response");
|
|
176
|
+
assertScope(TmuxServerScopeSchemaZ.parse(raw.server));
|
|
177
|
+
const resource = TerminalRuntimeInventoryProjectionV1SchemaZ.parse(raw.resource);
|
|
178
|
+
if (resource.workspaceName !== workspaceName)
|
|
179
|
+
throw new TmuxServerClientError("scope-mismatch");
|
|
180
|
+
return { version: 1 as const, server: scope, resource };
|
|
181
|
+
},
|
|
182
|
+
async createSession(operationId: string, intent: WorkspaceSessionCreateArguments) {
|
|
183
|
+
const safeIntent = WorkspaceSessionCreateArgumentsSchemaZ.parse(intent);
|
|
184
|
+
if (
|
|
185
|
+
safeIntent.expectedDaemonInstanceId &&
|
|
186
|
+
safeIntent.expectedDaemonInstanceId !== scope.generation
|
|
187
|
+
)
|
|
188
|
+
throw new TmuxServerClientError("scope-mismatch");
|
|
189
|
+
const result = WorkspaceSessionCreateResultSchemaZ.parse(
|
|
190
|
+
await scopedRequest("sessions/create", {
|
|
191
|
+
operationId,
|
|
192
|
+
expectedDaemonInstanceId: scope.generation,
|
|
193
|
+
intent: safeIntent,
|
|
194
|
+
}),
|
|
195
|
+
);
|
|
196
|
+
if (result.daemonInstanceId !== scope.generation || result.operationId !== operationId)
|
|
197
|
+
throw new TmuxServerClientError("scope-mismatch");
|
|
198
|
+
return result;
|
|
199
|
+
},
|
|
200
|
+
async createPane(
|
|
201
|
+
operationId: string,
|
|
202
|
+
intent: WorkspacePaneCreateArguments,
|
|
203
|
+
liveSessionId: string,
|
|
204
|
+
) {
|
|
205
|
+
const body = WorkspacePaneCreateMutationRequestSchemaZ.parse({
|
|
206
|
+
operationId,
|
|
207
|
+
expectedDaemonInstanceId: scope.generation,
|
|
208
|
+
intent,
|
|
209
|
+
});
|
|
210
|
+
const result = WorkspacePaneCreateMutationResultSchemaZ.parse(
|
|
211
|
+
await scopedRequest(
|
|
212
|
+
`panes/create?liveSessionId=${encodeURIComponent(liveSessionId)}`,
|
|
213
|
+
body,
|
|
214
|
+
),
|
|
215
|
+
);
|
|
216
|
+
if (
|
|
217
|
+
result.daemonInstanceId !== scope.generation ||
|
|
218
|
+
result.operationId !== operationId ||
|
|
219
|
+
result.resource.workspaceName !== intent.workspaceName
|
|
220
|
+
)
|
|
221
|
+
throw new TmuxServerClientError("scope-mismatch");
|
|
222
|
+
return result;
|
|
223
|
+
},
|
|
224
|
+
async mutate(operationId: string, intent: WorkspaceMultiplexerIntent, liveSessionId?: string) {
|
|
225
|
+
const body = WorkspaceMultiplexerMutationRequestSchemaZ.parse({
|
|
226
|
+
operationId,
|
|
227
|
+
expectedDaemonInstanceId: scope.generation,
|
|
228
|
+
intent,
|
|
229
|
+
});
|
|
230
|
+
const result = WorkspaceMultiplexerMutationResultSchemaZ.parse(
|
|
231
|
+
await scopedRequest(
|
|
232
|
+
`mutations${liveSessionId ? `?liveSessionId=${encodeURIComponent(liveSessionId)}` : ""}`,
|
|
233
|
+
body,
|
|
234
|
+
intent.verb === "workspace.session.kill" && intent.fleetTarget
|
|
235
|
+
? undefined
|
|
236
|
+
: { "X-Tmux-Ide-Host-Client-Id": options.hostClientId },
|
|
237
|
+
),
|
|
238
|
+
);
|
|
239
|
+
if (
|
|
240
|
+
result.daemonInstanceId !== scope.generation ||
|
|
241
|
+
result.operationId !== operationId ||
|
|
242
|
+
result.verb !== intent.verb ||
|
|
243
|
+
result.workspaceName !== intent.workspaceName
|
|
244
|
+
)
|
|
245
|
+
throw new TmuxServerClientError("scope-mismatch");
|
|
246
|
+
return result;
|
|
247
|
+
},
|
|
248
|
+
async issuePaneStream(
|
|
249
|
+
requestId: string,
|
|
250
|
+
stream: PaneStreamLeaseRequest,
|
|
251
|
+
liveSessionId?: string,
|
|
252
|
+
) {
|
|
253
|
+
const body = PaneStreamIssueMutationRequestSchemaZ.parse({
|
|
254
|
+
requestId,
|
|
255
|
+
expectedDaemonInstanceId: scope.generation,
|
|
256
|
+
stream,
|
|
257
|
+
});
|
|
258
|
+
const result = PaneStreamIssueResultSchemaZ.parse(
|
|
259
|
+
await scopedRequest(
|
|
260
|
+
`pane-streams/issue${liveSessionId ? `?liveSessionId=${encodeURIComponent(liveSessionId)}` : ""}`,
|
|
261
|
+
body,
|
|
262
|
+
{
|
|
263
|
+
Origin: options.origin,
|
|
264
|
+
"X-Tmux-Ide-Request-Id": requestId,
|
|
265
|
+
"X-Tmux-Ide-Expected-Daemon-Instance-Id": scope.generation,
|
|
266
|
+
"X-Tmux-Ide-Host-Client-Id": options.hostClientId,
|
|
267
|
+
},
|
|
268
|
+
),
|
|
269
|
+
);
|
|
270
|
+
if (
|
|
271
|
+
result.status === "issued" &&
|
|
272
|
+
(result.descriptor.daemonInstanceId !== scope.generation ||
|
|
273
|
+
result.descriptor.requestId !== requestId ||
|
|
274
|
+
// The adopted default owner retains its original redemption address.
|
|
275
|
+
// Its exact generation and request are still proven by this bound issue response.
|
|
276
|
+
![tmuxServerPaneStreamPath(scope), PANE_STREAM_REDEEM_PATH].includes(
|
|
277
|
+
new URL(result.descriptor.webSocketUrl).pathname,
|
|
278
|
+
) ||
|
|
279
|
+
JSON.stringify([...result.descriptor.panes].sort()) !==
|
|
280
|
+
JSON.stringify([...stream.panes].sort()))
|
|
281
|
+
)
|
|
282
|
+
throw new TmuxServerClientError("scope-mismatch");
|
|
283
|
+
return result;
|
|
284
|
+
},
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
export type TmuxServerClient = ReturnType<typeof createTmuxServerClient>;
|