@rigkit/provider-cmux 0.2.2 → 0.2.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/README.md +3 -4
- package/package.json +3 -3
- package/src/capabilities.ts +1 -3
- package/src/host.ts +43 -38
- package/src/index.test.ts +49 -20
- package/src/index.ts +2 -0
- package/src/provider.ts +28 -27
- package/src/version.ts +1 -1
package/README.md
CHANGED
|
@@ -43,14 +43,13 @@ export default workflow("site", {
|
|
|
43
43
|
})
|
|
44
44
|
.sequence("site")
|
|
45
45
|
.operation("open", {
|
|
46
|
-
requiredHostCapabilities: [cmux.capabilities.open],
|
|
47
46
|
run: async ({ providers }) => {
|
|
48
47
|
await providers.cmux.open({
|
|
49
48
|
name: "site",
|
|
50
49
|
ssh: {
|
|
51
|
-
host: "
|
|
52
|
-
username: "
|
|
53
|
-
|
|
50
|
+
host: "devbox.example.com",
|
|
51
|
+
username: "root",
|
|
52
|
+
sshOptions: ["ServerAliveInterval=15"],
|
|
54
53
|
},
|
|
55
54
|
cwd: "/workspace/site",
|
|
56
55
|
command: "pnpm dev",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rigkit/provider-cmux",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.4",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -17,8 +17,8 @@
|
|
|
17
17
|
"README.md"
|
|
18
18
|
],
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@rigkit/sdk": "0.2.
|
|
21
|
-
"@rigkit/engine": "0.2.
|
|
20
|
+
"@rigkit/sdk": "0.2.4",
|
|
21
|
+
"@rigkit/engine": "0.2.4"
|
|
22
22
|
},
|
|
23
23
|
"devDependencies": {
|
|
24
24
|
"@types/bun": "latest",
|
package/src/capabilities.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export const CMUX_OPEN_CAPABILITY_ID = "cmux.open";
|
|
2
2
|
|
|
3
3
|
export const CMUX_OPEN_SCHEMA_HASH =
|
|
4
|
-
"sha256:
|
|
4
|
+
"sha256:671373232fc79a7f75dd01c8c83c0c350af62b349a89bb3cfcc96af2cd76c878";
|
|
5
5
|
|
|
6
6
|
export const CMUX_OPEN_CAPABILITY = {
|
|
7
7
|
id: CMUX_OPEN_CAPABILITY_ID,
|
|
@@ -14,8 +14,6 @@ export type CmuxOpenSshInput = string | {
|
|
|
14
14
|
host?: string;
|
|
15
15
|
port?: number;
|
|
16
16
|
username?: string;
|
|
17
|
-
auth?: { type: "token"; token: string } | { type: "privateKey"; privateKey: string };
|
|
18
|
-
command?: string;
|
|
19
17
|
identity?: string;
|
|
20
18
|
sshOptions?: readonly string[];
|
|
21
19
|
remoteCommandArgs?: readonly string[];
|
package/src/host.ts
CHANGED
|
@@ -13,7 +13,11 @@ import {
|
|
|
13
13
|
type CmuxWaitForRemoteOptions,
|
|
14
14
|
type CmuxWorkspace,
|
|
15
15
|
} from "./index.ts";
|
|
16
|
-
import {
|
|
16
|
+
import {
|
|
17
|
+
defineHostCapability,
|
|
18
|
+
type HostCapabilityContext,
|
|
19
|
+
type HostCapabilityHandler,
|
|
20
|
+
} from "@rigkit/sdk/host";
|
|
17
21
|
import {
|
|
18
22
|
CMUX_OPEN_CAPABILITY,
|
|
19
23
|
type CmuxOpenInput,
|
|
@@ -39,23 +43,19 @@ export type CmuxOpenClient = Pick<
|
|
|
39
43
|
export type CmuxOpenHostOptions = {
|
|
40
44
|
client?: CmuxOpenClient;
|
|
41
45
|
clientOptions?: CmuxClientOptions;
|
|
46
|
+
logger?: (message: string) => void;
|
|
42
47
|
};
|
|
43
48
|
|
|
44
|
-
const freestyleTokenSshOptions = [
|
|
45
|
-
"StrictHostKeyChecking=no",
|
|
46
|
-
"UserKnownHostsFile=/dev/null",
|
|
47
|
-
"LogLevel=ERROR",
|
|
48
|
-
"IdentitiesOnly=yes",
|
|
49
|
-
"IdentityFile=/dev/null",
|
|
50
|
-
"ControlMaster=no",
|
|
51
|
-
] as const;
|
|
52
|
-
|
|
53
49
|
export function createCmuxOpenHostCapability(
|
|
54
50
|
options: CmuxOpenHostOptions = {},
|
|
55
51
|
): CmuxHostCapabilityHandler {
|
|
56
52
|
return defineHostCapability(CMUX_OPEN_CAPABILITY.id, {
|
|
57
53
|
schemaHash: CMUX_OPEN_CAPABILITY.schemaHash,
|
|
58
|
-
handle: async (params) =>
|
|
54
|
+
handle: async (params, context) =>
|
|
55
|
+
await openCmux(params, {
|
|
56
|
+
...options,
|
|
57
|
+
logger: options.logger ?? hostCapabilityLogger(context) ?? options.clientOptions?.logger,
|
|
58
|
+
}),
|
|
59
59
|
});
|
|
60
60
|
}
|
|
61
61
|
|
|
@@ -66,18 +66,26 @@ export async function openCmux(
|
|
|
66
66
|
options: CmuxOpenHostOptions = {},
|
|
67
67
|
): Promise<CmuxOpenResult> {
|
|
68
68
|
const input = parseCmuxOpenInput(params);
|
|
69
|
-
const
|
|
69
|
+
const logger = cmuxOpenLogger(options);
|
|
70
|
+
const cmux = options.client ?? createCmuxClient({
|
|
71
|
+
...options.clientOptions,
|
|
72
|
+
...(options.logger ? { logger: options.logger } : {}),
|
|
73
|
+
printCommands: options.clientOptions?.printCommands ?? false,
|
|
74
|
+
});
|
|
70
75
|
const command = commandForInput(input);
|
|
71
76
|
let workspace: CmuxWorkspace;
|
|
72
77
|
let terminalPane: CmuxPane | undefined;
|
|
73
78
|
|
|
79
|
+
logger?.(`cmux: opening ${input.name}`);
|
|
74
80
|
if (input.ssh) {
|
|
81
|
+
logger?.("cmux: connecting remote workspace");
|
|
75
82
|
workspace = await cmux.ssh({
|
|
76
83
|
...cmuxSshOptionsForInput(input.ssh),
|
|
77
84
|
name: input.name,
|
|
78
85
|
noFocus: input.focus === false,
|
|
79
86
|
});
|
|
80
87
|
} else {
|
|
88
|
+
logger?.("cmux: creating workspace");
|
|
81
89
|
const workspaceOptions: CmuxNewWorkspaceOptions = {
|
|
82
90
|
name: input.name,
|
|
83
91
|
cwd: input.cwd,
|
|
@@ -90,6 +98,7 @@ export async function openCmux(
|
|
|
90
98
|
const workspaceId = workspace.id ?? workspace.handle;
|
|
91
99
|
|
|
92
100
|
if (input.ssh && command) {
|
|
101
|
+
logger?.(input.cwd ? `cmux: starting command in ${input.cwd}` : "cmux: starting command");
|
|
93
102
|
const paneOptions: CmuxNewPaneOptions = {
|
|
94
103
|
workspace: workspaceId,
|
|
95
104
|
type: "terminal",
|
|
@@ -107,10 +116,12 @@ export async function openCmux(
|
|
|
107
116
|
|
|
108
117
|
const waitOptions = remoteReadyOptionsForInput(input);
|
|
109
118
|
if (input.ssh && waitOptions) {
|
|
119
|
+
logger?.("cmux: waiting for remote ports");
|
|
110
120
|
await cmux.waitForRemoteReady(workspaceId, waitOptions);
|
|
111
121
|
}
|
|
112
122
|
|
|
113
123
|
if (input.ssh && terminalPane?.surface) {
|
|
124
|
+
logger?.("cmux: refreshing remote ports");
|
|
114
125
|
const kickOptions: CmuxPortsKickOptions = {
|
|
115
126
|
workspace: workspaceId,
|
|
116
127
|
surface: terminalPane.surface,
|
|
@@ -121,6 +132,7 @@ export async function openCmux(
|
|
|
121
132
|
|
|
122
133
|
let browserPane: CmuxPane | undefined;
|
|
123
134
|
if (input.url) {
|
|
135
|
+
logger?.(`cmux: opening ${input.url}`);
|
|
124
136
|
const browserOptions: CmuxBrowserOpenOptions = {
|
|
125
137
|
workspace: workspaceId,
|
|
126
138
|
url: input.url,
|
|
@@ -130,9 +142,11 @@ export async function openCmux(
|
|
|
130
142
|
}
|
|
131
143
|
|
|
132
144
|
if (input.focus !== false) {
|
|
145
|
+
logger?.("cmux: focusing workspace");
|
|
133
146
|
await cmux.selectWorkspace(workspaceId);
|
|
134
147
|
}
|
|
135
148
|
|
|
149
|
+
logger?.(`cmux: ready ${input.name}`);
|
|
136
150
|
return {
|
|
137
151
|
sessionId: workspaceId,
|
|
138
152
|
workspaceId,
|
|
@@ -144,6 +158,15 @@ export async function openCmux(
|
|
|
144
158
|
};
|
|
145
159
|
}
|
|
146
160
|
|
|
161
|
+
function cmuxOpenLogger(options: CmuxOpenHostOptions): ((message: string) => void) | undefined {
|
|
162
|
+
return options.logger ?? options.clientOptions?.logger;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
function hostCapabilityLogger(context: HostCapabilityContext | undefined): ((message: string) => void) | undefined {
|
|
166
|
+
if (!context) return undefined;
|
|
167
|
+
return (message) => context.log(message, { label: "cmux" });
|
|
168
|
+
}
|
|
169
|
+
|
|
147
170
|
export function parseCmuxOpenInput(value: unknown): CmuxOpenInput {
|
|
148
171
|
if (!isRecord(value)) throw new Error(`cmux.open requires an object input`);
|
|
149
172
|
const name = requiredString(value, "name");
|
|
@@ -171,8 +194,6 @@ function parseSshInput(value: unknown): CmuxOpenSshInput {
|
|
|
171
194
|
...optionalStringField(value, "host"),
|
|
172
195
|
...optionalNumberField(value, "port"),
|
|
173
196
|
...optionalStringField(value, "username"),
|
|
174
|
-
...(value.auth !== undefined ? { auth: parseSshAuth(value.auth) } : {}),
|
|
175
|
-
...optionalStringField(value, "command"),
|
|
176
197
|
...optionalStringField(value, "identity"),
|
|
177
198
|
...optionalStringArrayField(value, "sshOptions"),
|
|
178
199
|
...optionalStringArrayField(value, "remoteCommandArgs"),
|
|
@@ -183,17 +204,6 @@ function parseSshInput(value: unknown): CmuxOpenSshInput {
|
|
|
183
204
|
};
|
|
184
205
|
}
|
|
185
206
|
|
|
186
|
-
function parseSshAuth(value: unknown): Exclude<Extract<CmuxOpenSshInput, object>["auth"], undefined> {
|
|
187
|
-
if (!isRecord(value)) throw new Error(`cmux.open ssh.auth must be an object`);
|
|
188
|
-
if (value.type === "token") {
|
|
189
|
-
return { type: "token", token: requiredString(value, "token") };
|
|
190
|
-
}
|
|
191
|
-
if (value.type === "privateKey") {
|
|
192
|
-
return { type: "privateKey", privateKey: requiredString(value, "privateKey") };
|
|
193
|
-
}
|
|
194
|
-
throw new Error(`cmux.open ssh.auth.type must be "token" or "privateKey"`);
|
|
195
|
-
}
|
|
196
|
-
|
|
197
207
|
function parseRemoteReadyOptions(value: unknown): boolean | CmuxRemoteReadyOptions {
|
|
198
208
|
if (typeof value === "boolean") return value;
|
|
199
209
|
if (!isRecord(value)) throw new Error(`cmux.open waitForRemoteReady must be a boolean or object`);
|
|
@@ -208,27 +218,22 @@ function cmuxSshOptionsForInput(ssh: CmuxOpenSshInput): CmuxSshOptions {
|
|
|
208
218
|
if (typeof ssh === "string") return { destination: ssh };
|
|
209
219
|
|
|
210
220
|
const destination = ssh.destination ?? sshDestination(ssh);
|
|
211
|
-
const sshOptions = [
|
|
212
|
-
...(ssh.auth?.type === "token" ? freestyleTokenSshOptions : []),
|
|
213
|
-
...(ssh.sshOptions ?? []),
|
|
214
|
-
];
|
|
215
221
|
return {
|
|
216
222
|
destination,
|
|
217
|
-
port: ssh.port,
|
|
218
|
-
identity: ssh.identity,
|
|
219
|
-
sshOptions,
|
|
220
|
-
remoteCommandArgs: ssh.remoteCommandArgs,
|
|
221
|
-
initialCommand: ssh.initialCommand,
|
|
222
|
-
terminalStartupCommand: ssh.terminalStartupCommand
|
|
223
|
-
autoConnect: ssh.autoConnect,
|
|
224
|
-
skipDaemonBootstrap: ssh.skipDaemonBootstrap,
|
|
223
|
+
...(ssh.port !== undefined ? { port: ssh.port } : {}),
|
|
224
|
+
...(ssh.identity !== undefined ? { identity: ssh.identity } : {}),
|
|
225
|
+
...(ssh.sshOptions?.length ? { sshOptions: ssh.sshOptions } : {}),
|
|
226
|
+
...(ssh.remoteCommandArgs !== undefined ? { remoteCommandArgs: ssh.remoteCommandArgs } : {}),
|
|
227
|
+
...(ssh.initialCommand !== undefined ? { initialCommand: ssh.initialCommand } : {}),
|
|
228
|
+
...(ssh.terminalStartupCommand !== undefined ? { terminalStartupCommand: ssh.terminalStartupCommand } : {}),
|
|
229
|
+
...(ssh.autoConnect !== undefined ? { autoConnect: ssh.autoConnect } : {}),
|
|
230
|
+
...(ssh.skipDaemonBootstrap !== undefined ? { skipDaemonBootstrap: ssh.skipDaemonBootstrap } : {}),
|
|
225
231
|
};
|
|
226
232
|
}
|
|
227
233
|
|
|
228
234
|
function sshDestination(ssh: Extract<CmuxOpenSshInput, object>): string {
|
|
229
235
|
if (!ssh.host) throw new Error(`cmux.open ssh.host is required when ssh.destination is omitted`);
|
|
230
236
|
if (!ssh.username) throw new Error(`cmux.open ssh.username is required when ssh.destination is omitted`);
|
|
231
|
-
if (ssh.auth?.type === "token") return `${ssh.username},${ssh.auth.token}@${ssh.host}`;
|
|
232
237
|
return `${ssh.username}@${ssh.host}`;
|
|
233
238
|
}
|
|
234
239
|
|
package/src/index.test.ts
CHANGED
|
@@ -6,7 +6,6 @@ import { describe, expect, test } from "bun:test";
|
|
|
6
6
|
import type { ProviderStorage, ProviderStorageRecord } from "@rigkit/engine";
|
|
7
7
|
import type { JsonValue } from "@rigkit/sdk";
|
|
8
8
|
import {
|
|
9
|
-
CMUX_OPEN_CAPABILITY,
|
|
10
9
|
CmuxCommandError,
|
|
11
10
|
cmux,
|
|
12
11
|
cmuxProviderPlugin,
|
|
@@ -403,21 +402,20 @@ describe("cmux sdk", () => {
|
|
|
403
402
|
|
|
404
403
|
test("handles cmux.open host capability for an ssh workspace", async () => {
|
|
405
404
|
const calls: Array<{ method: string; params: unknown }> = [];
|
|
405
|
+
const logs: string[] = [];
|
|
406
406
|
const client = fakeOpenClient(calls);
|
|
407
407
|
|
|
408
408
|
const result = await openCmux({
|
|
409
409
|
name: "website",
|
|
410
410
|
ssh: {
|
|
411
411
|
kind: "ssh",
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
auth: { type: "token", token: "token_123" },
|
|
415
|
-
command: "ssh vm_123:token_123@vm-ssh.freestyle.sh",
|
|
412
|
+
destination: "vm_123,token_123@vm-ssh.freestyle.sh",
|
|
413
|
+
sshOptions: ["ServerAliveInterval=15"],
|
|
416
414
|
},
|
|
417
415
|
cwd: "/workspace/site",
|
|
418
416
|
command: "pnpm dev",
|
|
419
417
|
url: "http://localhost:4321",
|
|
420
|
-
}, { client });
|
|
418
|
+
}, { client, logger: (message) => logs.push(message) });
|
|
421
419
|
|
|
422
420
|
expect(result).toEqual({
|
|
423
421
|
sessionId: "workspace-1",
|
|
@@ -434,15 +432,7 @@ describe("cmux sdk", () => {
|
|
|
434
432
|
params: expect.objectContaining({
|
|
435
433
|
destination: "vm_123,token_123@vm-ssh.freestyle.sh",
|
|
436
434
|
name: "website",
|
|
437
|
-
|
|
438
|
-
sshOptions: [
|
|
439
|
-
"StrictHostKeyChecking=no",
|
|
440
|
-
"UserKnownHostsFile=/dev/null",
|
|
441
|
-
"LogLevel=ERROR",
|
|
442
|
-
"IdentitiesOnly=yes",
|
|
443
|
-
"IdentityFile=/dev/null",
|
|
444
|
-
"ControlMaster=no",
|
|
445
|
-
],
|
|
435
|
+
sshOptions: ["ServerAliveInterval=15"],
|
|
446
436
|
}),
|
|
447
437
|
},
|
|
448
438
|
{
|
|
@@ -490,19 +480,54 @@ describe("cmux sdk", () => {
|
|
|
490
480
|
params: "workspace-1",
|
|
491
481
|
},
|
|
492
482
|
]);
|
|
483
|
+
expect(calls[0]?.params).not.toHaveProperty("terminalStartupCommand");
|
|
484
|
+
expect(logs).toEqual([
|
|
485
|
+
"cmux: opening website",
|
|
486
|
+
"cmux: connecting remote workspace",
|
|
487
|
+
"cmux: starting command in /workspace/site",
|
|
488
|
+
"cmux: waiting for remote ports",
|
|
489
|
+
"cmux: refreshing remote ports",
|
|
490
|
+
"cmux: opening http://localhost:4321",
|
|
491
|
+
"cmux: focusing workspace",
|
|
492
|
+
"cmux: ready website",
|
|
493
|
+
]);
|
|
494
|
+
});
|
|
495
|
+
|
|
496
|
+
test("forwards an explicit cmux ssh terminal startup command", async () => {
|
|
497
|
+
const calls: Array<{ method: string; params: unknown }> = [];
|
|
498
|
+
const client = fakeOpenClient(calls);
|
|
499
|
+
|
|
500
|
+
await openCmux({
|
|
501
|
+
name: "website",
|
|
502
|
+
ssh: {
|
|
503
|
+
kind: "ssh",
|
|
504
|
+
destination: "vm_123,token_123@vm-ssh.freestyle.sh",
|
|
505
|
+
terminalStartupCommand: "ssh -tt vm_123:token_123@vm-ssh.freestyle.sh",
|
|
506
|
+
},
|
|
507
|
+
}, { client });
|
|
508
|
+
|
|
509
|
+
expect(calls[0]).toEqual({
|
|
510
|
+
method: "ssh",
|
|
511
|
+
params: expect.objectContaining({
|
|
512
|
+
destination: "vm_123,token_123@vm-ssh.freestyle.sh",
|
|
513
|
+
name: "website",
|
|
514
|
+
terminalStartupCommand: "ssh -tt vm_123:token_123@vm-ssh.freestyle.sh",
|
|
515
|
+
}),
|
|
516
|
+
});
|
|
493
517
|
});
|
|
494
518
|
|
|
495
519
|
test("exposes a provider facade that requests cmux.open from the local host", async () => {
|
|
496
520
|
const definition = cmux.provider();
|
|
497
521
|
expect(definition.providerId).toBe("cmux");
|
|
498
522
|
expect(definition.plugin).toBe(cmuxProviderPlugin);
|
|
499
|
-
expect(cmux.capabilities.open).toBe(CMUX_OPEN_CAPABILITY);
|
|
500
523
|
|
|
501
524
|
const controller = await cmuxProviderPlugin.createProvider({
|
|
502
525
|
provider: { providerId: "cmux", config: {} },
|
|
503
526
|
storage: memoryProviderStorage("cmux"),
|
|
527
|
+
hostStorage: memoryProviderStorage("cmux"),
|
|
528
|
+
local: { open: async () => {} },
|
|
504
529
|
});
|
|
505
|
-
const requests: Array<{ capability: string; params: unknown }> = [];
|
|
530
|
+
const requests: Array<{ capability: string; params: unknown; options: unknown }> = [];
|
|
506
531
|
const runtime = await controller.runtime({
|
|
507
532
|
workflow: "test",
|
|
508
533
|
nodePath: "operation.open",
|
|
@@ -513,8 +538,8 @@ describe("cmux sdk", () => {
|
|
|
513
538
|
metadata: () => {},
|
|
514
539
|
local: {
|
|
515
540
|
open: async () => {},
|
|
516
|
-
requestCapability: async <Result,>(capability: string, params: unknown) => {
|
|
517
|
-
requests.push({ capability, params });
|
|
541
|
+
requestCapability: async <Result,>(capability: string, params: unknown, options: unknown) => {
|
|
542
|
+
requests.push({ capability, params, options });
|
|
518
543
|
return { sessionId: "workspace-1", workspaceId: "workspace-1" } as Result;
|
|
519
544
|
},
|
|
520
545
|
},
|
|
@@ -526,6 +551,7 @@ describe("cmux sdk", () => {
|
|
|
526
551
|
{
|
|
527
552
|
capability: "cmux.open",
|
|
528
553
|
params: { name: "workspace" },
|
|
554
|
+
options: { nodePath: "operation.open" },
|
|
529
555
|
},
|
|
530
556
|
]);
|
|
531
557
|
expect(session.sessionId).toBe("workspace-1");
|
|
@@ -542,6 +568,8 @@ describe("cmux sdk", () => {
|
|
|
542
568
|
const controller = await cmuxProviderPlugin.createProvider({
|
|
543
569
|
provider: { providerId: "cmux", config: {} },
|
|
544
570
|
storage: memoryProviderStorage("cmux"),
|
|
571
|
+
hostStorage: memoryProviderStorage("cmux"),
|
|
572
|
+
local: { open: async () => {} },
|
|
545
573
|
});
|
|
546
574
|
let resolveClosed!: () => void;
|
|
547
575
|
const runtime = await controller.runtime({
|
|
@@ -554,9 +582,10 @@ describe("cmux sdk", () => {
|
|
|
554
582
|
metadata: () => {},
|
|
555
583
|
local: {
|
|
556
584
|
open: async () => {},
|
|
557
|
-
requestCapabilitySession: async <Result,>(capability: string, params: unknown) => {
|
|
585
|
+
requestCapabilitySession: async <Result,>(capability: string, params: unknown, options: unknown) => {
|
|
558
586
|
expect(capability).toBe("cmux.open");
|
|
559
587
|
expect(params).toEqual({ name: "workspace" });
|
|
588
|
+
expect(options).toEqual({ nodePath: "operation.open" });
|
|
560
589
|
return {
|
|
561
590
|
result: { sessionId: "workspace-1", workspaceId: "workspace-1" } as Result,
|
|
562
591
|
closed: new Promise<void>((resolve) => {
|
package/src/index.ts
CHANGED
package/src/provider.ts
CHANGED
|
@@ -5,7 +5,6 @@ import {
|
|
|
5
5
|
} from "@rigkit/sdk";
|
|
6
6
|
import type { BaseProviderPlugin, WorkflowProviderController } from "@rigkit/engine";
|
|
7
7
|
import {
|
|
8
|
-
CMUX_OPEN_CAPABILITY,
|
|
9
8
|
CMUX_OPEN_CAPABILITY_ID,
|
|
10
9
|
type CmuxOpenInput,
|
|
11
10
|
type CmuxOpenResult,
|
|
@@ -30,10 +29,6 @@ export function provider(): CmuxProviderDefinition {
|
|
|
30
29
|
|
|
31
30
|
export const cmux = {
|
|
32
31
|
provider,
|
|
33
|
-
capability: CMUX_OPEN_CAPABILITY,
|
|
34
|
-
capabilities: {
|
|
35
|
-
open: CMUX_OPEN_CAPABILITY,
|
|
36
|
-
},
|
|
37
32
|
};
|
|
38
33
|
|
|
39
34
|
export const cmuxProviderPlugin: BaseProviderPlugin = {
|
|
@@ -42,37 +37,43 @@ export const cmuxProviderPlugin: BaseProviderPlugin = {
|
|
|
42
37
|
return {
|
|
43
38
|
providerId: CMUX_PROVIDER_ID,
|
|
44
39
|
runtime(context) {
|
|
45
|
-
return createCmuxRuntime(context.local);
|
|
40
|
+
return createCmuxRuntime(context.local, context.nodePath);
|
|
46
41
|
},
|
|
47
42
|
};
|
|
48
43
|
},
|
|
49
44
|
};
|
|
50
45
|
|
|
51
|
-
function createCmuxRuntime(local: LocalWorkspaceRuntime): CmuxRuntime {
|
|
46
|
+
function createCmuxRuntime(local: LocalWorkspaceRuntime, nodePath: string): CmuxRuntime {
|
|
47
|
+
return {
|
|
48
|
+
open: async (input) => await requestCmuxOpen(local, input, { nodePath }),
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export async function requestCmuxOpen(
|
|
53
|
+
local: LocalWorkspaceRuntime,
|
|
54
|
+
input: CmuxOpenInput,
|
|
55
|
+
options: { nodePath?: string } = {},
|
|
56
|
+
): Promise<CmuxOpenSession> {
|
|
57
|
+
if (local.requestCapabilitySession) {
|
|
58
|
+
const session = await local.requestCapabilitySession<CmuxOpenResult>(CMUX_OPEN_CAPABILITY_ID, input, options);
|
|
59
|
+
return {
|
|
60
|
+
...parseCmuxOpenResult(session.result),
|
|
61
|
+
closed: session.closed,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
if (!local.requestCapability) {
|
|
65
|
+
throw new Error(`Host capability ${CMUX_OPEN_CAPABILITY_ID} is unavailable in this runtime`);
|
|
66
|
+
}
|
|
67
|
+
const result = parseCmuxOpenResult(
|
|
68
|
+
await local.requestCapability(CMUX_OPEN_CAPABILITY_ID, input, options),
|
|
69
|
+
);
|
|
52
70
|
return {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
const session = await local.requestCapabilitySession<CmuxOpenResult>(CMUX_OPEN_CAPABILITY_ID, input);
|
|
56
|
-
return {
|
|
57
|
-
...parseCmuxOpenResult(session.result),
|
|
58
|
-
closed: session.closed,
|
|
59
|
-
};
|
|
60
|
-
}
|
|
61
|
-
if (!local.requestCapability) {
|
|
62
|
-
throw new Error(`Host capability ${CMUX_OPEN_CAPABILITY_ID} is unavailable in this runtime`);
|
|
63
|
-
}
|
|
64
|
-
const result = parseCmuxOpenResult(
|
|
65
|
-
await local.requestCapability(CMUX_OPEN_CAPABILITY_ID, input),
|
|
66
|
-
);
|
|
67
|
-
return {
|
|
68
|
-
...result,
|
|
69
|
-
closed: new Promise<void>(() => {}),
|
|
70
|
-
};
|
|
71
|
-
},
|
|
71
|
+
...result,
|
|
72
|
+
closed: new Promise<void>(() => {}),
|
|
72
73
|
};
|
|
73
74
|
}
|
|
74
75
|
|
|
75
|
-
function parseCmuxOpenResult(value: unknown): CmuxOpenResult {
|
|
76
|
+
export function parseCmuxOpenResult(value: unknown): CmuxOpenResult {
|
|
76
77
|
if (!isRecord(value)) throw new Error(`cmux.open returned a non-object result`);
|
|
77
78
|
const sessionId = stringField(value, "sessionId");
|
|
78
79
|
if (!sessionId) throw new Error(`cmux.open result is missing sessionId`);
|
package/src/version.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const RIGKIT_PROVIDER_CMUX_VERSION = "0.2.
|
|
1
|
+
export const RIGKIT_PROVIDER_CMUX_VERSION = "0.2.4";
|