@rigkit/sdk 0.1.8
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 +19 -0
- package/package.json +41 -0
- package/src/cli.ts +116 -0
- package/src/host.ts +46 -0
- package/src/index.test.ts +53 -0
- package/src/index.ts +84 -0
- package/src/runtime/api-handlers.ts +166 -0
- package/src/runtime/api.ts +69 -0
- package/src/runtime/app.test.ts +924 -0
- package/src/runtime/app.ts +63 -0
- package/src/runtime/cli.ts +115 -0
- package/src/runtime/control.ts +163 -0
- package/src/runtime/errors.ts +108 -0
- package/src/runtime/index.ts +81 -0
- package/src/runtime/openapi.ts +5 -0
- package/src/runtime/operations.ts +267 -0
- package/src/runtime/protocol.ts +193 -0
- package/src/runtime/runs.ts +292 -0
- package/src/runtime/server.ts +182 -0
- package/src/runtime/sessions.ts +257 -0
- package/src/runtime/state.ts +12 -0
- package/src/runtime/token.ts +16 -0
- package/src/runtime/types.ts +35 -0
- package/src/runtime/version.ts +1 -0
- package/src/version.ts +1 -0
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createDevMachineEngine,
|
|
3
|
+
type DevMachineEngine,
|
|
4
|
+
type EngineOperationSummary,
|
|
5
|
+
type JsonValue,
|
|
6
|
+
} from "@rigkit/engine";
|
|
7
|
+
import { normalizeRuntimeRunError } from "./errors.ts";
|
|
8
|
+
import {
|
|
9
|
+
HostCommandResultSchema,
|
|
10
|
+
objectSchema,
|
|
11
|
+
type JsonSchema,
|
|
12
|
+
type RuntimeOperation,
|
|
13
|
+
type RuntimeOperationsManifest,
|
|
14
|
+
} from "./protocol.ts";
|
|
15
|
+
import {
|
|
16
|
+
completeRun,
|
|
17
|
+
emitRunEvent,
|
|
18
|
+
failRun,
|
|
19
|
+
requestHost,
|
|
20
|
+
requestHostCapability,
|
|
21
|
+
requestHostCapabilitySession,
|
|
22
|
+
type RunRecord,
|
|
23
|
+
type RunStore,
|
|
24
|
+
} from "./runs.ts";
|
|
25
|
+
import { createRuntimeStateService } from "./state.ts";
|
|
26
|
+
import { RIGKIT_RUNTIME_VERSION } from "./version.ts";
|
|
27
|
+
|
|
28
|
+
export type EngineLoadOptions = {
|
|
29
|
+
projectId?: string;
|
|
30
|
+
projectDir: string;
|
|
31
|
+
configPath: string;
|
|
32
|
+
statePath?: string;
|
|
33
|
+
source?: JsonValue;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export async function loadEngine(input: EngineLoadOptions): Promise<DevMachineEngine> {
|
|
37
|
+
const engine = await createDevMachineEngine({
|
|
38
|
+
projectDir: input.projectDir,
|
|
39
|
+
configPath: input.configPath,
|
|
40
|
+
state: createRuntimeStateService({
|
|
41
|
+
projectId: input.projectId,
|
|
42
|
+
projectDir: input.projectDir,
|
|
43
|
+
configPath: input.configPath,
|
|
44
|
+
statePath: input.statePath,
|
|
45
|
+
runtimeVersion: RIGKIT_RUNTIME_VERSION,
|
|
46
|
+
source: input.source,
|
|
47
|
+
}),
|
|
48
|
+
});
|
|
49
|
+
await engine.load();
|
|
50
|
+
return engine;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export function runOperation(run: RunRecord, store: RunStore, options: EngineLoadOptions): void {
|
|
54
|
+
executeOperation(run, store, options).catch((error) => failRun(run, normalizeRuntimeRunError(error), store));
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
async function executeOperation(run: RunRecord, store: RunStore, options: EngineLoadOptions): Promise<void> {
|
|
58
|
+
const engine = await createDevMachineEngine({
|
|
59
|
+
projectDir: options.projectDir,
|
|
60
|
+
configPath: options.configPath,
|
|
61
|
+
state: createRuntimeStateService({
|
|
62
|
+
projectId: options.projectId,
|
|
63
|
+
projectDir: options.projectDir,
|
|
64
|
+
configPath: options.configPath,
|
|
65
|
+
statePath: options.statePath,
|
|
66
|
+
runtimeVersion: RIGKIT_RUNTIME_VERSION,
|
|
67
|
+
source: options.source,
|
|
68
|
+
}),
|
|
69
|
+
interaction: {
|
|
70
|
+
present: async (request) => {
|
|
71
|
+
await requestHost(store, run, "open.external", {
|
|
72
|
+
target: request.url,
|
|
73
|
+
kind: "url",
|
|
74
|
+
label: request.title,
|
|
75
|
+
});
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
local: {
|
|
79
|
+
open: async (target) => {
|
|
80
|
+
await requestHost(store, run, "open.external", { target, kind: guessExternalKind(target) });
|
|
81
|
+
},
|
|
82
|
+
command: async (command) => {
|
|
83
|
+
const result = await requestHost(store, run, "host.command.run", command);
|
|
84
|
+
return HostCommandResultSchema.parse(result);
|
|
85
|
+
},
|
|
86
|
+
requestCapability: async <Result = unknown>(capability: string, params: unknown) =>
|
|
87
|
+
await requestHostCapability(store, run, capability, params) as Result,
|
|
88
|
+
requestCapabilitySession: async <Result = unknown>(capability: string, params: unknown) =>
|
|
89
|
+
await requestHostCapabilitySession<Result>(store, run, capability, params),
|
|
90
|
+
},
|
|
91
|
+
});
|
|
92
|
+
engine.onEvent((event) => emitRunEvent(run, event));
|
|
93
|
+
await engine.load();
|
|
94
|
+
|
|
95
|
+
const result = await engine.runRuntimeOperation({ operation: run.operation, input: run.input });
|
|
96
|
+
completeRun(run, result, store);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export function operationsFor(engine: DevMachineEngine): RuntimeOperation[] {
|
|
100
|
+
return engine.listRuntimeOperations().map((operation) => runtimeOperationForEngineOperation(engine, operation));
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function runtimeOperationForEngineOperation(engine: DevMachineEngine, operation: EngineOperationSummary): RuntimeOperation {
|
|
104
|
+
const required = operation.inputFields
|
|
105
|
+
.filter((field) => field.required ?? true)
|
|
106
|
+
.map((field) => field.name);
|
|
107
|
+
const properties = Object.fromEntries(
|
|
108
|
+
operation.inputFields.map((field) => [field.name, jsonSchemaForField(engine, operation, field)]),
|
|
109
|
+
);
|
|
110
|
+
const hasWorkspaceInput = operation.inputFields.some((field) => field.kind === "workspace");
|
|
111
|
+
return {
|
|
112
|
+
id: operation.id,
|
|
113
|
+
...(operation.aliases?.length ? { aliases: [...operation.aliases] } : {}),
|
|
114
|
+
kind: operation.kind ?? (hasWorkspaceInput ? "workspace-action" : "command"),
|
|
115
|
+
source: operation.source ?? "config",
|
|
116
|
+
title: operation.title ?? titleize(operation.id),
|
|
117
|
+
description: operation.description ?? "",
|
|
118
|
+
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
|
+
cli: operation.cli ? cloneOperationCli(operation.cli) : cliForFields(operation.inputFields),
|
|
128
|
+
inputSchema: objectSchema(properties, required),
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function jsonSchemaForField(
|
|
133
|
+
engine: DevMachineEngine,
|
|
134
|
+
operation: EngineOperationSummary,
|
|
135
|
+
field: EngineOperationSummary["inputFields"][number],
|
|
136
|
+
): JsonSchema {
|
|
137
|
+
const schema: JsonSchema = {
|
|
138
|
+
type: field.kind === "boolean" || field.kind === "number" ? field.kind : "string",
|
|
139
|
+
...(field.description ? { description: field.description } : {}),
|
|
140
|
+
...(field.defaultValue !== undefined ? { default: field.defaultValue } : {}),
|
|
141
|
+
};
|
|
142
|
+
if (field.kind === "string" && (field.required ?? true)) {
|
|
143
|
+
schema.minLength = 1;
|
|
144
|
+
}
|
|
145
|
+
if (field.name === "workflow") {
|
|
146
|
+
const workflows = engine.listWorkflows().map((workflow) => workflow.name);
|
|
147
|
+
Object.assign(schema, workflowJsonSchema(workflows));
|
|
148
|
+
}
|
|
149
|
+
if (field.kind === "workspace") {
|
|
150
|
+
schema["x-rigkit-input"] = {
|
|
151
|
+
kind: "workspace",
|
|
152
|
+
workflow: operation.workflow,
|
|
153
|
+
resolve: "data",
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
return schema;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
function cloneOperationCli(cli: NonNullable<EngineOperationSummary["cli"]>): NonNullable<RuntimeOperation["cli"]> {
|
|
160
|
+
return {
|
|
161
|
+
...(cli.positionals ? { positionals: cli.positionals.map((item) => ({ ...item })) } : {}),
|
|
162
|
+
...(cli.options
|
|
163
|
+
? {
|
|
164
|
+
options: cli.options.map((item) => ({
|
|
165
|
+
...item,
|
|
166
|
+
...(item.aliases ? { aliases: [...item.aliases] } : {}),
|
|
167
|
+
})),
|
|
168
|
+
}
|
|
169
|
+
: {}),
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
function cliForFields(fields: EngineOperationSummary["inputFields"]): NonNullable<RuntimeOperation["cli"]> {
|
|
174
|
+
return {
|
|
175
|
+
positionals: fields
|
|
176
|
+
.filter((field) => typeof field.position === "number")
|
|
177
|
+
.map((field) => ({ name: field.name, index: field.position! })),
|
|
178
|
+
options: fields
|
|
179
|
+
.filter((field) => typeof field.position !== "number")
|
|
180
|
+
.map((field) => ({
|
|
181
|
+
name: field.name,
|
|
182
|
+
flag: `--${dashCase(field.name)}`,
|
|
183
|
+
required: field.required ?? true,
|
|
184
|
+
type: field.kind === "boolean" || field.kind === "number" ? field.kind : "string",
|
|
185
|
+
})),
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
export function operationManifestFor(engine: DevMachineEngine): RuntimeOperationsManifest {
|
|
190
|
+
const operations = operationsFor(engine);
|
|
191
|
+
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
|
+
operations,
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
|
|
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
|
+
function workflowJsonSchema(workflows: string[]): JsonSchema {
|
|
246
|
+
return workflows.length > 0
|
|
247
|
+
? { type: "string", enum: workflows }
|
|
248
|
+
: { type: "string" };
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
function dashCase(value: string): string {
|
|
252
|
+
return value.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
function titleize(value: string): string {
|
|
256
|
+
return value
|
|
257
|
+
.split(/[-_.\s]+/g)
|
|
258
|
+
.filter(Boolean)
|
|
259
|
+
.map((part) => `${part.slice(0, 1).toUpperCase()}${part.slice(1)}`)
|
|
260
|
+
.join(" ");
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
function guessExternalKind(target: string): "url" | "file" | "unknown" {
|
|
264
|
+
if (/^[a-z][a-z0-9+.-]*:/i.test(target)) return "url";
|
|
265
|
+
if (target.startsWith("/")) return "file";
|
|
266
|
+
return "unknown";
|
|
267
|
+
}
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import { Schema } from "effect";
|
|
2
|
+
import type { WorkflowEvent } from "@rigkit/engine";
|
|
3
|
+
|
|
4
|
+
export const RUNTIME_API_VERSION = 1;
|
|
5
|
+
export const RUNTIME_PROTOCOL_HASH = "sha256:6dc28b06c95c98d310db445f1b19aef478cd828f11287467fe261483dfde4f81";
|
|
6
|
+
export const DEFAULT_IDLE_MS = 30 * 60 * 1000;
|
|
7
|
+
|
|
8
|
+
export class RuntimeProtocolSchemaError extends Error {
|
|
9
|
+
constructor(readonly cause: unknown) {
|
|
10
|
+
super(String(cause));
|
|
11
|
+
this.name = "RuntimeProtocolSchemaError";
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
type ParseResult<T> =
|
|
16
|
+
| { success: true; data: T }
|
|
17
|
+
| { success: false; error: RuntimeProtocolSchemaError };
|
|
18
|
+
|
|
19
|
+
type RuntimeSchema<T> = {
|
|
20
|
+
parse(value: unknown): T;
|
|
21
|
+
safeParse(value: unknown): ParseResult<T>;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
function runtimeSchema<T, I>(schema: Schema.Schema<T, I, never>): RuntimeSchema<T> {
|
|
25
|
+
const decode = Schema.decodeUnknownSync(schema);
|
|
26
|
+
return {
|
|
27
|
+
parse(value) {
|
|
28
|
+
try {
|
|
29
|
+
return decode(value);
|
|
30
|
+
} catch (error) {
|
|
31
|
+
throw new RuntimeProtocolSchemaError(error);
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
safeParse(value) {
|
|
35
|
+
try {
|
|
36
|
+
return { success: true, data: decode(value) };
|
|
37
|
+
} catch (error) {
|
|
38
|
+
return { success: false, error: new RuntimeProtocolSchemaError(error) };
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export const RunOperationRequestEffectSchema = Schema.Struct({
|
|
45
|
+
operation: Schema.NonEmptyString,
|
|
46
|
+
input: Schema.optional(Schema.Unknown),
|
|
47
|
+
}).annotations({ identifier: "RunOperationRequest" });
|
|
48
|
+
|
|
49
|
+
export const HostResponseEffectSchema = Schema.Union(
|
|
50
|
+
Schema.Struct({
|
|
51
|
+
error: Schema.Struct({
|
|
52
|
+
code: Schema.optional(Schema.String),
|
|
53
|
+
message: Schema.optional(Schema.String),
|
|
54
|
+
}),
|
|
55
|
+
}),
|
|
56
|
+
Schema.Struct({
|
|
57
|
+
result: Schema.optional(Schema.Unknown),
|
|
58
|
+
}),
|
|
59
|
+
).annotations({ identifier: "HostResponse" });
|
|
60
|
+
|
|
61
|
+
export const HostCommandRequestEffectSchema = Schema.Struct({
|
|
62
|
+
argv: Schema.Array(Schema.String).pipe(Schema.minItems(1)),
|
|
63
|
+
cwd: Schema.optional(Schema.String),
|
|
64
|
+
env: Schema.optional(Schema.Record({ key: Schema.String, value: Schema.UndefinedOr(Schema.String) })),
|
|
65
|
+
stdin: Schema.optional(Schema.NullOr(Schema.String)),
|
|
66
|
+
mode: Schema.optional(Schema.Literal("capture", "interactive")),
|
|
67
|
+
reason: Schema.optional(Schema.String),
|
|
68
|
+
presentation: Schema.optional(Schema.Struct({
|
|
69
|
+
visible: Schema.optional(Schema.Boolean),
|
|
70
|
+
label: Schema.optional(Schema.String),
|
|
71
|
+
})),
|
|
72
|
+
}).annotations({ identifier: "HostCommandRequest" });
|
|
73
|
+
|
|
74
|
+
export const HostCommandResultEffectSchema = Schema.Struct({
|
|
75
|
+
exitCode: Schema.Int,
|
|
76
|
+
stdout: Schema.NullOr(Schema.String),
|
|
77
|
+
stderr: Schema.NullOr(Schema.String),
|
|
78
|
+
}).annotations({ identifier: "HostCommandResult" });
|
|
79
|
+
|
|
80
|
+
export type RunOperationRequest = Schema.Schema.Type<typeof RunOperationRequestEffectSchema>;
|
|
81
|
+
export type HostResponse = Schema.Schema.Type<typeof HostResponseEffectSchema>;
|
|
82
|
+
export type HostCommandRequest = Schema.Schema.Type<typeof HostCommandRequestEffectSchema>;
|
|
83
|
+
export type HostCommandResult = Schema.Schema.Type<typeof HostCommandResultEffectSchema>;
|
|
84
|
+
|
|
85
|
+
export const RunOperationRequestSchema: RuntimeSchema<RunOperationRequest> = runtimeSchema(RunOperationRequestEffectSchema);
|
|
86
|
+
export const HostResponseSchema: RuntimeSchema<HostResponse> = runtimeSchema(HostResponseEffectSchema);
|
|
87
|
+
export const HostCommandRequestSchema: RuntimeSchema<HostCommandRequest> = runtimeSchema(HostCommandRequestEffectSchema);
|
|
88
|
+
export const HostCommandResultSchema: RuntimeSchema<HostCommandResult> = runtimeSchema(HostCommandResultEffectSchema);
|
|
89
|
+
|
|
90
|
+
export type HostRequestEvent = {
|
|
91
|
+
type: "host.request";
|
|
92
|
+
requestId: string;
|
|
93
|
+
id: string;
|
|
94
|
+
method: string;
|
|
95
|
+
params: unknown;
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
export type HostCapabilityRequestEvent = {
|
|
99
|
+
type: "host.capability.request";
|
|
100
|
+
requestId: string;
|
|
101
|
+
id: string;
|
|
102
|
+
capability: string;
|
|
103
|
+
params: unknown;
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
export type RunCompletedEvent = {
|
|
107
|
+
type: "run.completed";
|
|
108
|
+
runId: string;
|
|
109
|
+
result: unknown;
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
export type RunFailedEvent = {
|
|
113
|
+
type: "run.failed";
|
|
114
|
+
runId: string;
|
|
115
|
+
error: { code?: string; message: string };
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
export type RuntimeEvent =
|
|
119
|
+
| WorkflowEvent
|
|
120
|
+
| HostRequestEvent
|
|
121
|
+
| HostCapabilityRequestEvent
|
|
122
|
+
| RunCompletedEvent
|
|
123
|
+
| RunFailedEvent;
|
|
124
|
+
|
|
125
|
+
export type JsonSchema = Record<string, unknown>;
|
|
126
|
+
|
|
127
|
+
export type RuntimeOperationSource = "core" | "config";
|
|
128
|
+
|
|
129
|
+
export type RuntimeOperationKind = "command" | "workspace-action";
|
|
130
|
+
|
|
131
|
+
export type RuntimeOperationCliPosition = {
|
|
132
|
+
name: string;
|
|
133
|
+
index: number;
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
export type RuntimeOperationCliOption = {
|
|
137
|
+
name: string;
|
|
138
|
+
flag: string;
|
|
139
|
+
aliases?: string[];
|
|
140
|
+
required?: boolean;
|
|
141
|
+
runtime?: boolean;
|
|
142
|
+
type?: "string" | "boolean" | "number";
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
export type RuntimeOperationCli = {
|
|
146
|
+
positionals?: RuntimeOperationCliPosition[];
|
|
147
|
+
options?: RuntimeOperationCliOption[];
|
|
148
|
+
};
|
|
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
|
+
export type RuntimeOperation = {
|
|
161
|
+
id: string;
|
|
162
|
+
aliases?: string[];
|
|
163
|
+
kind: RuntimeOperationKind;
|
|
164
|
+
source: RuntimeOperationSource;
|
|
165
|
+
title: string;
|
|
166
|
+
description: string;
|
|
167
|
+
createsWorkspace?: boolean;
|
|
168
|
+
requiredHostMethods?: RuntimeHostMethodRequirement[];
|
|
169
|
+
requiredHostCapabilities?: RuntimeHostCapabilityRequirement[];
|
|
170
|
+
cli?: RuntimeOperationCli;
|
|
171
|
+
inputSchema: JsonSchema;
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
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
|
+
operations: RuntimeOperation[];
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
export function objectSchema(properties: Record<string, unknown>, required: string[] = []): JsonSchema {
|
|
187
|
+
return {
|
|
188
|
+
type: "object",
|
|
189
|
+
additionalProperties: false,
|
|
190
|
+
...(required.length > 0 ? { required } : {}),
|
|
191
|
+
properties,
|
|
192
|
+
};
|
|
193
|
+
}
|