@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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rigkit/sdk",
3
- "version": "0.2.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.2",
27
- "@rigkit/runtime-client": "0.2.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.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,
@@ -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,
@@ -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("data");
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: "fork",
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
- createsWorkspace: true,
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 forkOperation = manifest.operations.find((item) => item.id === "fork");
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(operation?.requiredHostMethods).toEqual([
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(forkOperation?.source).toBe("config");
365
- expect(forkOperation?.createsWorkspace).toBe(true);
366
- expect(manifest.operations.some((item) => item.id === "create")).toBe(false);
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 data", async () => {
461
- const projectDir = mkdtempSync(join(tmpdir(), "rigkit-runtime-workspace-data-"));
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-data")
475
+ const root = sequence("workspace-ctx")
469
476
  .step("prepare", async () => ({ repoPath: "/workspace/repo" }))
470
- .create(async ({ ctx, name }) => ({
471
- name,
472
- resourceId: "resource-" + name,
473
- repoPath: ctx.repoPath,
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-data-test",
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<{ data: Record<string, unknown>; metadata: Record<string, unknown> }> }>);
518
+ }).then((response) => response.json() as Promise<{ workspaces: Array<{ ctx: Record<string, unknown> }> }>);
509
519
 
510
- expect(workspaces[0]?.data).toEqual({
520
+ expect(workspaces[0]?.ctx).toEqual({
511
521
  name: "demo",
512
- resourceId: "resource-demo",
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
- .create(async ({ name }) => ({ name, resourceId: "resource-" + name }));
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
 
@@ -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 operation = findRuntimeOperation(manifest.operations, body.operation);
91
- if (!operation) throw new RuntimeControlHttpError(400, `Unknown operation ${body.operation}`);
91
+ const resolved = resolveRuntimeOperation(manifest, body.operation);
92
+ if (!resolved) throw new RuntimeControlHttpError(400, `Unknown operation ${body.operation}`);
92
93
 
93
- const run = createRun(operation.id, body.input ?? {}, operation);
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 findRuntimeOperation(operations: RuntimeOperation[], requestedOperation: string): RuntimeOperation | undefined {
148
- return operations.find((operation) =>
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): WorkspaceRecord & { data: WorkspaceRecord["metadata"] } {
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
- ...workspace,
156
- data: workspace.metadata,
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
 
@@ -35,8 +35,6 @@ export {
35
35
  type RuntimeStateServiceOptions,
36
36
  } from "./state.ts";
37
37
  export {
38
- HostCapabilityRequirementEffectSchema,
39
- HostMethodRequirementEffectSchema,
40
38
  OkResponseEffectSchema,
41
39
  OperationsManifestEffectSchema,
42
40
  ProjectInfoEffectSchema,
@@ -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 }
@@ -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:6dc28b06c95c98d310db445f1b19aef478cd828f11287467fe261483dfde4f81";
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 {
@@ -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 {
@@ -1 +1 @@
1
- export const RIGKIT_RUNTIME_VERSION = "0.2.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.2";
1
+ export const RIGKIT_SDK_VERSION = "0.2.3";