@rigkit/sdk 0.2.2 → 0.2.3
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/package.json +3 -3
- package/src/index.test.ts +1 -1
- package/src/index.ts +0 -2
- package/src/runtime/api.ts +0 -2
- package/src/runtime/app.test.ts +50 -78
- package/src/runtime/control.ts +39 -8
- package/src/runtime/index.ts +0 -2
- package/src/runtime/operations.ts +8 -57
- package/src/runtime/protocol.ts +2 -21
- package/src/runtime/sessions.ts +0 -56
- package/src/runtime/version.ts +1 -1
- package/src/version.ts +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rigkit/sdk",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.3",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -23,8 +23,8 @@
|
|
|
23
23
|
"@effect/platform": "0.96.1",
|
|
24
24
|
"@effect/platform-bun": "0.89.0",
|
|
25
25
|
"effect": "^3.21.2",
|
|
26
|
-
"@rigkit/engine": "0.2.
|
|
27
|
-
"@rigkit/runtime-client": "0.2.
|
|
26
|
+
"@rigkit/engine": "0.2.3",
|
|
27
|
+
"@rigkit/runtime-client": "0.2.3"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
30
|
"@types/bun": "latest",
|
package/src/index.test.ts
CHANGED
|
@@ -16,7 +16,7 @@ import { defineHostCapabilities, defineHostCapability } from "./host.ts";
|
|
|
16
16
|
|
|
17
17
|
describe("@rigkit/sdk package boundary", () => {
|
|
18
18
|
test("exports authoring API and project runtime entrypoints", () => {
|
|
19
|
-
expect(RIGKIT_SDK_VERSION).toBe("0.2.
|
|
19
|
+
expect(RIGKIT_SDK_VERSION).toBe("0.2.3");
|
|
20
20
|
expect(env).toBeTypeOf("function");
|
|
21
21
|
expect(env.secret).toBeTypeOf("function");
|
|
22
22
|
expect(defineConfig).toBeTypeOf("function");
|
package/src/index.ts
CHANGED
|
@@ -19,12 +19,10 @@ export {
|
|
|
19
19
|
DEFAULT_IDLE_MS,
|
|
20
20
|
RIGKIT_RUNTIME_VERSION,
|
|
21
21
|
createRuntimeStateService,
|
|
22
|
-
HostCapabilityRequirementEffectSchema,
|
|
23
22
|
HostCommandRequestEffectSchema,
|
|
24
23
|
HostCommandRequestSchema,
|
|
25
24
|
HostCommandResultEffectSchema,
|
|
26
25
|
HostCommandResultSchema,
|
|
27
|
-
HostMethodRequirementEffectSchema,
|
|
28
26
|
HostResponseEffectSchema,
|
|
29
27
|
HostResponseSchema,
|
|
30
28
|
OkResponseEffectSchema,
|
package/src/runtime/api.ts
CHANGED
|
@@ -3,8 +3,6 @@ import { runtimeControlApi } from "@rigkit/runtime-client";
|
|
|
3
3
|
|
|
4
4
|
export {
|
|
5
5
|
RuntimeControlHealthEffectSchema as RuntimeHealthEffectSchema,
|
|
6
|
-
RuntimeControlHostCapabilityRequirementEffectSchema as HostCapabilityRequirementEffectSchema,
|
|
7
|
-
RuntimeControlHostMethodRequirementEffectSchema as HostMethodRequirementEffectSchema,
|
|
8
6
|
RuntimeControlMetadataEffectSchema as RuntimeMetadataEffectSchema,
|
|
9
7
|
RuntimeControlOkResponseEffectSchema as OkResponseEffectSchema,
|
|
10
8
|
RuntimeControlOperationCliEffectSchema as RuntimeOperationCliEffectSchema,
|
package/src/runtime/app.test.ts
CHANGED
|
@@ -237,11 +237,10 @@ describe("runtime HTTP app", () => {
|
|
|
237
237
|
scheme: "bearer",
|
|
238
238
|
});
|
|
239
239
|
expect(body.components.schemas.RuntimeOperation.required).toContain("inputSchema");
|
|
240
|
-
expect(body.components.schemas.Workspace.required).toContain("
|
|
240
|
+
expect(body.components.schemas.Workspace.required).toContain("ctx");
|
|
241
241
|
expect(body.components.schemas.OperationsManifest.required).toEqual([
|
|
242
|
-
"hostMethods",
|
|
243
|
-
"hostCapabilities",
|
|
244
242
|
"operations",
|
|
243
|
+
"workspaceOperations",
|
|
245
244
|
]);
|
|
246
245
|
});
|
|
247
246
|
|
|
@@ -277,7 +276,6 @@ describe("runtime HTTP app", () => {
|
|
|
277
276
|
kind: "command",
|
|
278
277
|
title: "SSH",
|
|
279
278
|
description: "Get an SSH command",
|
|
280
|
-
requiredHostMethods: [{ id: "host.command.run", modes: ["interactive"] }],
|
|
281
279
|
inputFields: [
|
|
282
280
|
{ kind: "string", name: "workflow", required: false },
|
|
283
281
|
{ kind: "string", name: "workspaceOrVmId", position: 0, required: true },
|
|
@@ -299,9 +297,6 @@ describe("runtime HTTP app", () => {
|
|
|
299
297
|
source: "config",
|
|
300
298
|
title: "Open",
|
|
301
299
|
description: "Open a workspace",
|
|
302
|
-
createsWorkspace: false,
|
|
303
|
-
requiredHostMethods: [{ id: "host.command.run", modes: ["interactive"] }],
|
|
304
|
-
requiredHostCapabilities: [{ id: "cmux.open", schemaHash: "sha256:cmux-open-schema" }],
|
|
305
300
|
inputFields: [
|
|
306
301
|
{
|
|
307
302
|
kind: "workspace",
|
|
@@ -319,33 +314,47 @@ describe("runtime HTTP app", () => {
|
|
|
319
314
|
},
|
|
320
315
|
],
|
|
321
316
|
},
|
|
317
|
+
{
|
|
318
|
+
workflow: "",
|
|
319
|
+
id: "create",
|
|
320
|
+
source: "core",
|
|
321
|
+
kind: "command",
|
|
322
|
+
createsWorkspace: true,
|
|
323
|
+
inputFields: [{ kind: "string", name: "name", required: true }],
|
|
324
|
+
},
|
|
325
|
+
],
|
|
326
|
+
listRuntimeWorkspaceOperations: () => [
|
|
322
327
|
{
|
|
323
328
|
workflow: "test",
|
|
324
|
-
id: "
|
|
329
|
+
id: "remove",
|
|
330
|
+
source: "core",
|
|
331
|
+
kind: "workspace-action",
|
|
332
|
+
title: "Remove",
|
|
333
|
+
description: "Remove a workspace",
|
|
334
|
+
inputFields: [],
|
|
335
|
+
},
|
|
336
|
+
{
|
|
337
|
+
workflow: "test",
|
|
338
|
+
id: "open-cmux",
|
|
325
339
|
source: "config",
|
|
326
|
-
|
|
340
|
+
kind: "workspace-action",
|
|
341
|
+
title: "Open cmux",
|
|
342
|
+
description: "Open a workspace in cmux",
|
|
327
343
|
inputFields: [],
|
|
328
344
|
},
|
|
329
345
|
],
|
|
330
346
|
} as any);
|
|
331
347
|
|
|
332
348
|
const operation = manifest.operations.find((item) => item.id === "open");
|
|
333
|
-
const
|
|
349
|
+
const createOperation = manifest.operations.find((item) => item.id === "create");
|
|
334
350
|
const sshOperation = manifest.operations.find((item) => item.id === "ssh");
|
|
351
|
+
const cmuxOperation = manifest.workspaceOperations.find((item) => item.id === "open-cmux");
|
|
335
352
|
const inputSchema = operation?.inputSchema as any;
|
|
336
353
|
const sshInputSchema = sshOperation?.inputSchema as any;
|
|
337
354
|
|
|
338
355
|
expect(operation?.source).toBe("config");
|
|
339
356
|
expect(operation?.kind).toBe("workspace-action");
|
|
340
|
-
expect(
|
|
341
|
-
{ id: "host.command.run", modes: ["interactive"] },
|
|
342
|
-
]);
|
|
343
|
-
expect(operation?.requiredHostCapabilities).toEqual([
|
|
344
|
-
{ id: "cmux.open", schemaHash: "sha256:cmux-open-schema" },
|
|
345
|
-
]);
|
|
346
|
-
expect(manifest.hostCapabilities.optional).toEqual([
|
|
347
|
-
{ id: "cmux.open", schemaHash: "sha256:cmux-open-schema" },
|
|
348
|
-
]);
|
|
357
|
+
expect(cmuxOperation?.id).toBe("open-cmux");
|
|
349
358
|
expect(operation?.cli?.positionals).toEqual([{ name: "workspace", index: 0 }]);
|
|
350
359
|
expect(operation?.cli?.options).toEqual([
|
|
351
360
|
{ name: "rebuild", flag: "--rebuild", required: false, type: "boolean" },
|
|
@@ -361,9 +370,9 @@ describe("runtime HTTP app", () => {
|
|
|
361
370
|
default: false,
|
|
362
371
|
description: "Rebuild before opening",
|
|
363
372
|
});
|
|
364
|
-
expect(
|
|
365
|
-
expect(
|
|
366
|
-
expect(manifest.
|
|
373
|
+
expect(createOperation?.source).toBe("core");
|
|
374
|
+
expect(createOperation?.createsWorkspace).toBe(true);
|
|
375
|
+
expect(manifest.workspaceOperations.map((item) => item.id)).toEqual(["remove", "open-cmux"]);
|
|
367
376
|
expect(sshOperation?.cli?.options?.find((item) => item.name === "print")).toEqual({
|
|
368
377
|
name: "print",
|
|
369
378
|
flag: "--print",
|
|
@@ -447,8 +456,6 @@ describe("runtime HTTP app", () => {
|
|
|
447
456
|
|
|
448
457
|
expect(ack?.operation).toEqual({
|
|
449
458
|
id: "plan",
|
|
450
|
-
requiredHostCapabilities: [],
|
|
451
|
-
requiredHostMethods: [],
|
|
452
459
|
});
|
|
453
460
|
expect(messages.some((message) => message.type === "heartbeat.ack")).toBe(true);
|
|
454
461
|
expect(messages.some((message) => message.type === "run.completed")).toBe(true);
|
|
@@ -457,21 +464,24 @@ describe("runtime HTTP app", () => {
|
|
|
457
464
|
}
|
|
458
465
|
});
|
|
459
466
|
|
|
460
|
-
test("exposes persisted workspace payload as workspace
|
|
461
|
-
const projectDir = mkdtempSync(join(tmpdir(), "rigkit-runtime-workspace-
|
|
467
|
+
test("exposes persisted workspace payload as workspace context", async () => {
|
|
468
|
+
const projectDir = mkdtempSync(join(tmpdir(), "rigkit-runtime-workspace-ctx-"));
|
|
462
469
|
const configPath = join(projectDir, "rig.config.ts");
|
|
463
470
|
writeFileSync(
|
|
464
471
|
configPath,
|
|
465
472
|
`
|
|
466
473
|
import { defineConfig, sequence } from "${import.meta.dir}/../../../engine/src/index.ts";
|
|
467
474
|
|
|
468
|
-
const root = sequence("workspace-
|
|
475
|
+
const root = sequence("workspace-ctx")
|
|
469
476
|
.step("prepare", async () => ({ repoPath: "/workspace/repo" }))
|
|
470
|
-
.
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
477
|
+
.workspace({
|
|
478
|
+
create: async ({ workflow, workspace }) => ({
|
|
479
|
+
name: workspace.name,
|
|
480
|
+
vmId: "vm-" + workspace.name,
|
|
481
|
+
repoPath: workflow.ctx.repoPath,
|
|
482
|
+
}),
|
|
483
|
+
remove: async () => {},
|
|
484
|
+
});
|
|
475
485
|
|
|
476
486
|
export default defineConfig({
|
|
477
487
|
providers: {},
|
|
@@ -481,7 +491,7 @@ describe("runtime HTTP app", () => {
|
|
|
481
491
|
);
|
|
482
492
|
|
|
483
493
|
const server = await serveRuntime({
|
|
484
|
-
projectId: "project-workspace-
|
|
494
|
+
projectId: "project-workspace-ctx-test",
|
|
485
495
|
projectDir,
|
|
486
496
|
configPath,
|
|
487
497
|
statePath: join(projectDir, "state.sqlite"),
|
|
@@ -505,14 +515,13 @@ describe("runtime HTTP app", () => {
|
|
|
505
515
|
|
|
506
516
|
const { workspaces } = await fetch(new URL("/workspaces", server.url), {
|
|
507
517
|
headers: { authorization: `Bearer ${server.token}` },
|
|
508
|
-
}).then((response) => response.json() as Promise<{ workspaces: Array<{
|
|
518
|
+
}).then((response) => response.json() as Promise<{ workspaces: Array<{ ctx: Record<string, unknown> }> }>);
|
|
509
519
|
|
|
510
|
-
expect(workspaces[0]?.
|
|
520
|
+
expect(workspaces[0]?.ctx).toEqual({
|
|
511
521
|
name: "demo",
|
|
512
|
-
|
|
522
|
+
vmId: "vm-demo",
|
|
513
523
|
repoPath: "/workspace/repo",
|
|
514
524
|
});
|
|
515
|
-
expect(workspaces[0]?.metadata).toEqual(workspaces[0]?.data);
|
|
516
525
|
} finally {
|
|
517
526
|
server.stop();
|
|
518
527
|
}
|
|
@@ -528,7 +537,10 @@ describe("runtime HTTP app", () => {
|
|
|
528
537
|
|
|
529
538
|
const root = sequence("validation")
|
|
530
539
|
.step("prepare", async () => ({ ok: true }))
|
|
531
|
-
.
|
|
540
|
+
.workspace({
|
|
541
|
+
create: async ({ workspace }) => ({ name: workspace.name, vmId: "vm-" + workspace.name }),
|
|
542
|
+
remove: async () => {},
|
|
543
|
+
});
|
|
532
544
|
|
|
533
545
|
export default defineConfig({
|
|
534
546
|
providers: {},
|
|
@@ -574,46 +586,9 @@ describe("runtime HTTP app", () => {
|
|
|
574
586
|
}
|
|
575
587
|
});
|
|
576
588
|
|
|
577
|
-
test("fails run sessions when host hello lacks required methods or capabilities", async () => {
|
|
578
|
-
const { server, projectDir } = await serveRuntimeFixture("rigkit-runtime-required-host-", `
|
|
579
|
-
const root = sequence("required-host").operation("needs-host", {
|
|
580
|
-
requiredHostMethods: [{ id: "host.command.run", modes: ["capture"] }],
|
|
581
|
-
requiredHostCapabilities: [{ id: "cmux.open", schemaHash: "sha256:cmux-open-schema" }],
|
|
582
|
-
run: async () => await new Promise(() => {}),
|
|
583
|
-
});
|
|
584
|
-
|
|
585
|
-
export default defineConfig({
|
|
586
|
-
providers: {},
|
|
587
|
-
workflows: { root },
|
|
588
|
-
});
|
|
589
|
-
`);
|
|
590
|
-
|
|
591
|
-
try {
|
|
592
|
-
const started = await startRun(server, "needs-host");
|
|
593
|
-
const messages = await collectSessionMessages(
|
|
594
|
-
new URL(started.sessionUrl, server.url),
|
|
595
|
-
server.token,
|
|
596
|
-
{
|
|
597
|
-
done: (items) => items.some((item) => item.type === "run.failed"),
|
|
598
|
-
},
|
|
599
|
-
);
|
|
600
|
-
const failed = messages.find((message) => message.type === "run.failed");
|
|
601
|
-
const message = String(failed?.error?.message ?? "");
|
|
602
|
-
|
|
603
|
-
expect(failed?.error?.code).toBe("HOST_REQUEST_FAILED");
|
|
604
|
-
expect(message).toContain("host method host.command.run:capture");
|
|
605
|
-
expect(message).toContain("host capability cmux.open@sha256:cmux-open-schema");
|
|
606
|
-
expect(messages.some((item) => item.type === "hello.ack")).toBe(false);
|
|
607
|
-
} finally {
|
|
608
|
-
server.stop();
|
|
609
|
-
rmSync(projectDir, { recursive: true, force: true });
|
|
610
|
-
}
|
|
611
|
-
});
|
|
612
|
-
|
|
613
589
|
test("bridges typed host capability requests over run sessions", async () => {
|
|
614
590
|
const { server, projectDir } = await serveRuntimeFixture("rigkit-runtime-capability-", `
|
|
615
591
|
const root = sequence("capability-test").operation("open", {
|
|
616
|
-
requiredHostCapabilities: [{ id: "cmux.open", schemaHash: "sha256:cmux-open-schema" }],
|
|
617
592
|
run: async ({ local }) => await local.requestCapability("cmux.open", { name: "demo" }),
|
|
618
593
|
});
|
|
619
594
|
|
|
@@ -659,7 +634,6 @@ describe("runtime HTTP app", () => {
|
|
|
659
634
|
test("resolves host capability resource lifetimes from session close reports", async () => {
|
|
660
635
|
const { server, projectDir } = await serveRuntimeFixture("rigkit-runtime-capability-close-", `
|
|
661
636
|
const root = sequence("capability-close-test").operation("open", {
|
|
662
|
-
requiredHostCapabilities: [{ id: "cmux.open", schemaHash: "sha256:cmux-open-schema" }],
|
|
663
637
|
run: async ({ local }) => {
|
|
664
638
|
if (!local.requestCapabilitySession) throw new Error("requestCapabilitySession unavailable");
|
|
665
639
|
const session = await local.requestCapabilitySession("cmux.open", { name: "demo" });
|
|
@@ -708,7 +682,6 @@ describe("runtime HTTP app", () => {
|
|
|
708
682
|
test("keeps host-owned capability runs attached until the host cancels", async () => {
|
|
709
683
|
const { server, projectDir } = await serveRuntimeFixture("rigkit-runtime-capability-attached-", `
|
|
710
684
|
const root = sequence("capability-attached-test").operation("open", {
|
|
711
|
-
requiredHostCapabilities: [{ id: "cmux.open", schemaHash: "sha256:cmux-open-schema" }],
|
|
712
685
|
run: async ({ local }) => {
|
|
713
686
|
await local.requestCapability("cmux.open", { name: "demo" });
|
|
714
687
|
await new Promise(() => {});
|
|
@@ -755,7 +728,6 @@ describe("runtime HTTP app", () => {
|
|
|
755
728
|
test("turns host response errors into typed host request failures", async () => {
|
|
756
729
|
const { server, projectDir } = await serveRuntimeFixture("rigkit-runtime-capability-error-", `
|
|
757
730
|
const root = sequence("capability-error-test").operation("cmux-open", {
|
|
758
|
-
requiredHostCapabilities: [{ id: "cmux.open", schemaHash: "sha256:cmux-open-schema" }],
|
|
759
731
|
run: async ({ local }) => await local.requestCapability("cmux.open", { name: "demo" }),
|
|
760
732
|
});
|
|
761
733
|
|
package/src/runtime/control.ts
CHANGED
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
type HostResponse,
|
|
10
10
|
type RunOperationRequest,
|
|
11
11
|
type RuntimeOperation,
|
|
12
|
+
type RuntimeOperationsManifest,
|
|
12
13
|
} from "./protocol.ts";
|
|
13
14
|
import {
|
|
14
15
|
createRun,
|
|
@@ -87,10 +88,10 @@ export function runtimeRuns(store: RunStore) {
|
|
|
87
88
|
export async function startRuntimeRun(state: RuntimeAppState, body: RunOperationRequest) {
|
|
88
89
|
const engine = await loadEngine(state.context);
|
|
89
90
|
const manifest = operationManifestFor(engine);
|
|
90
|
-
const
|
|
91
|
-
if (!
|
|
91
|
+
const resolved = resolveRuntimeOperation(manifest, body.operation);
|
|
92
|
+
if (!resolved) throw new RuntimeControlHttpError(400, `Unknown operation ${body.operation}`);
|
|
92
93
|
|
|
93
|
-
const run = createRun(
|
|
94
|
+
const run = createRun(resolved.runOperation, body.input ?? {}, resolved.operation);
|
|
94
95
|
state.store.runs.set(run.id, run);
|
|
95
96
|
runOperation(run, state.store, state.context);
|
|
96
97
|
|
|
@@ -144,16 +145,46 @@ export function runtimeControlErrorStatus(error: unknown): number {
|
|
|
144
145
|
return 500;
|
|
145
146
|
}
|
|
146
147
|
|
|
147
|
-
function
|
|
148
|
-
|
|
148
|
+
function resolveRuntimeOperation(
|
|
149
|
+
manifest: RuntimeOperationsManifest,
|
|
150
|
+
requestedOperation: string,
|
|
151
|
+
): { operation: RuntimeOperation; runOperation: string } | undefined {
|
|
152
|
+
const workspaceOperation = parseWorkspaceOperationId(requestedOperation);
|
|
153
|
+
if (workspaceOperation) {
|
|
154
|
+
const operation = manifest.workspaceOperations.find((item) => item.id === workspaceOperation.operation);
|
|
155
|
+
return operation ? { operation, runOperation: requestedOperation } : undefined;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const operation = manifest.operations.find((operation) =>
|
|
149
159
|
operation.id === requestedOperation || operation.aliases?.includes(requestedOperation)
|
|
150
160
|
);
|
|
161
|
+
return operation ? { operation, runOperation: operation.id } : undefined;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
function parseWorkspaceOperationId(value: string): { workspace: string; operation: string } | undefined {
|
|
165
|
+
const slash = value.indexOf("/");
|
|
166
|
+
if (slash <= 0 || slash === value.length - 1) return undefined;
|
|
167
|
+
return {
|
|
168
|
+
workspace: value.slice(0, slash),
|
|
169
|
+
operation: value.slice(slash + 1),
|
|
170
|
+
};
|
|
151
171
|
}
|
|
152
172
|
|
|
153
|
-
function runtimeWorkspace(workspace: WorkspaceRecord):
|
|
173
|
+
function runtimeWorkspace(workspace: WorkspaceRecord): {
|
|
174
|
+
id: string;
|
|
175
|
+
name: string;
|
|
176
|
+
workflow: string;
|
|
177
|
+
ctx: WorkspaceRecord["ctx"];
|
|
178
|
+
createdAt: string;
|
|
179
|
+
updatedAt: string;
|
|
180
|
+
} {
|
|
154
181
|
return {
|
|
155
|
-
|
|
156
|
-
|
|
182
|
+
id: workspace.id,
|
|
183
|
+
name: workspace.name,
|
|
184
|
+
workflow: workspace.workflow,
|
|
185
|
+
ctx: workspace.ctx,
|
|
186
|
+
createdAt: workspace.createdAt,
|
|
187
|
+
updatedAt: workspace.updatedAt,
|
|
157
188
|
};
|
|
158
189
|
}
|
|
159
190
|
|
package/src/runtime/index.ts
CHANGED
|
@@ -100,6 +100,12 @@ export function operationsFor(engine: DevMachineEngine): RuntimeOperation[] {
|
|
|
100
100
|
return engine.listRuntimeOperations().map((operation) => runtimeOperationForEngineOperation(engine, operation));
|
|
101
101
|
}
|
|
102
102
|
|
|
103
|
+
export function workspaceOperationsFor(engine: DevMachineEngine): RuntimeOperation[] {
|
|
104
|
+
return engine.listRuntimeWorkspaceOperations().map((operation) =>
|
|
105
|
+
runtimeOperationForEngineOperation(engine, operation)
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
|
|
103
109
|
function runtimeOperationForEngineOperation(engine: DevMachineEngine, operation: EngineOperationSummary): RuntimeOperation {
|
|
104
110
|
const required = operation.inputFields
|
|
105
111
|
.filter((field) => field.required ?? true)
|
|
@@ -116,14 +122,6 @@ function runtimeOperationForEngineOperation(engine: DevMachineEngine, operation:
|
|
|
116
122
|
title: operation.title ?? titleize(operation.id),
|
|
117
123
|
description: operation.description ?? "",
|
|
118
124
|
createsWorkspace: operation.createsWorkspace,
|
|
119
|
-
requiredHostMethods: operation.requiredHostMethods?.map((method) => ({
|
|
120
|
-
id: method.id,
|
|
121
|
-
...(method.modes?.length ? { modes: [...method.modes] } : {}),
|
|
122
|
-
})),
|
|
123
|
-
requiredHostCapabilities: operation.requiredHostCapabilities?.map((capability) => ({
|
|
124
|
-
id: capability.id,
|
|
125
|
-
...(capability.schemaHash ? { schemaHash: capability.schemaHash } : {}),
|
|
126
|
-
})),
|
|
127
125
|
cli: operation.cli ? cloneOperationCli(operation.cli) : cliForFields(operation.inputFields),
|
|
128
126
|
inputSchema: objectSchema(properties, required),
|
|
129
127
|
};
|
|
@@ -188,60 +186,13 @@ function cliForFields(fields: EngineOperationSummary["inputFields"]): NonNullabl
|
|
|
188
186
|
|
|
189
187
|
export function operationManifestFor(engine: DevMachineEngine): RuntimeOperationsManifest {
|
|
190
188
|
const operations = operationsFor(engine);
|
|
189
|
+
const workspaceOperations = workspaceOperationsFor(engine);
|
|
191
190
|
return {
|
|
192
|
-
hostMethods: {
|
|
193
|
-
known: [
|
|
194
|
-
{ id: "message.show" },
|
|
195
|
-
{ id: "prompt.text" },
|
|
196
|
-
{ id: "prompt.confirm" },
|
|
197
|
-
{ id: "prompt.select" },
|
|
198
|
-
{ id: "open.external" },
|
|
199
|
-
{ id: "host.command.run", modes: ["capture", "interactive"] },
|
|
200
|
-
],
|
|
201
|
-
requiredByOperations: Object.fromEntries(
|
|
202
|
-
operations
|
|
203
|
-
.filter((operation) => operation.requiredHostMethods?.length)
|
|
204
|
-
.map((operation) => [
|
|
205
|
-
operation.id,
|
|
206
|
-
operation.requiredHostMethods!.flatMap((method) =>
|
|
207
|
-
method.modes?.length
|
|
208
|
-
? method.modes.map((mode) => `${method.id}:${mode}`)
|
|
209
|
-
: [method.id]
|
|
210
|
-
),
|
|
211
|
-
]),
|
|
212
|
-
),
|
|
213
|
-
},
|
|
214
|
-
hostCapabilities: {
|
|
215
|
-
optional: dedupeHostCapabilities(
|
|
216
|
-
operations.flatMap((operation) => operation.requiredHostCapabilities ?? []),
|
|
217
|
-
),
|
|
218
|
-
requiredByOperations: Object.fromEntries(
|
|
219
|
-
operations
|
|
220
|
-
.filter((operation) => operation.requiredHostCapabilities?.length)
|
|
221
|
-
.map((operation) => [operation.id, operation.requiredHostCapabilities!.map((capability) => capability.id)]),
|
|
222
|
-
),
|
|
223
|
-
},
|
|
224
191
|
operations,
|
|
192
|
+
workspaceOperations,
|
|
225
193
|
};
|
|
226
194
|
}
|
|
227
195
|
|
|
228
|
-
function dedupeHostCapabilities(
|
|
229
|
-
capabilities: Array<{ id: string; schemaHash?: string }>,
|
|
230
|
-
): Array<{ id: string; schemaHash?: string }> {
|
|
231
|
-
const seen = new Set<string>();
|
|
232
|
-
const deduped: Array<{ id: string; schemaHash?: string }> = [];
|
|
233
|
-
for (const capability of capabilities) {
|
|
234
|
-
const key = capability.schemaHash ? `${capability.id}\0${capability.schemaHash}` : capability.id;
|
|
235
|
-
if (seen.has(key)) continue;
|
|
236
|
-
seen.add(key);
|
|
237
|
-
deduped.push({
|
|
238
|
-
id: capability.id,
|
|
239
|
-
...(capability.schemaHash ? { schemaHash: capability.schemaHash } : {}),
|
|
240
|
-
});
|
|
241
|
-
}
|
|
242
|
-
return deduped;
|
|
243
|
-
}
|
|
244
|
-
|
|
245
196
|
function workflowJsonSchema(workflows: string[]): JsonSchema {
|
|
246
197
|
return workflows.length > 0
|
|
247
198
|
? { type: "string", enum: workflows }
|
package/src/runtime/protocol.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { Schema } from "effect";
|
|
|
2
2
|
import type { WorkflowEvent } from "@rigkit/engine";
|
|
3
3
|
|
|
4
4
|
export const RUNTIME_API_VERSION = 1;
|
|
5
|
-
export const RUNTIME_PROTOCOL_HASH = "sha256:
|
|
5
|
+
export const RUNTIME_PROTOCOL_HASH = "sha256:ac8d4a503b56c15b333ea51f57ab1f6fca776bea93f498120b10ab601cc0960a";
|
|
6
6
|
export const DEFAULT_IDLE_MS = 30 * 60 * 1000;
|
|
7
7
|
|
|
8
8
|
export class RuntimeProtocolSchemaError extends Error {
|
|
@@ -147,16 +147,6 @@ export type RuntimeOperationCli = {
|
|
|
147
147
|
options?: RuntimeOperationCliOption[];
|
|
148
148
|
};
|
|
149
149
|
|
|
150
|
-
export type RuntimeHostMethodRequirement = {
|
|
151
|
-
id: string;
|
|
152
|
-
modes?: string[];
|
|
153
|
-
};
|
|
154
|
-
|
|
155
|
-
export type RuntimeHostCapabilityRequirement = {
|
|
156
|
-
id: string;
|
|
157
|
-
schemaHash?: string;
|
|
158
|
-
};
|
|
159
|
-
|
|
160
150
|
export type RuntimeOperation = {
|
|
161
151
|
id: string;
|
|
162
152
|
aliases?: string[];
|
|
@@ -165,22 +155,13 @@ export type RuntimeOperation = {
|
|
|
165
155
|
title: string;
|
|
166
156
|
description: string;
|
|
167
157
|
createsWorkspace?: boolean;
|
|
168
|
-
requiredHostMethods?: RuntimeHostMethodRequirement[];
|
|
169
|
-
requiredHostCapabilities?: RuntimeHostCapabilityRequirement[];
|
|
170
158
|
cli?: RuntimeOperationCli;
|
|
171
159
|
inputSchema: JsonSchema;
|
|
172
160
|
};
|
|
173
161
|
|
|
174
162
|
export type RuntimeOperationsManifest = {
|
|
175
|
-
hostMethods: {
|
|
176
|
-
known: RuntimeHostMethodRequirement[];
|
|
177
|
-
requiredByOperations: Record<string, string[]>;
|
|
178
|
-
};
|
|
179
|
-
hostCapabilities: {
|
|
180
|
-
optional: RuntimeHostCapabilityRequirement[];
|
|
181
|
-
requiredByOperations: Record<string, string[]>;
|
|
182
|
-
};
|
|
183
163
|
operations: RuntimeOperation[];
|
|
164
|
+
workspaceOperations: RuntimeOperation[];
|
|
184
165
|
};
|
|
185
166
|
|
|
186
167
|
export function objectSchema(properties: Record<string, unknown>, required: string[] = []): JsonSchema {
|
package/src/runtime/sessions.ts
CHANGED
|
@@ -81,19 +81,6 @@ function openRunSession(
|
|
|
81
81
|
const message = parseSessionMessage(value);
|
|
82
82
|
if (!message) return;
|
|
83
83
|
if (message.type === "hello") {
|
|
84
|
-
const unsupported = unsupportedSessionRequirements(message, run.operationDefinition);
|
|
85
|
-
if (unsupported.length > 0) {
|
|
86
|
-
failRun(
|
|
87
|
-
run,
|
|
88
|
-
new RuntimeHostRequestError({
|
|
89
|
-
message: `Host does not support required ${unsupported.join(", ")}`,
|
|
90
|
-
}),
|
|
91
|
-
state.store,
|
|
92
|
-
);
|
|
93
|
-
acknowledged = true;
|
|
94
|
-
sendBacklog();
|
|
95
|
-
return;
|
|
96
|
-
}
|
|
97
84
|
acknowledged = true;
|
|
98
85
|
sendHelloAck(socket, run);
|
|
99
86
|
sendBacklog();
|
|
@@ -160,53 +147,10 @@ function sendHelloAck(ws: RuntimeSessionTransport, run: { operation: string; ope
|
|
|
160
147
|
},
|
|
161
148
|
operation: {
|
|
162
149
|
id: run.operation,
|
|
163
|
-
requiredHostCapabilities: run.operationDefinition?.requiredHostCapabilities ?? [],
|
|
164
|
-
requiredHostMethods: run.operationDefinition?.requiredHostMethods ?? [],
|
|
165
150
|
},
|
|
166
151
|
}));
|
|
167
152
|
}
|
|
168
153
|
|
|
169
|
-
function unsupportedSessionRequirements(message: SessionMessage, operation: RuntimeOperation | undefined): string[] {
|
|
170
|
-
const unsupported: string[] = [];
|
|
171
|
-
for (const requirement of operation?.requiredHostMethods ?? []) {
|
|
172
|
-
const hostMethod = sessionItems(message.hostMethods).find((item) => item.id === requirement.id);
|
|
173
|
-
if (!hostMethod || !supportsModes(hostMethod.modes, requirement.modes)) {
|
|
174
|
-
unsupported.push(`host method ${formatRequirement(requirement.id, requirement.modes)}`);
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
for (const requirement of operation?.requiredHostCapabilities ?? []) {
|
|
178
|
-
const capability = sessionItems(message.hostCapabilities).find((item) => item.id === requirement.id);
|
|
179
|
-
if (!capability || (requirement.schemaHash && capability.schemaHash !== requirement.schemaHash)) {
|
|
180
|
-
unsupported.push(requirement.schemaHash
|
|
181
|
-
? `host capability ${requirement.id}@${requirement.schemaHash}`
|
|
182
|
-
: `host capability ${requirement.id}`);
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
return unsupported;
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
function sessionItems(value: unknown): Array<{ id: string; modes?: string[]; schemaHash?: string }> {
|
|
189
|
-
if (!Array.isArray(value)) return [];
|
|
190
|
-
return value.flatMap((item) => {
|
|
191
|
-
if (!isRecord(item) || typeof item.id !== "string") return [];
|
|
192
|
-
return [{
|
|
193
|
-
id: item.id,
|
|
194
|
-
modes: Array.isArray(item.modes) ? item.modes.filter((mode): mode is string => typeof mode === "string") : undefined,
|
|
195
|
-
schemaHash: typeof item.schemaHash === "string" ? item.schemaHash : undefined,
|
|
196
|
-
}];
|
|
197
|
-
});
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
function supportsModes(hostModes: string[] | undefined, requiredModes: string[] | undefined): boolean {
|
|
201
|
-
if (!requiredModes?.length) return true;
|
|
202
|
-
const supported = new Set(hostModes ?? []);
|
|
203
|
-
return requiredModes.every((mode) => supported.has(mode));
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
function formatRequirement(id: string, modes: string[] | undefined): string {
|
|
207
|
-
return modes?.length ? `${id}:${modes.join("|")}` : id;
|
|
208
|
-
}
|
|
209
|
-
|
|
210
154
|
function sessionEvent(event: unknown): Record<string, unknown> {
|
|
211
155
|
if (isRecord(event) && event.type === "host.request") {
|
|
212
156
|
return {
|
package/src/runtime/version.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const RIGKIT_RUNTIME_VERSION = "0.2.
|
|
1
|
+
export const RIGKIT_RUNTIME_VERSION = "0.2.3";
|
package/src/version.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const RIGKIT_SDK_VERSION = "0.2.
|
|
1
|
+
export const RIGKIT_SDK_VERSION = "0.2.3";
|