@neutrome/open-ai-router 0.4.2 → 0.5.0
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/.dev.vars.example +2 -0
- package/README.md +5 -1
- package/package.json +5 -4
- package/src/admission/access.ts +0 -1
- package/src/admission/types.ts +0 -1
- package/src/app/factory.test.ts +40 -34
- package/src/app/factory.ts +120 -173
- package/src/app/google-genai-route.ts +48 -0
- package/src/app/http-utils.ts +14 -0
- package/src/app/model-listing.ts +29 -0
- package/src/app/response-lifecycle.ts +66 -0
- package/src/app/types.ts +38 -0
- package/src/index.ts +11 -43
- package/src/otlp.ts +148 -0
- package/src/router/audit.ts +5 -12
- package/src/router/config.ts +4 -4
- package/src/router/error-codec.ts +170 -0
- package/src/router/errors.ts +38 -1
- package/src/router/execute.test.ts +177 -107
- package/src/router/execute.ts +68 -924
- package/src/router/execution-events.ts +39 -0
- package/src/router/execution-invocation.ts +144 -0
- package/src/router/execution-observation.ts +161 -0
- package/src/router/execution-resolution.ts +120 -0
- package/src/router/execution-runtime.test.ts +156 -83
- package/src/router/execution-runtime.ts +144 -542
- package/src/router/execution-transforms.ts +82 -0
- package/src/router/execution-types.ts +8 -19
- package/src/router/index.ts +6 -5
- package/src/router/mcp.ts +12 -6
- package/src/router/provider-invoker.ts +134 -0
- package/src/router/provider-stream.ts +192 -0
- package/src/router/provider-telemetry.ts +59 -0
- package/src/router/remote-mcp-execution.ts +61 -0
- package/src/router/request-program.ts +16 -0
- package/src/router/request-target.ts +56 -0
- package/src/router/resolve.test.ts +43 -10
- package/src/router/resolve.ts +50 -28
- package/src/router/response-delivery.ts +141 -0
- package/src/router/runtime.test.ts +56 -0
- package/src/router/runtime.ts +79 -9
- package/src/router/targets.ts +3 -1
- package/src/router/upstream-client.ts +137 -0
- package/src/telemetry.test.ts +50 -0
- package/src/telemetry.ts +316 -0
- package/src/trace-labels.ts +29 -0
- package/src/upstream-auth/env.ts +15 -3
- package/src/upstream-auth/proxy.ts +6 -1
- package/src/upstream-auth/registry.ts +3 -1
- package/src/util/glob.ts +1 -1
- package/src/util/model-syntax.ts +3 -3
- package/src/worker.ts +12 -6
- package/worker-configuration.d.ts +195 -164
- package/pnpm-workspace.yaml +0 -4
- package/src/admission/jwt.test.ts +0 -96
- package/src/admission/jwt.ts +0 -221
- package/src/app/handlers.ts +0 -198
- package/src/example.test.ts +0 -377
- package/src/example.ts +0 -73
- package/src/observer.test.ts +0 -54
- package/src/observer.ts +0 -315
- package/src/timing.ts +0 -36
|
@@ -1,32 +1,45 @@
|
|
|
1
|
-
import { cloneProgram
|
|
1
|
+
import { cloneProgram } from "@neutrome/lil-engine";
|
|
2
2
|
import type { Program, ValidationMode } from "@neutrome/lil-engine";
|
|
3
3
|
import type { ExecutorContext } from "@neutrome/lilsdk-ts";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
|
|
4
|
+
import { validateProgramOrThrow as validateObservedProgram } from "./execution-observation.ts";
|
|
5
|
+
import {
|
|
6
|
+
ensureActiveSignal as assertActiveSignal,
|
|
7
|
+
providerInvokerOrThrow as requireProviderInvoker,
|
|
8
|
+
resolveExecutorOrThrow as resolveRuntimeExecutor,
|
|
9
|
+
resolveTargetOrThrow as resolveRuntimeTarget,
|
|
10
|
+
throwIfRecursionExceeded as throwIfDepthExceeded,
|
|
11
|
+
} from "./execution-resolution.ts";
|
|
12
|
+
import {
|
|
13
|
+
invokeExecution,
|
|
14
|
+
streamExecution,
|
|
15
|
+
type InvocationOptions,
|
|
16
|
+
} from "./execution-invocation.ts";
|
|
17
|
+
import { applyExecutionTransforms } from "./execution-transforms.ts";
|
|
7
18
|
import type {
|
|
8
|
-
AuditEvent,
|
|
9
19
|
ExecutionRuntime,
|
|
10
20
|
ExecutionRuntimeOptions,
|
|
11
21
|
ExecutionTarget,
|
|
12
|
-
Executor,
|
|
13
22
|
InvokeOptions,
|
|
14
|
-
ProgramTransform,
|
|
15
23
|
ProviderInvocationContext,
|
|
16
|
-
ProviderInvoker,
|
|
17
24
|
} from "./execution-types.ts";
|
|
18
25
|
|
|
19
26
|
const DEFAULT_MAX_DEPTH = 8;
|
|
20
27
|
|
|
21
|
-
export function createExecutionRuntime(
|
|
28
|
+
export function createExecutionRuntime(
|
|
29
|
+
options: ExecutionRuntimeOptions = {},
|
|
30
|
+
): ExecutionRuntime {
|
|
22
31
|
let requestCounter = 0;
|
|
23
32
|
let executionCounter = 0;
|
|
24
33
|
|
|
25
|
-
const requestIdFactory =
|
|
26
|
-
|
|
34
|
+
const requestIdFactory =
|
|
35
|
+
options.requestIdFactory ?? (() => `req_${++requestCounter}`);
|
|
36
|
+
const executionIdFactory =
|
|
37
|
+
options.executionIdFactory ?? (() => `exec_${++executionCounter}`);
|
|
27
38
|
const observe = options.observe ?? (() => {});
|
|
28
39
|
const fallbackSignal = options.signal ?? new AbortController().signal;
|
|
29
|
-
const executorImplementations = new Map(
|
|
40
|
+
const executorImplementations = new Map(
|
|
41
|
+
Object.entries(options.executorImplementations ?? {}),
|
|
42
|
+
);
|
|
30
43
|
const transforms = new Map(Object.entries(options.transforms ?? {}));
|
|
31
44
|
const maxDepth = options.maxDepth ?? DEFAULT_MAX_DEPTH;
|
|
32
45
|
const validatePrograms = options.validatePrograms ?? true;
|
|
@@ -40,19 +53,19 @@ export function createExecutionRuntime(options: ExecutionRuntimeOptions = {}): E
|
|
|
40
53
|
},
|
|
41
54
|
};
|
|
42
55
|
|
|
43
|
-
async function
|
|
56
|
+
async function prepareExecution(
|
|
44
57
|
request: ReturnType<typeof cloneProgram>,
|
|
45
|
-
invokeOptions: InvokeOptions
|
|
58
|
+
invokeOptions: InvokeOptions,
|
|
46
59
|
depth: number,
|
|
47
60
|
) {
|
|
48
|
-
|
|
61
|
+
throwIfDepthExceeded(depth, maxDepth);
|
|
49
62
|
const requestId = invokeOptions.requestId ?? requestIdFactory();
|
|
50
63
|
const executionId = invokeOptions.executionId ?? executionIdFactory();
|
|
51
64
|
const parentExecutionId = invokeOptions.parentExecutionId;
|
|
52
65
|
const signal = fallbackSignal;
|
|
53
|
-
const target =
|
|
66
|
+
const target = resolveRuntimeTarget(options, request, invokeOptions);
|
|
54
67
|
|
|
55
|
-
|
|
68
|
+
assertActiveSignal(signal, target, depth, maxDepth);
|
|
56
69
|
validateProgramOrThrow(request, {
|
|
57
70
|
stage: "request",
|
|
58
71
|
mode: "program",
|
|
@@ -64,287 +77,117 @@ export function createExecutionRuntime(options: ExecutionRuntimeOptions = {}): E
|
|
|
64
77
|
emitSuccess: true,
|
|
65
78
|
});
|
|
66
79
|
|
|
67
|
-
|
|
68
|
-
request,
|
|
69
|
-
target,
|
|
80
|
+
return {
|
|
70
81
|
requestId,
|
|
71
82
|
executionId,
|
|
72
83
|
parentExecutionId,
|
|
73
84
|
signal,
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
const startedAt = new Date(startedMs).toISOString();
|
|
81
|
-
observe(createAuditEvent({
|
|
82
|
-
kind: "executor.started",
|
|
83
|
-
requestId,
|
|
84
|
-
executionId,
|
|
85
|
-
target: executionTargetAuditRef(target),
|
|
86
|
-
data: {
|
|
87
|
-
executorId: target.executorId,
|
|
88
|
-
alias: target.alias,
|
|
89
|
-
transforms: target.transforms ?? [],
|
|
90
|
-
depth,
|
|
91
|
-
maxDepth,
|
|
92
|
-
startedAt,
|
|
93
|
-
},
|
|
94
|
-
...withParentExecutionId(parentExecutionId),
|
|
95
|
-
}));
|
|
96
|
-
|
|
97
|
-
try {
|
|
98
|
-
const result = await executor.execute(
|
|
99
|
-
transformed,
|
|
100
|
-
createExecutionContext(requestId, executionId, parentExecutionId, signal, depth),
|
|
101
|
-
);
|
|
102
|
-
validateProgramOrThrow(result, {
|
|
103
|
-
stage: "executor_result",
|
|
104
|
-
mode: "program",
|
|
85
|
+
target,
|
|
86
|
+
transformed: await applyExecutionTransforms({
|
|
87
|
+
program: request,
|
|
88
|
+
target,
|
|
89
|
+
transforms,
|
|
90
|
+
context: createExecutionContext(
|
|
105
91
|
requestId,
|
|
106
92
|
executionId,
|
|
107
93
|
parentExecutionId,
|
|
108
|
-
|
|
94
|
+
signal,
|
|
109
95
|
depth,
|
|
110
|
-
|
|
111
|
-
});
|
|
112
|
-
const finishedMs = Date.now();
|
|
113
|
-
observe(createAuditEvent({
|
|
114
|
-
kind: "executor.finished",
|
|
115
|
-
requestId,
|
|
116
|
-
executionId,
|
|
117
|
-
target: executionTargetAuditRef(target),
|
|
118
|
-
data: {
|
|
119
|
-
startedAt,
|
|
120
|
-
finishedAt: new Date(finishedMs).toISOString(),
|
|
121
|
-
durationMs: finishedMs - startedMs,
|
|
122
|
-
},
|
|
123
|
-
...withParentExecutionId(parentExecutionId),
|
|
124
|
-
}));
|
|
125
|
-
return result;
|
|
126
|
-
} catch (error) {
|
|
127
|
-
const normalized = normalizeExecutionError(error, "executor", "executor_invoke", target, depth);
|
|
128
|
-
observeExecutionError(normalized, requestId, executionId, parentExecutionId, target, depth);
|
|
129
|
-
throw normalized;
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
const providerInvoker = getProviderInvokerOrThrow();
|
|
134
|
-
const startedMs = Date.now();
|
|
135
|
-
const startedAt = new Date(startedMs).toISOString();
|
|
136
|
-
const providerCtx = createProviderInvocationContext(
|
|
137
|
-
requestId,
|
|
138
|
-
executionId,
|
|
139
|
-
parentExecutionId,
|
|
140
|
-
target,
|
|
141
|
-
signal,
|
|
142
|
-
);
|
|
143
|
-
|
|
144
|
-
observe(createAuditEvent({
|
|
145
|
-
kind: "provider.started",
|
|
146
|
-
requestId,
|
|
147
|
-
executionId,
|
|
148
|
-
target: executionTargetAuditRef(target),
|
|
149
|
-
data: {
|
|
150
|
-
model: target.model,
|
|
151
|
-
provider: target.provider ?? "",
|
|
152
|
-
transforms: target.transforms ?? [],
|
|
153
|
-
depth,
|
|
154
|
-
maxDepth,
|
|
155
|
-
startedAt,
|
|
156
|
-
},
|
|
157
|
-
...withParentExecutionId(parentExecutionId),
|
|
158
|
-
}));
|
|
159
|
-
|
|
160
|
-
try {
|
|
161
|
-
const result = await providerInvoker.execute(transformed, providerCtx);
|
|
162
|
-
validateProgramOrThrow(result, {
|
|
163
|
-
stage: "provider_result",
|
|
164
|
-
mode: "program",
|
|
96
|
+
),
|
|
165
97
|
requestId,
|
|
166
98
|
executionId,
|
|
167
99
|
parentExecutionId,
|
|
168
|
-
target,
|
|
169
100
|
depth,
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
...withParentExecutionId(parentExecutionId),
|
|
186
|
-
}));
|
|
187
|
-
return result;
|
|
188
|
-
} catch (error) {
|
|
189
|
-
const normalized = normalizeExecutionError(error, "provider", "provider_invoke", target, depth);
|
|
190
|
-
observeExecutionError(normalized, requestId, executionId, parentExecutionId, target, depth);
|
|
191
|
-
throw normalized;
|
|
192
|
-
}
|
|
101
|
+
maxDepth,
|
|
102
|
+
observe,
|
|
103
|
+
validate: (program) =>
|
|
104
|
+
validateProgramOrThrow(program, {
|
|
105
|
+
stage: "transform_output",
|
|
106
|
+
mode: "program",
|
|
107
|
+
requestId,
|
|
108
|
+
executionId,
|
|
109
|
+
parentExecutionId,
|
|
110
|
+
target,
|
|
111
|
+
depth,
|
|
112
|
+
emitSuccess: true,
|
|
113
|
+
}),
|
|
114
|
+
}),
|
|
115
|
+
};
|
|
193
116
|
}
|
|
194
117
|
|
|
195
|
-
async function
|
|
118
|
+
async function executeTarget(
|
|
196
119
|
request: ReturnType<typeof cloneProgram>,
|
|
197
120
|
invokeOptions: InvokeOptions = {},
|
|
198
121
|
depth: number,
|
|
199
122
|
) {
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
const executionId = invokeOptions.executionId ?? executionIdFactory();
|
|
203
|
-
const parentExecutionId = invokeOptions.parentExecutionId;
|
|
204
|
-
const signal = fallbackSignal;
|
|
205
|
-
const target = resolveTargetOrThrow(request, invokeOptions);
|
|
206
|
-
|
|
207
|
-
ensureActiveSignal(signal, "request", target, depth);
|
|
208
|
-
validateProgramOrThrow(request, {
|
|
209
|
-
stage: "request",
|
|
210
|
-
mode: "program",
|
|
211
|
-
requestId,
|
|
212
|
-
executionId,
|
|
213
|
-
parentExecutionId,
|
|
214
|
-
target,
|
|
215
|
-
depth,
|
|
216
|
-
emitSuccess: true,
|
|
217
|
-
});
|
|
218
|
-
|
|
219
|
-
const transformed = await applyTransforms(
|
|
220
|
-
request,
|
|
221
|
-
target,
|
|
222
|
-
requestId,
|
|
223
|
-
executionId,
|
|
224
|
-
parentExecutionId,
|
|
225
|
-
signal,
|
|
226
|
-
depth,
|
|
123
|
+
return invokeExecution(
|
|
124
|
+
await prepareInvocation(request, invokeOptions, depth),
|
|
227
125
|
);
|
|
126
|
+
}
|
|
228
127
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
executionId,
|
|
237
|
-
target: executionTargetAuditRef(target),
|
|
238
|
-
data: {
|
|
239
|
-
executorId: target.executorId,
|
|
240
|
-
alias: target.alias,
|
|
241
|
-
transforms: target.transforms ?? [],
|
|
242
|
-
depth,
|
|
243
|
-
maxDepth,
|
|
244
|
-
startedAt,
|
|
245
|
-
},
|
|
246
|
-
...withParentExecutionId(parentExecutionId),
|
|
247
|
-
}));
|
|
248
|
-
|
|
249
|
-
try {
|
|
250
|
-
for await (const chunk of executor.stream(
|
|
251
|
-
transformed,
|
|
252
|
-
createExecutionContext(requestId, executionId, parentExecutionId, signal, depth),
|
|
253
|
-
)) {
|
|
254
|
-
validateProgramOrThrow(chunk, {
|
|
255
|
-
stage: "stream_chunk",
|
|
256
|
-
mode: "stream_chunk",
|
|
257
|
-
requestId,
|
|
258
|
-
executionId,
|
|
259
|
-
parentExecutionId,
|
|
260
|
-
target,
|
|
261
|
-
depth,
|
|
262
|
-
emitSuccess: false,
|
|
263
|
-
});
|
|
264
|
-
yield chunk;
|
|
265
|
-
}
|
|
266
|
-
const finishedMs = Date.now();
|
|
267
|
-
observe(createAuditEvent({
|
|
268
|
-
kind: "executor.stream_finished",
|
|
269
|
-
requestId,
|
|
270
|
-
executionId,
|
|
271
|
-
target: executionTargetAuditRef(target),
|
|
272
|
-
data: {
|
|
273
|
-
startedAt,
|
|
274
|
-
finishedAt: new Date(finishedMs).toISOString(),
|
|
275
|
-
durationMs: finishedMs - startedMs,
|
|
276
|
-
},
|
|
277
|
-
...withParentExecutionId(parentExecutionId),
|
|
278
|
-
}));
|
|
279
|
-
return;
|
|
280
|
-
} catch (error) {
|
|
281
|
-
const normalized = normalizeExecutionError(error, "stream", "stream_chunk", target, depth);
|
|
282
|
-
observeExecutionError(normalized, requestId, executionId, parentExecutionId, target, depth);
|
|
283
|
-
throw normalized;
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
const providerInvoker = getProviderInvokerOrThrow();
|
|
288
|
-
const startedMs = Date.now();
|
|
289
|
-
const startedAt = new Date(startedMs).toISOString();
|
|
290
|
-
const providerCtx = createProviderInvocationContext(
|
|
291
|
-
requestId,
|
|
292
|
-
executionId,
|
|
293
|
-
parentExecutionId,
|
|
294
|
-
target,
|
|
295
|
-
signal,
|
|
128
|
+
async function* streamTarget(
|
|
129
|
+
request: ReturnType<typeof cloneProgram>,
|
|
130
|
+
invokeOptions: InvokeOptions = {},
|
|
131
|
+
depth: number,
|
|
132
|
+
) {
|
|
133
|
+
yield* streamExecution(
|
|
134
|
+
await prepareInvocation(request, invokeOptions, depth),
|
|
296
135
|
);
|
|
136
|
+
}
|
|
297
137
|
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
138
|
+
async function prepareInvocation(
|
|
139
|
+
request: Program,
|
|
140
|
+
invokeOptions: InvokeOptions,
|
|
141
|
+
depth: number,
|
|
142
|
+
): Promise<InvocationOptions> {
|
|
143
|
+
const prepared = await prepareExecution(request, invokeOptions, depth);
|
|
144
|
+
const executor =
|
|
145
|
+
prepared.target.kind === "executor"
|
|
146
|
+
? await resolveRuntimeExecutor(
|
|
147
|
+
options,
|
|
148
|
+
executorImplementations,
|
|
149
|
+
prepared.target.executorId,
|
|
150
|
+
)
|
|
151
|
+
: undefined;
|
|
152
|
+
return {
|
|
153
|
+
program: prepared.transformed,
|
|
154
|
+
identity: { ...prepared, depth },
|
|
155
|
+
signal: prepared.signal,
|
|
156
|
+
maxDepth,
|
|
157
|
+
observe,
|
|
158
|
+
executor,
|
|
159
|
+
providerInvoker:
|
|
160
|
+
prepared.target.kind === "provider"
|
|
161
|
+
? requireProviderInvoker(options)
|
|
162
|
+
: undefined,
|
|
163
|
+
createExecutorContext: () =>
|
|
164
|
+
createExecutionContext(
|
|
165
|
+
prepared.requestId,
|
|
166
|
+
prepared.executionId,
|
|
167
|
+
prepared.parentExecutionId,
|
|
168
|
+
prepared.signal,
|
|
307
169
|
depth,
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
try {
|
|
315
|
-
for await (const chunk of providerInvoker.stream(transformed, providerCtx)) {
|
|
316
|
-
validateProgramOrThrow(chunk, {
|
|
317
|
-
stage: "stream_chunk",
|
|
318
|
-
mode: "stream_chunk",
|
|
319
|
-
requestId,
|
|
320
|
-
executionId,
|
|
321
|
-
parentExecutionId,
|
|
170
|
+
),
|
|
171
|
+
createProviderContext: (target) =>
|
|
172
|
+
createProviderInvocationContext(
|
|
173
|
+
prepared.requestId,
|
|
174
|
+
prepared.executionId,
|
|
175
|
+
prepared.parentExecutionId,
|
|
322
176
|
target,
|
|
177
|
+
prepared.signal,
|
|
178
|
+
),
|
|
179
|
+
validate: (program, stage, mode) =>
|
|
180
|
+
validateProgramOrThrow(program, {
|
|
181
|
+
stage,
|
|
182
|
+
mode,
|
|
183
|
+
requestId: prepared.requestId,
|
|
184
|
+
executionId: prepared.executionId,
|
|
185
|
+
parentExecutionId: prepared.parentExecutionId,
|
|
186
|
+
target: prepared.target,
|
|
323
187
|
depth,
|
|
324
|
-
emitSuccess:
|
|
325
|
-
})
|
|
326
|
-
|
|
327
|
-
}
|
|
328
|
-
const finishedMs = Date.now();
|
|
329
|
-
observe(createAuditEvent({
|
|
330
|
-
kind: "provider.stream_finished",
|
|
331
|
-
requestId,
|
|
332
|
-
executionId,
|
|
333
|
-
target: executionTargetAuditRef(target),
|
|
334
|
-
data: {
|
|
335
|
-
provider: target.provider ?? "",
|
|
336
|
-
model: target.model,
|
|
337
|
-
startedAt,
|
|
338
|
-
finishedAt: new Date(finishedMs).toISOString(),
|
|
339
|
-
durationMs: finishedMs - startedMs,
|
|
340
|
-
},
|
|
341
|
-
...withParentExecutionId(parentExecutionId),
|
|
342
|
-
}));
|
|
343
|
-
} catch (error) {
|
|
344
|
-
const normalized = normalizeExecutionError(error, "stream", "stream_chunk", target, depth);
|
|
345
|
-
observeExecutionError(normalized, requestId, executionId, parentExecutionId, target, depth);
|
|
346
|
-
throw normalized;
|
|
347
|
-
}
|
|
188
|
+
emitSuccess: stage !== "stream_chunk",
|
|
189
|
+
}),
|
|
190
|
+
};
|
|
348
191
|
}
|
|
349
192
|
|
|
350
193
|
function createExecutionContext(
|
|
@@ -359,172 +202,30 @@ export function createExecutionRuntime(options: ExecutionRuntimeOptions = {}): E
|
|
|
359
202
|
executionId,
|
|
360
203
|
...(parentExecutionId ? { parentExecutionId } : {}),
|
|
361
204
|
async invoke(request, invokeOptions = {}) {
|
|
362
|
-
return executeTarget(
|
|
363
|
-
|
|
364
|
-
requestId,
|
|
365
|
-
parentExecutionId: executionId,
|
|
366
|
-
}, depth + 1);
|
|
367
|
-
},
|
|
368
|
-
async *invokeStream(request, invokeOptions = {}) {
|
|
369
|
-
yield* streamTarget(cloneProgram(request), {
|
|
370
|
-
...invokeOptions,
|
|
371
|
-
requestId,
|
|
372
|
-
parentExecutionId: executionId,
|
|
373
|
-
}, depth + 1);
|
|
374
|
-
},
|
|
375
|
-
observe,
|
|
376
|
-
signal,
|
|
377
|
-
};
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
async function applyTransforms(
|
|
381
|
-
program: ReturnType<typeof cloneProgram>,
|
|
382
|
-
target: ExecutionTarget,
|
|
383
|
-
requestId: string,
|
|
384
|
-
executionId: string,
|
|
385
|
-
parentExecutionId: string | undefined,
|
|
386
|
-
signal: AbortSignal,
|
|
387
|
-
depth: number,
|
|
388
|
-
) {
|
|
389
|
-
let current = cloneProgram(program);
|
|
390
|
-
const transformContext = createExecutionContext(
|
|
391
|
-
requestId,
|
|
392
|
-
executionId,
|
|
393
|
-
parentExecutionId,
|
|
394
|
-
signal,
|
|
395
|
-
depth,
|
|
396
|
-
);
|
|
397
|
-
for (const transformName of target.transforms ?? []) {
|
|
398
|
-
const transform = transforms.get(transformName);
|
|
399
|
-
if (!transform) {
|
|
400
|
-
throw new ExecutionError(
|
|
401
|
-
"transform",
|
|
402
|
-
`Unknown transform: ${transformName}`,
|
|
205
|
+
return executeTarget(
|
|
206
|
+
cloneProgram(request),
|
|
403
207
|
{
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
);
|
|
408
|
-
}
|
|
409
|
-
try {
|
|
410
|
-
current = await transform.apply(current, transformContext);
|
|
411
|
-
} catch (error) {
|
|
412
|
-
throw new ExecutionError(
|
|
413
|
-
"transform",
|
|
414
|
-
`Transform ${transform.name} failed`,
|
|
415
|
-
{
|
|
416
|
-
stage: "transform",
|
|
417
|
-
details: { transform: transform.name, target: executionTargetId(target), depth, maxDepth },
|
|
418
|
-
cause: error,
|
|
208
|
+
...invokeOptions,
|
|
209
|
+
requestId,
|
|
210
|
+
parentExecutionId: executionId,
|
|
419
211
|
},
|
|
212
|
+
depth + 1,
|
|
420
213
|
);
|
|
421
|
-
}
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
requestId,
|
|
426
|
-
executionId,
|
|
427
|
-
parentExecutionId,
|
|
428
|
-
target,
|
|
429
|
-
depth,
|
|
430
|
-
emitSuccess: true,
|
|
431
|
-
});
|
|
432
|
-
observe(createAuditEvent({
|
|
433
|
-
kind: "transform.applied",
|
|
434
|
-
requestId,
|
|
435
|
-
executionId,
|
|
436
|
-
target: executionTargetAuditRef(target),
|
|
437
|
-
data: {
|
|
438
|
-
transform: transform.name,
|
|
439
|
-
target: executionTargetId(target),
|
|
440
|
-
depth,
|
|
441
|
-
maxDepth,
|
|
442
|
-
},
|
|
443
|
-
...withParentExecutionId(parentExecutionId),
|
|
444
|
-
}));
|
|
445
|
-
}
|
|
446
|
-
return current;
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
function resolveTargetOrThrow(
|
|
450
|
-
request: ReturnType<typeof cloneProgram>,
|
|
451
|
-
invokeOptions: InvokeOptions,
|
|
452
|
-
): ExecutionTarget {
|
|
453
|
-
if (invokeOptions.target) {
|
|
454
|
-
return invokeOptions.target;
|
|
455
|
-
}
|
|
456
|
-
if (options.resolveTarget) {
|
|
457
|
-
try {
|
|
458
|
-
return options.resolveTarget(request, invokeOptions);
|
|
459
|
-
} catch (error) {
|
|
460
|
-
throw new ExecutionError(
|
|
461
|
-
"resolution",
|
|
462
|
-
error instanceof Error ? error.message : "Execution target resolution failed",
|
|
214
|
+
},
|
|
215
|
+
async *invokeStream(request, invokeOptions = {}) {
|
|
216
|
+
yield* streamTarget(
|
|
217
|
+
cloneProgram(request),
|
|
463
218
|
{
|
|
464
|
-
|
|
465
|
-
|
|
219
|
+
...invokeOptions,
|
|
220
|
+
requestId,
|
|
221
|
+
parentExecutionId: executionId,
|
|
466
222
|
},
|
|
223
|
+
depth + 1,
|
|
467
224
|
);
|
|
468
|
-
}
|
|
469
|
-
}
|
|
470
|
-
throw new ExecutionError("resolution", "No execution target specified", {
|
|
471
|
-
stage: "target_resolution",
|
|
472
|
-
});
|
|
473
|
-
}
|
|
474
|
-
|
|
475
|
-
async function getExecutorOrThrow(name: string): Promise<Executor> {
|
|
476
|
-
const cached = executorImplementations.get(name);
|
|
477
|
-
if (cached) {
|
|
478
|
-
return cached;
|
|
479
|
-
}
|
|
480
|
-
|
|
481
|
-
const resolved = await options.resolveExecutor?.(name);
|
|
482
|
-
if (resolved) {
|
|
483
|
-
executorImplementations.set(name, resolved);
|
|
484
|
-
return resolved;
|
|
485
|
-
}
|
|
486
|
-
|
|
487
|
-
const executor = executorImplementations.get(name);
|
|
488
|
-
if (!executor) {
|
|
489
|
-
throw new ExecutionError("resolution", `Unknown executor: ${name}`, {
|
|
490
|
-
stage: "target_resolution",
|
|
491
|
-
});
|
|
492
|
-
}
|
|
493
|
-
return executor;
|
|
494
|
-
}
|
|
495
|
-
|
|
496
|
-
function getProviderInvokerOrThrow(): ProviderInvoker {
|
|
497
|
-
if (!options.providerInvoker) {
|
|
498
|
-
throw new ExecutionError("provider", "No provider invoker configured", {
|
|
499
|
-
stage: "provider_invoke",
|
|
500
|
-
});
|
|
501
|
-
}
|
|
502
|
-
return options.providerInvoker;
|
|
503
|
-
}
|
|
504
|
-
|
|
505
|
-
function observeExecutionError(
|
|
506
|
-
error: ExecutionError,
|
|
507
|
-
requestId: string,
|
|
508
|
-
executionId: string,
|
|
509
|
-
parentExecutionId: string | undefined,
|
|
510
|
-
target: ExecutionTarget,
|
|
511
|
-
depth: number,
|
|
512
|
-
): void {
|
|
513
|
-
observe(createAuditEvent({
|
|
514
|
-
kind: "execution.failed",
|
|
515
|
-
requestId,
|
|
516
|
-
executionId,
|
|
517
|
-
target: executionTargetAuditRef(target),
|
|
518
|
-
errorKind: error.kind,
|
|
519
|
-
data: {
|
|
520
|
-
message: error.message,
|
|
521
|
-
stage: error.stage,
|
|
522
|
-
depth,
|
|
523
|
-
maxDepth,
|
|
524
|
-
...(error.details ?? {}),
|
|
525
225
|
},
|
|
526
|
-
|
|
527
|
-
|
|
226
|
+
observe,
|
|
227
|
+
signal,
|
|
228
|
+
};
|
|
528
229
|
}
|
|
529
230
|
|
|
530
231
|
function createProviderInvocationContext(
|
|
@@ -553,24 +254,15 @@ export function createExecutionRuntime(options: ExecutionRuntimeOptions = {}): E
|
|
|
553
254
|
return { parentExecutionId };
|
|
554
255
|
}
|
|
555
256
|
|
|
556
|
-
function throwIfRecursionExceeded(depth: number): void {
|
|
557
|
-
if (depth <= maxDepth) {
|
|
558
|
-
return;
|
|
559
|
-
}
|
|
560
|
-
throw new ExecutionError(
|
|
561
|
-
"recursion_limit",
|
|
562
|
-
`Execution recursion depth ${depth} exceeds maxDepth ${maxDepth}`,
|
|
563
|
-
{
|
|
564
|
-
stage: "target_resolution",
|
|
565
|
-
details: { depth, maxDepth },
|
|
566
|
-
},
|
|
567
|
-
);
|
|
568
|
-
}
|
|
569
|
-
|
|
570
257
|
function validateProgramOrThrow(
|
|
571
258
|
program: Program,
|
|
572
259
|
context: {
|
|
573
|
-
stage:
|
|
260
|
+
stage:
|
|
261
|
+
| "request"
|
|
262
|
+
| "transform_output"
|
|
263
|
+
| "provider_result"
|
|
264
|
+
| "executor_result"
|
|
265
|
+
| "stream_chunk";
|
|
574
266
|
mode: ValidationMode;
|
|
575
267
|
requestId: string;
|
|
576
268
|
executionId: string;
|
|
@@ -580,100 +272,10 @@ export function createExecutionRuntime(options: ExecutionRuntimeOptions = {}): E
|
|
|
580
272
|
emitSuccess: boolean;
|
|
581
273
|
},
|
|
582
274
|
): void {
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
if (!result.ok) {
|
|
589
|
-
throw new ExecutionError(
|
|
590
|
-
"validation",
|
|
591
|
-
`Program validation failed during ${context.stage}`,
|
|
592
|
-
{
|
|
593
|
-
stage: context.stage,
|
|
594
|
-
details: {
|
|
595
|
-
issues: result.issues,
|
|
596
|
-
depth: context.depth,
|
|
597
|
-
maxDepth,
|
|
598
|
-
target: executionTargetId(context.target),
|
|
599
|
-
},
|
|
600
|
-
},
|
|
601
|
-
);
|
|
602
|
-
}
|
|
603
|
-
|
|
604
|
-
if (context.emitSuccess) {
|
|
605
|
-
observe(createAuditEvent({
|
|
606
|
-
kind: "program.validated",
|
|
607
|
-
requestId: context.requestId,
|
|
608
|
-
executionId: context.executionId,
|
|
609
|
-
target: executionTargetAuditRef(context.target),
|
|
610
|
-
data: {
|
|
611
|
-
stage: context.stage,
|
|
612
|
-
mode: context.mode,
|
|
613
|
-
issues: 0,
|
|
614
|
-
depth: context.depth,
|
|
615
|
-
maxDepth,
|
|
616
|
-
},
|
|
617
|
-
...withParentExecutionId(context.parentExecutionId),
|
|
618
|
-
}));
|
|
619
|
-
}
|
|
620
|
-
}
|
|
621
|
-
|
|
622
|
-
function ensureActiveSignal(
|
|
623
|
-
signal: AbortSignal,
|
|
624
|
-
stage: "request",
|
|
625
|
-
target: ExecutionTarget,
|
|
626
|
-
depth: number,
|
|
627
|
-
): void {
|
|
628
|
-
if (!signal.aborted) {
|
|
629
|
-
return;
|
|
630
|
-
}
|
|
631
|
-
throw new ExecutionError(
|
|
632
|
-
"cancellation",
|
|
633
|
-
"Execution aborted",
|
|
634
|
-
{
|
|
635
|
-
stage,
|
|
636
|
-
details: { depth, maxDepth, target: executionTargetId(target) },
|
|
637
|
-
cause: signal.reason,
|
|
638
|
-
},
|
|
639
|
-
);
|
|
640
|
-
}
|
|
641
|
-
|
|
642
|
-
function normalizeExecutionError(
|
|
643
|
-
error: unknown,
|
|
644
|
-
fallbackKind: "provider" | "executor" | "stream",
|
|
645
|
-
fallbackStage: "provider_invoke" | "executor_invoke" | "stream_chunk",
|
|
646
|
-
target: ExecutionTarget,
|
|
647
|
-
depth: number,
|
|
648
|
-
): ExecutionError {
|
|
649
|
-
if (isExecutionError(error)) {
|
|
650
|
-
return error;
|
|
651
|
-
}
|
|
652
|
-
if (isAbortLike(error)) {
|
|
653
|
-
return new ExecutionError(
|
|
654
|
-
"cancellation",
|
|
655
|
-
"Execution aborted",
|
|
656
|
-
{
|
|
657
|
-
stage: fallbackStage,
|
|
658
|
-
details: { depth, maxDepth, target: executionTargetId(target) },
|
|
659
|
-
cause: error,
|
|
660
|
-
},
|
|
661
|
-
);
|
|
662
|
-
}
|
|
663
|
-
return new ExecutionError(
|
|
664
|
-
fallbackKind,
|
|
665
|
-
error instanceof Error ? error.message : String(error),
|
|
666
|
-
{
|
|
667
|
-
stage: fallbackStage,
|
|
668
|
-
details: { depth, maxDepth, target: executionTargetId(target) },
|
|
669
|
-
cause: error,
|
|
670
|
-
},
|
|
671
|
-
);
|
|
672
|
-
}
|
|
673
|
-
|
|
674
|
-
function isAbortLike(error: unknown): boolean {
|
|
675
|
-
return error instanceof DOMException
|
|
676
|
-
? error.name === "AbortError"
|
|
677
|
-
: error instanceof Error && error.name === "AbortError";
|
|
275
|
+
validateObservedProgram(program, context, {
|
|
276
|
+
enabled: validatePrograms,
|
|
277
|
+
maxDepth,
|
|
278
|
+
observe,
|
|
279
|
+
});
|
|
678
280
|
}
|
|
679
281
|
}
|