@workbench-ai/workbench-protocol 0.0.43 → 0.0.44
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/dist/adapter-definition.d.ts +46 -0
- package/dist/adapter-definition.d.ts.map +1 -0
- package/dist/adapter-definition.js +172 -0
- package/dist/adapter-manifest.d.ts +20 -6
- package/dist/adapter-manifest.d.ts.map +1 -1
- package/dist/adapter-manifest.js +149 -43
- package/dist/adapter-protocol.d.ts +47 -41
- package/dist/adapter-protocol.d.ts.map +1 -1
- package/dist/adapter-protocol.js +139 -125
- package/dist/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -2
- package/dist/task-source-result.d.ts +29 -0
- package/dist/task-source-result.d.ts.map +1 -0
- package/dist/task-source-result.js +160 -0
- package/package.json +2 -2
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { Json } from "@workbench-ai/workbench-contract";
|
|
2
|
+
import type { WorkbenchAdapterAuthManifest, WorkbenchAdapterInvocationLike, WorkbenchAdapterManifest, WorkbenchAdapterOperation, WorkbenchAdapterSlotManifest } from "./adapter-manifest.ts";
|
|
3
|
+
import { type WorkbenchAdapterOperationRequest, type WorkbenchAdapterOperationResult, type WorkbenchAdapterOperationResultValue } from "./adapter-protocol.ts";
|
|
4
|
+
export interface WorkbenchAdapterDefinition<TContext = unknown> {
|
|
5
|
+
id: string;
|
|
6
|
+
setup?: string[];
|
|
7
|
+
auth?: WorkbenchAdapterAuthManifest;
|
|
8
|
+
tasks?: WorkbenchAdapterOperationDefinition<TContext>;
|
|
9
|
+
run?: WorkbenchAdapterOperationDefinition<TContext>;
|
|
10
|
+
score?: WorkbenchAdapterOperationDefinition<TContext>;
|
|
11
|
+
improve?: WorkbenchAdapterOperationDefinition<TContext>;
|
|
12
|
+
slots?: Record<string, WorkbenchAdapterSlotManifest>;
|
|
13
|
+
}
|
|
14
|
+
export interface WorkbenchAdapterOperationDefinition<TContext = unknown> {
|
|
15
|
+
command?: string;
|
|
16
|
+
handle?: WorkbenchAdapterOperationHandler<TContext>;
|
|
17
|
+
}
|
|
18
|
+
export interface WorkbenchAdapterHandlerContext<TContext = unknown> {
|
|
19
|
+
request: WorkbenchAdapterOperationRequest;
|
|
20
|
+
operation: WorkbenchAdapterOperation;
|
|
21
|
+
invocation: WorkbenchAdapterOperationRequest["invocation"];
|
|
22
|
+
with: Record<string, Json>;
|
|
23
|
+
paths: WorkbenchAdapterOperationRequest["paths"];
|
|
24
|
+
runtime: TContext;
|
|
25
|
+
slot(name: string): WorkbenchAdapterInvocationLike | null;
|
|
26
|
+
result<TValue extends WorkbenchAdapterOperationResultValue>(value: TValue, metadata?: Omit<WorkbenchAdapterOperationResult<TValue>, "protocol" | "operation" | "value">): WorkbenchAdapterOperationResult<TValue>;
|
|
27
|
+
}
|
|
28
|
+
export type WorkbenchAdapterOperationHandler<TContext = unknown> = (context: WorkbenchAdapterHandlerContext<TContext>) => WorkbenchAdapterHandlerReturn | Promise<WorkbenchAdapterHandlerReturn>;
|
|
29
|
+
export type WorkbenchAdapterHandlerReturn = WorkbenchAdapterOperationResult | WorkbenchAdapterOperationResultValue | undefined | void;
|
|
30
|
+
export interface RunDefinedWorkbenchAdapterOptions<TContext = unknown> {
|
|
31
|
+
requestPath?: string;
|
|
32
|
+
outputRoot?: string;
|
|
33
|
+
runtime?: TContext;
|
|
34
|
+
}
|
|
35
|
+
export declare function defineAdapter<TContext = unknown>(definition: WorkbenchAdapterDefinition<TContext>): WorkbenchAdapterDefinition<TContext>;
|
|
36
|
+
export declare function defineTaskSource<TContext = unknown>(definition?: WorkbenchAdapterOperationDefinition<TContext>): WorkbenchAdapterOperationDefinition<TContext>;
|
|
37
|
+
export declare function defineRunner<TContext = unknown>(definition?: WorkbenchAdapterOperationDefinition<TContext>): WorkbenchAdapterOperationDefinition<TContext>;
|
|
38
|
+
export declare function defineScorer<TContext = unknown>(definition?: WorkbenchAdapterOperationDefinition<TContext>): WorkbenchAdapterOperationDefinition<TContext>;
|
|
39
|
+
export declare function defineOptimizer<TContext = unknown>(definition?: WorkbenchAdapterOperationDefinition<TContext>): WorkbenchAdapterOperationDefinition<TContext>;
|
|
40
|
+
export declare function adapterSlot(path: string, operation: WorkbenchAdapterOperation): WorkbenchAdapterSlotManifest;
|
|
41
|
+
export declare function workbenchAdapterManifestFromDefinition(definition: WorkbenchAdapterDefinition): WorkbenchAdapterManifest;
|
|
42
|
+
export declare function runDefinedAdapter<TContext = unknown>(definition: WorkbenchAdapterDefinition<TContext>, options?: RunDefinedWorkbenchAdapterOptions<TContext>): Promise<WorkbenchAdapterOperationResult | null>;
|
|
43
|
+
export declare function operationDefinitionForRequest<TContext = unknown>(definition: WorkbenchAdapterDefinition<TContext>, operation: WorkbenchAdapterOperation): WorkbenchAdapterOperationDefinition<TContext> | undefined;
|
|
44
|
+
export declare function adapterResult<TValue extends WorkbenchAdapterOperationResultValue>(operation: WorkbenchAdapterOperation, value: TValue, metadata?: Omit<WorkbenchAdapterOperationResult<TValue>, "protocol" | "operation" | "value">): WorkbenchAdapterOperationResult<TValue>;
|
|
45
|
+
export declare function adapterSlotInvocation(request: WorkbenchAdapterOperationRequest, slots: Record<string, WorkbenchAdapterSlotManifest> | undefined, name: string): WorkbenchAdapterInvocationLike | null;
|
|
46
|
+
//# sourceMappingURL=adapter-definition.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter-definition.d.ts","sourceRoot":"","sources":["../src/adapter-definition.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import { promises as fs } from "node:fs";
|
|
2
|
+
import { adapterCommandName, } from "./adapter-manifest.js";
|
|
3
|
+
import { WORKBENCH_ADAPTER_RESULT_PROTOCOL, ensureWorkbenchAdapterOutputDir, readWorkbenchAdapterOperationRequest, workbenchAdapterOperationResultPath, writeWorkbenchAdapterOperationResult, } from "./adapter-protocol.js";
|
|
4
|
+
export function defineAdapter(definition) {
|
|
5
|
+
return definition;
|
|
6
|
+
}
|
|
7
|
+
export function defineTaskSource(definition = {}) {
|
|
8
|
+
return definition;
|
|
9
|
+
}
|
|
10
|
+
export function defineRunner(definition = {}) {
|
|
11
|
+
return definition;
|
|
12
|
+
}
|
|
13
|
+
export function defineScorer(definition = {}) {
|
|
14
|
+
return definition;
|
|
15
|
+
}
|
|
16
|
+
export function defineOptimizer(definition = {}) {
|
|
17
|
+
return definition;
|
|
18
|
+
}
|
|
19
|
+
export function adapterSlot(path, operation) {
|
|
20
|
+
return { path, operation };
|
|
21
|
+
}
|
|
22
|
+
export function workbenchAdapterManifestFromDefinition(definition) {
|
|
23
|
+
const operations = {};
|
|
24
|
+
addOperation(operations, definition.id, "tasks.resolve", definition.tasks);
|
|
25
|
+
addOperation(operations, definition.id, "subject.run", definition.run);
|
|
26
|
+
addOperation(operations, definition.id, "trial.score", definition.score);
|
|
27
|
+
addOperation(operations, definition.id, "subject.improve", definition.improve);
|
|
28
|
+
if (Object.keys(operations).length === 0) {
|
|
29
|
+
throw new Error(`Adapter ${definition.id} must define at least one operation.`);
|
|
30
|
+
}
|
|
31
|
+
return {
|
|
32
|
+
id: definition.id,
|
|
33
|
+
protocol: "workbench.adapter.v2",
|
|
34
|
+
operations,
|
|
35
|
+
setup: definition.setup ? [...definition.setup] : [],
|
|
36
|
+
...(definition.auth ? { auth: cloneJson(definition.auth) } : {}),
|
|
37
|
+
...(definition.slots ? { slots: cloneJson(definition.slots) } : {}),
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
export async function runDefinedAdapter(definition, options = {}) {
|
|
41
|
+
let request = await readWorkbenchAdapterOperationRequest(options.requestPath);
|
|
42
|
+
if (request.invocation.use !== definition.id) {
|
|
43
|
+
throw new Error(`Adapter ${definition.id} cannot execute request for ${request.invocation.use}.`);
|
|
44
|
+
}
|
|
45
|
+
if (options.outputRoot && options.outputRoot !== request.paths.output) {
|
|
46
|
+
request = {
|
|
47
|
+
...request,
|
|
48
|
+
paths: {
|
|
49
|
+
...request.paths,
|
|
50
|
+
output: options.outputRoot,
|
|
51
|
+
result: workbenchAdapterOperationResultPath(options.outputRoot),
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
await ensureWorkbenchAdapterOutputDir(request);
|
|
56
|
+
const operationDefinition = operationDefinitionForRequest(definition, request.operation);
|
|
57
|
+
if (!operationDefinition) {
|
|
58
|
+
throw new Error(`Adapter ${definition.id} does not implement ${request.operation}.`);
|
|
59
|
+
}
|
|
60
|
+
if (!operationDefinition.handle) {
|
|
61
|
+
throw new Error(`Adapter ${definition.id} ${request.operation} does not define a handler.`);
|
|
62
|
+
}
|
|
63
|
+
const handlerResult = await operationDefinition.handle(adapterHandlerContext({
|
|
64
|
+
definition,
|
|
65
|
+
request,
|
|
66
|
+
runtime: options.runtime,
|
|
67
|
+
}));
|
|
68
|
+
if (await fileExists(request.paths.result)) {
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
const result = normalizeHandlerResult(request.operation, handlerResult);
|
|
72
|
+
await writeWorkbenchAdapterOperationResult(request.paths.output, result);
|
|
73
|
+
return result;
|
|
74
|
+
}
|
|
75
|
+
export function operationDefinitionForRequest(definition, operation) {
|
|
76
|
+
if (operation === "tasks.resolve") {
|
|
77
|
+
return definition.tasks;
|
|
78
|
+
}
|
|
79
|
+
if (operation === "subject.run") {
|
|
80
|
+
return definition.run;
|
|
81
|
+
}
|
|
82
|
+
if (operation === "trial.score") {
|
|
83
|
+
return definition.score;
|
|
84
|
+
}
|
|
85
|
+
if (operation === "subject.improve") {
|
|
86
|
+
return definition.improve;
|
|
87
|
+
}
|
|
88
|
+
return undefined;
|
|
89
|
+
}
|
|
90
|
+
export function adapterResult(operation, value, metadata = {}) {
|
|
91
|
+
return {
|
|
92
|
+
protocol: WORKBENCH_ADAPTER_RESULT_PROTOCOL,
|
|
93
|
+
operation,
|
|
94
|
+
ok: true,
|
|
95
|
+
...metadata,
|
|
96
|
+
value,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
export function adapterSlotInvocation(request, slots, name) {
|
|
100
|
+
const slot = slots?.[name];
|
|
101
|
+
if (!slot) {
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
const value = jsonPointerValue(adapterWithRecord(request), slot.path);
|
|
105
|
+
return isInvocationLike(value) ? value : null;
|
|
106
|
+
}
|
|
107
|
+
function addOperation(operations, adapterId, operation, definition) {
|
|
108
|
+
if (!definition) {
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
operations[operation] = {
|
|
112
|
+
command: definition.command ?? adapterCommandName(adapterId),
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
function cloneJson(value) {
|
|
116
|
+
return JSON.parse(JSON.stringify(value));
|
|
117
|
+
}
|
|
118
|
+
function adapterHandlerContext(args) {
|
|
119
|
+
return {
|
|
120
|
+
request: args.request,
|
|
121
|
+
operation: args.request.operation,
|
|
122
|
+
invocation: args.request.invocation,
|
|
123
|
+
with: adapterWithRecord(args.request),
|
|
124
|
+
paths: args.request.paths,
|
|
125
|
+
runtime: args.runtime,
|
|
126
|
+
slot: (name) => adapterSlotInvocation(args.request, args.definition.slots, name),
|
|
127
|
+
result: (value, metadata = {}) => adapterResult(args.request.operation, value, metadata),
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
function normalizeHandlerResult(operation, result) {
|
|
131
|
+
if (isOperationResult(result)) {
|
|
132
|
+
return result;
|
|
133
|
+
}
|
|
134
|
+
return adapterResult(operation, result === undefined ? null : result);
|
|
135
|
+
}
|
|
136
|
+
function isOperationResult(value) {
|
|
137
|
+
return !!value &&
|
|
138
|
+
typeof value === "object" &&
|
|
139
|
+
!Array.isArray(value) &&
|
|
140
|
+
value.protocol === WORKBENCH_ADAPTER_RESULT_PROTOCOL &&
|
|
141
|
+
typeof value.operation === "string";
|
|
142
|
+
}
|
|
143
|
+
function adapterWithRecord(request) {
|
|
144
|
+
const value = request.invocation.with;
|
|
145
|
+
return value && typeof value === "object" && !Array.isArray(value)
|
|
146
|
+
? value
|
|
147
|
+
: {};
|
|
148
|
+
}
|
|
149
|
+
function jsonPointerValue(root, pointer) {
|
|
150
|
+
if (pointer === "") {
|
|
151
|
+
return root;
|
|
152
|
+
}
|
|
153
|
+
let current = root;
|
|
154
|
+
for (const rawPart of pointer.slice(1).split("/")) {
|
|
155
|
+
const part = rawPart.replace(/~1/gu, "/").replace(/~0/gu, "~");
|
|
156
|
+
if (!current || typeof current !== "object") {
|
|
157
|
+
return undefined;
|
|
158
|
+
}
|
|
159
|
+
current = current[part];
|
|
160
|
+
}
|
|
161
|
+
return current;
|
|
162
|
+
}
|
|
163
|
+
function isInvocationLike(value) {
|
|
164
|
+
return !!value &&
|
|
165
|
+
typeof value === "object" &&
|
|
166
|
+
!Array.isArray(value) &&
|
|
167
|
+
typeof value.use === "string" &&
|
|
168
|
+
(value.use.length > 0);
|
|
169
|
+
}
|
|
170
|
+
async function fileExists(filePath) {
|
|
171
|
+
return fs.stat(filePath).then((stat) => stat.isFile(), () => false);
|
|
172
|
+
}
|
|
@@ -1,13 +1,19 @@
|
|
|
1
1
|
export interface WorkbenchAdapterManifest {
|
|
2
2
|
id: string;
|
|
3
|
-
protocol: "workbench.adapter.
|
|
4
|
-
|
|
3
|
+
protocol: "workbench.adapter.v2";
|
|
4
|
+
operations: Partial<Record<WorkbenchAdapterOperation, WorkbenchAdapterOperationManifest>>;
|
|
5
5
|
setup: string[];
|
|
6
|
-
command: string;
|
|
7
6
|
auth?: WorkbenchAdapterAuthManifest;
|
|
8
|
-
|
|
7
|
+
slots?: Record<string, WorkbenchAdapterSlotManifest>;
|
|
8
|
+
}
|
|
9
|
+
export type WorkbenchAdapterOperation = "tasks.resolve" | "subject.run" | "trial.score" | "subject.improve";
|
|
10
|
+
export interface WorkbenchAdapterOperationManifest {
|
|
11
|
+
command: string;
|
|
12
|
+
}
|
|
13
|
+
export interface WorkbenchAdapterSlotManifest {
|
|
14
|
+
path: string;
|
|
15
|
+
operation: WorkbenchAdapterOperation;
|
|
9
16
|
}
|
|
10
|
-
export type WorkbenchAdapterCapability = "task-source" | "runner" | "scorer" | "optimizer";
|
|
11
17
|
export interface WorkbenchAdapterAuthManifest {
|
|
12
18
|
methods?: Record<string, WorkbenchAdapterAuthMethodManifest>;
|
|
13
19
|
slots?: Record<string, {
|
|
@@ -37,17 +43,25 @@ export interface WorkbenchAdapterAuthRequirement {
|
|
|
37
43
|
slot?: string;
|
|
38
44
|
profile: string;
|
|
39
45
|
}
|
|
46
|
+
export interface WorkbenchAdapterOperationRequirement {
|
|
47
|
+
invocation: WorkbenchAdapterInvocationLike;
|
|
48
|
+
operation: WorkbenchAdapterOperation;
|
|
49
|
+
}
|
|
40
50
|
export declare function adapterCommandName(adapterId: string): string;
|
|
51
|
+
export declare function workbenchAdapterManifestSupportsOperation(manifest: WorkbenchAdapterManifest, operation: WorkbenchAdapterOperation): boolean;
|
|
52
|
+
export declare function workbenchAdapterOperationCommand(manifest: WorkbenchAdapterManifest, operation: WorkbenchAdapterOperation): string;
|
|
41
53
|
export declare function cloneWorkbenchAdapterManifest(manifest: WorkbenchAdapterManifest): WorkbenchAdapterManifest;
|
|
42
54
|
export declare function parseWorkbenchAdapterManifest(source: string, label?: string): WorkbenchAdapterManifest;
|
|
43
55
|
export declare function workbenchAdapterManifestRequiresAuth(manifest: WorkbenchAdapterManifest): boolean;
|
|
44
56
|
export declare function collectWorkbenchAdapterInvocations(roots: readonly WorkbenchAdapterInvocationLike[], manifests: readonly WorkbenchAdapterManifest[] | Map<string, WorkbenchAdapterManifest>): WorkbenchAdapterInvocationLike[];
|
|
57
|
+
export declare function collectWorkbenchAdapterOperationRequirements(roots: readonly WorkbenchAdapterOperationRequirement[], manifests: readonly WorkbenchAdapterManifest[] | Map<string, WorkbenchAdapterManifest>): WorkbenchAdapterOperationRequirement[];
|
|
58
|
+
export declare function collectWorkbenchAdapterOperationIssues(roots: readonly WorkbenchAdapterOperationRequirement[], manifests: readonly WorkbenchAdapterManifest[] | Map<string, WorkbenchAdapterManifest>): string[];
|
|
59
|
+
export declare function assertWorkbenchAdapterOperationSupport(roots: readonly WorkbenchAdapterOperationRequirement[], manifests: readonly WorkbenchAdapterManifest[] | Map<string, WorkbenchAdapterManifest>): void;
|
|
45
60
|
export declare function collectWorkbenchAdapterAuthRequirements(roots: readonly WorkbenchAdapterInvocationLike[], manifests: readonly WorkbenchAdapterManifest[] | Map<string, WorkbenchAdapterManifest>): WorkbenchAdapterAuthRequirement[];
|
|
46
61
|
export declare function withDefaultWorkbenchAdapterAuthProfiles<T extends {
|
|
47
62
|
improve?: WorkbenchAdapterInvocationLike;
|
|
48
63
|
run: WorkbenchAdapterInvocationLike;
|
|
49
64
|
score?: WorkbenchAdapterInvocationLike;
|
|
50
|
-
grade?: WorkbenchAdapterInvocationLike;
|
|
51
65
|
}>(spec: T, manifests: readonly WorkbenchAdapterManifest[] | Map<string, WorkbenchAdapterManifest>): T;
|
|
52
66
|
export declare function withDefaultWorkbenchAdapterAuth<T extends WorkbenchAdapterInvocationLike>(invocation: T, manifests: readonly WorkbenchAdapterManifest[] | Map<string, WorkbenchAdapterManifest>): T;
|
|
53
67
|
//# sourceMappingURL=adapter-manifest.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adapter-manifest.d.ts","sourceRoot":"","sources":["../src/adapter-manifest.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,wBAAwB;IACvC,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,sBAAsB,CAAC;IACjC,
|
|
1
|
+
{"version":3,"file":"adapter-manifest.d.ts","sourceRoot":"","sources":["../src/adapter-manifest.ts"],"names":[],"mappings":"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"}
|
package/dist/adapter-manifest.js
CHANGED
|
@@ -2,13 +2,23 @@ import YAML from "yaml";
|
|
|
2
2
|
export function adapterCommandName(adapterId) {
|
|
3
3
|
return `workbench-adapter-${adapterId}`;
|
|
4
4
|
}
|
|
5
|
+
export function workbenchAdapterManifestSupportsOperation(manifest, operation) {
|
|
6
|
+
return manifest.operations[operation] !== undefined;
|
|
7
|
+
}
|
|
8
|
+
export function workbenchAdapterOperationCommand(manifest, operation) {
|
|
9
|
+
const operationManifest = manifest.operations[operation];
|
|
10
|
+
if (!operationManifest) {
|
|
11
|
+
throw new Error(`Adapter ${manifest.id} does not implement ${operation}.`);
|
|
12
|
+
}
|
|
13
|
+
return operationManifest.command;
|
|
14
|
+
}
|
|
5
15
|
export function cloneWorkbenchAdapterManifest(manifest) {
|
|
6
16
|
return {
|
|
7
17
|
...manifest,
|
|
8
|
-
|
|
18
|
+
operations: cloneJson(manifest.operations),
|
|
9
19
|
setup: [...manifest.setup],
|
|
10
20
|
...(manifest.auth ? { auth: cloneJson(manifest.auth) } : {}),
|
|
11
|
-
...(manifest.
|
|
21
|
+
...(manifest.slots ? { slots: cloneJson(manifest.slots) } : {}),
|
|
12
22
|
};
|
|
13
23
|
}
|
|
14
24
|
export function parseWorkbenchAdapterManifest(source, label = "workbench.adapter.yaml") {
|
|
@@ -17,42 +27,75 @@ export function parseWorkbenchAdapterManifest(source, label = "workbench.adapter
|
|
|
17
27
|
throw new Error(`${label} must be a YAML object.`);
|
|
18
28
|
}
|
|
19
29
|
const record = parsed;
|
|
20
|
-
rejectUnknownManifestKeys(record, label, ["id", "protocol", "
|
|
30
|
+
rejectUnknownManifestKeys(record, label, ["id", "protocol", "operations", "setup", "auth", "slots"]);
|
|
21
31
|
const id = readAdapterId(record.id, `${label}.id`);
|
|
22
|
-
if (record.protocol !== "workbench.adapter.
|
|
23
|
-
throw new Error(`${label}.protocol must be workbench.adapter.
|
|
32
|
+
if (record.protocol !== "workbench.adapter.v2") {
|
|
33
|
+
throw new Error(`${label}.protocol must be workbench.adapter.v2.`);
|
|
24
34
|
}
|
|
25
|
-
const command = typeof record.command === "string" && record.command.trim()
|
|
26
|
-
? record.command.trim()
|
|
27
|
-
: adapterCommandName(id);
|
|
28
35
|
const setup = record.setup === undefined
|
|
29
36
|
? []
|
|
30
37
|
: readStringArray(record.setup, `${label}.setup`);
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
: readAdapterCapabilities(record.capabilities, `${label}.capabilities`);
|
|
34
|
-
const refs = record.refs === undefined
|
|
38
|
+
const operations = readAdapterOperations(record.operations, `${label}.operations`, id);
|
|
39
|
+
const slots = record.slots === undefined
|
|
35
40
|
? undefined
|
|
36
|
-
:
|
|
41
|
+
: readAdapterSlots(record.slots, `${label}.slots`);
|
|
37
42
|
const auth = readAuth(record.auth, `${label}.auth`);
|
|
38
43
|
return {
|
|
39
44
|
id,
|
|
40
|
-
protocol: "workbench.adapter.
|
|
41
|
-
|
|
45
|
+
protocol: "workbench.adapter.v2",
|
|
46
|
+
operations,
|
|
42
47
|
setup,
|
|
43
|
-
command,
|
|
44
48
|
...(auth ? { auth } : {}),
|
|
45
|
-
...(
|
|
49
|
+
...(slots ? { slots } : {}),
|
|
46
50
|
};
|
|
47
51
|
}
|
|
48
|
-
function
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
52
|
+
function readAdapterOperations(value, label, adapterId) {
|
|
53
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
54
|
+
throw new Error(`${label} must be an object.`);
|
|
55
|
+
}
|
|
56
|
+
const operations = {};
|
|
57
|
+
for (const [operation, rawConfig] of Object.entries(value).sort()) {
|
|
58
|
+
const normalizedOperation = readAdapterOperation(operation, `${label}.${operation}`);
|
|
59
|
+
if (!rawConfig || typeof rawConfig !== "object" || Array.isArray(rawConfig)) {
|
|
60
|
+
throw new Error(`${label}.${operation} must be an object.`);
|
|
53
61
|
}
|
|
54
|
-
|
|
55
|
-
|
|
62
|
+
const config = rawConfig;
|
|
63
|
+
rejectUnknownManifestKeys(config, `${label}.${operation}`, ["command"]);
|
|
64
|
+
operations[normalizedOperation] = {
|
|
65
|
+
command: config.command === undefined
|
|
66
|
+
? adapterCommandName(adapterId)
|
|
67
|
+
: readNonEmptyString(config.command, `${label}.${operation}.command`),
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
if (Object.keys(operations).length === 0) {
|
|
71
|
+
throw new Error(`${label} must declare at least one operation.`);
|
|
72
|
+
}
|
|
73
|
+
return operations;
|
|
74
|
+
}
|
|
75
|
+
function readAdapterSlots(value, label) {
|
|
76
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
77
|
+
throw new Error(`${label} must be an object.`);
|
|
78
|
+
}
|
|
79
|
+
const slots = {};
|
|
80
|
+
for (const [slot, rawConfig] of Object.entries(value).sort()) {
|
|
81
|
+
if (!/^[a-z][a-z0-9-]*$/u.test(slot)) {
|
|
82
|
+
throw new Error(`${label} keys must be lowercase adapter slot names.`);
|
|
83
|
+
}
|
|
84
|
+
if (!rawConfig || typeof rawConfig !== "object" || Array.isArray(rawConfig)) {
|
|
85
|
+
throw new Error(`${label}.${slot} must be an object.`);
|
|
86
|
+
}
|
|
87
|
+
const config = rawConfig;
|
|
88
|
+
rejectUnknownManifestKeys(config, `${label}.${slot}`, ["path", "operation"]);
|
|
89
|
+
const slotPath = readJsonPointer(config.path, `${label}.${slot}.path`);
|
|
90
|
+
slots[slot] = {
|
|
91
|
+
path: slotPath,
|
|
92
|
+
operation: readAdapterOperation(config.operation, `${label}.${slot}.operation`),
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
if (Object.keys(slots).length === 0) {
|
|
96
|
+
throw new Error(`${label} must include at least one slot.`);
|
|
97
|
+
}
|
|
98
|
+
return slots;
|
|
56
99
|
}
|
|
57
100
|
export function workbenchAdapterManifestRequiresAuth(manifest) {
|
|
58
101
|
return defaultWorkbenchAdapterAuthForManifest(manifest) !== undefined;
|
|
@@ -68,6 +111,63 @@ export function collectWorkbenchAdapterInvocations(roots, manifests) {
|
|
|
68
111
|
}
|
|
69
112
|
return collected;
|
|
70
113
|
}
|
|
114
|
+
export function collectWorkbenchAdapterOperationRequirements(roots, manifests) {
|
|
115
|
+
const manifestById = manifestMap(manifests);
|
|
116
|
+
const collected = [];
|
|
117
|
+
const queue = roots.flatMap((root) => {
|
|
118
|
+
const invocation = normalizeInvocationLike(root.invocation);
|
|
119
|
+
return invocation ? [{ invocation, operation: root.operation }] : [];
|
|
120
|
+
});
|
|
121
|
+
while (queue.length > 0) {
|
|
122
|
+
const requirement = queue.shift();
|
|
123
|
+
collected.push(requirement);
|
|
124
|
+
const manifest = manifestById.get(requirement.invocation.use);
|
|
125
|
+
const slots = manifest?.slots ? Object.values(manifest.slots) : [];
|
|
126
|
+
if (slots.length === 0) {
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
const config = invocationConfig(requirement.invocation);
|
|
130
|
+
for (const slot of slots) {
|
|
131
|
+
const value = readJsonPointerValue(config, slot.path);
|
|
132
|
+
if (Array.isArray(value)) {
|
|
133
|
+
for (const entry of value) {
|
|
134
|
+
const nested = normalizeInvocationLike(entry);
|
|
135
|
+
if (nested) {
|
|
136
|
+
queue.push({ invocation: nested, operation: slot.operation });
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
const nested = normalizeInvocationLike(value);
|
|
142
|
+
if (nested) {
|
|
143
|
+
queue.push({ invocation: nested, operation: slot.operation });
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
return collected;
|
|
148
|
+
}
|
|
149
|
+
export function collectWorkbenchAdapterOperationIssues(roots, manifests) {
|
|
150
|
+
const manifestById = manifestMap(manifests);
|
|
151
|
+
const issues = new Map();
|
|
152
|
+
for (const requirement of collectWorkbenchAdapterOperationRequirements(roots, manifestById)) {
|
|
153
|
+
const manifest = manifestById.get(requirement.invocation.use);
|
|
154
|
+
const key = `${requirement.invocation.use}:${requirement.operation}`;
|
|
155
|
+
if (!manifest) {
|
|
156
|
+
issues.set(key, `Adapter ${requirement.invocation.use} is referenced but is not installed.`);
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
if (!workbenchAdapterManifestSupportsOperation(manifest, requirement.operation)) {
|
|
160
|
+
issues.set(key, `Adapter ${requirement.invocation.use} does not implement ${requirement.operation}.`);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
return [...issues.values()];
|
|
164
|
+
}
|
|
165
|
+
export function assertWorkbenchAdapterOperationSupport(roots, manifests) {
|
|
166
|
+
const issues = collectWorkbenchAdapterOperationIssues(roots, manifests);
|
|
167
|
+
if (issues.length > 0) {
|
|
168
|
+
throw new Error(issues.join("\n"));
|
|
169
|
+
}
|
|
170
|
+
}
|
|
71
171
|
export function collectWorkbenchAdapterAuthRequirements(roots, manifests) {
|
|
72
172
|
const manifestById = manifestMap(manifests);
|
|
73
173
|
const targets = new Map();
|
|
@@ -93,9 +193,6 @@ export function withDefaultWorkbenchAdapterAuthProfiles(spec, manifests) {
|
|
|
93
193
|
if (clone.score) {
|
|
94
194
|
clone.score = withDefaultWorkbenchAdapterAuth(clone.score, manifestById);
|
|
95
195
|
}
|
|
96
|
-
if (clone.grade) {
|
|
97
|
-
clone.grade = withDefaultWorkbenchAdapterAuth(clone.grade, manifestById);
|
|
98
|
-
}
|
|
99
196
|
return clone;
|
|
100
197
|
}
|
|
101
198
|
export function withDefaultWorkbenchAdapterAuth(invocation, manifests) {
|
|
@@ -109,12 +206,13 @@ function applyDefaultWorkbenchAdapterAuth(invocation, manifestById) {
|
|
|
109
206
|
invocation.auth = defaultAuth;
|
|
110
207
|
}
|
|
111
208
|
}
|
|
112
|
-
|
|
209
|
+
const slots = manifest?.slots ? Object.values(manifest.slots) : [];
|
|
210
|
+
if (slots.length === 0) {
|
|
113
211
|
return invocation;
|
|
114
212
|
}
|
|
115
213
|
const config = invocationConfig(invocation);
|
|
116
|
-
for (const
|
|
117
|
-
const value =
|
|
214
|
+
for (const slot of slots) {
|
|
215
|
+
const value = readJsonPointerValue(config, slot.path);
|
|
118
216
|
if (Array.isArray(value)) {
|
|
119
217
|
for (let index = 0; index < value.length; index += 1) {
|
|
120
218
|
const nested = normalizeInvocationLike(value[index]);
|
|
@@ -126,7 +224,7 @@ function applyDefaultWorkbenchAdapterAuth(invocation, manifestById) {
|
|
|
126
224
|
}
|
|
127
225
|
const nested = normalizeInvocationLike(value);
|
|
128
226
|
if (nested) {
|
|
129
|
-
const parent = readJsonPointerParent(config,
|
|
227
|
+
const parent = readJsonPointerParent(config, slot.path);
|
|
130
228
|
if (parent) {
|
|
131
229
|
const withDefaults = applyDefaultWorkbenchAdapterAuth(nested, manifestById);
|
|
132
230
|
if (Array.isArray(parent.container) && typeof parent.key === "number") {
|
|
@@ -142,12 +240,13 @@ function applyDefaultWorkbenchAdapterAuth(invocation, manifestById) {
|
|
|
142
240
|
}
|
|
143
241
|
function nestedWorkbenchAdapterInvocations(invocation, manifestById) {
|
|
144
242
|
const manifest = manifestById.get(invocation.use);
|
|
145
|
-
|
|
243
|
+
const slots = manifest?.slots ? Object.values(manifest.slots) : [];
|
|
244
|
+
if (slots.length === 0) {
|
|
146
245
|
return [];
|
|
147
246
|
}
|
|
148
247
|
const config = invocationConfig(invocation);
|
|
149
|
-
return
|
|
150
|
-
const value =
|
|
248
|
+
return slots.flatMap((slot) => {
|
|
249
|
+
const value = readJsonPointerValue(config, slot.path);
|
|
151
250
|
if (Array.isArray(value)) {
|
|
152
251
|
return value.map((entry) => normalizeInvocationLike(entry)).filter(isInvocationLike);
|
|
153
252
|
}
|
|
@@ -235,7 +334,7 @@ function normalizeInvocationLike(value) {
|
|
|
235
334
|
function isInvocationLike(value) {
|
|
236
335
|
return value !== null;
|
|
237
336
|
}
|
|
238
|
-
function
|
|
337
|
+
function readJsonPointerValue(root, pointer) {
|
|
239
338
|
if (pointer === "") {
|
|
240
339
|
return root;
|
|
241
340
|
}
|
|
@@ -266,7 +365,7 @@ function readJsonPointerParent(root, pointer) {
|
|
|
266
365
|
}
|
|
267
366
|
const rawSegments = pointer.slice(1).split("/");
|
|
268
367
|
const last = decodeJsonPointerSegment(rawSegments.pop());
|
|
269
|
-
const parent =
|
|
368
|
+
const parent = readJsonPointerValue(root, rawSegments.length === 0 ? "" : `/${rawSegments.join("/")}`);
|
|
270
369
|
if (Array.isArray(parent)) {
|
|
271
370
|
const index = Number(last);
|
|
272
371
|
return Number.isInteger(index) && index >= 0 && index < parent.length
|
|
@@ -302,14 +401,21 @@ function readStringArray(value, label) {
|
|
|
302
401
|
}
|
|
303
402
|
return value.map((entry) => entry.trim());
|
|
304
403
|
}
|
|
305
|
-
function
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
404
|
+
function readAdapterOperation(value, label) {
|
|
405
|
+
if (value === "tasks.resolve" ||
|
|
406
|
+
value === "subject.run" ||
|
|
407
|
+
value === "trial.score" ||
|
|
408
|
+
value === "subject.improve") {
|
|
409
|
+
return value;
|
|
410
|
+
}
|
|
411
|
+
throw new Error(`${label} must be tasks.resolve, subject.run, trial.score, or subject.improve.`);
|
|
412
|
+
}
|
|
413
|
+
function readJsonPointer(value, label) {
|
|
414
|
+
const pointer = readNonEmptyString(value, label);
|
|
415
|
+
if (pointer !== "" && !pointer.startsWith("/")) {
|
|
416
|
+
throw new Error(`${label} must be a JSON pointer.`);
|
|
311
417
|
}
|
|
312
|
-
return
|
|
418
|
+
return pointer;
|
|
313
419
|
}
|
|
314
420
|
function readAuth(value, label) {
|
|
315
421
|
if (value === undefined) {
|