@fevex/core 0.1.0-alpha.5 → 0.1.0-alpha.6
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 +73 -9
- package/dist/agents/index.d.mts +1 -1
- package/dist/artifacts/index.d.mts +1 -1
- package/dist/channels/index.d.mts +1 -1
- package/dist/evals/index.d.mts +4 -4
- package/dist/{fevex-B5NxFKcV.d.mts → fevex-B4QY5Z6e.d.mts} +41 -12
- package/dist/http/index.d.mts +4 -4
- package/dist/http/index.mjs +2 -0
- package/dist/{index-Dsulk-n6.d.mts → index-1cHr7KB_.d.mts} +3 -3
- package/dist/{index-CKQCNvJz.d.mts → index-5p3q2yIp.d.mts} +2 -2
- package/dist/{index-aayvtf0J.d.mts → index-BJktlD4E.d.mts} +2 -2
- package/dist/{index-BPwkgdo3.d.mts → index-BgKFd9yw.d.mts} +1 -1
- package/dist/{index-Cb3AB98n.d.mts → index-CbACw6xZ.d.mts} +2 -2
- package/dist/index-CpLDt6Rw.d.mts +118 -0
- package/dist/{index-Br-zPxZH.d.mts → index-CseuTR-F.d.mts} +2 -2
- package/dist/{index-CGmHXV31.d.mts → index-CzAi2Y_Z.d.mts} +13 -6
- package/dist/{index--_LdSEuF.d.mts → index-DVw0zOc_.d.mts} +3 -3
- package/dist/{index-BFnWUu7j.d.mts → index-Df84VWmN.d.mts} +1 -1
- package/dist/index.d.mts +13 -13
- package/dist/index.mjs +466 -64
- package/dist/knowledge/index.d.mts +1 -1
- package/dist/models/index.d.mts +1 -1
- package/dist/observability/index.d.mts +2 -2
- package/dist/policies/index.d.mts +1 -1
- package/dist/runtime/index.d.mts +2 -2
- package/dist/sandbox/index.d.mts +1 -1
- package/dist/teams/index.d.mts +1 -1
- package/dist/testing/index.d.mts +6 -6
- package/dist/tools/index.d.mts +2 -2
- package/dist/{types-BDVUoAU6.d.mts → types-B8laW1hM.d.mts} +2 -0
- package/dist/workflows/index.d.mts +1 -1
- package/package.json +1 -1
- package/dist/index-D6lnI92z.d.mts +0 -80
package/dist/index.mjs
CHANGED
|
@@ -332,6 +332,18 @@ function createComposition(config) {
|
|
|
332
332
|
"error.message"
|
|
333
333
|
].includes(kind)) && (content.redact === void 0 || typeof content.redact === "function"), "INVALID_CONFIG", "Fevex config \"observability.content\" is invalid");
|
|
334
334
|
}
|
|
335
|
+
if (config.observability.exportQueue !== void 0) {
|
|
336
|
+
const queue = config.observability.exportQueue;
|
|
337
|
+
assertConfiguration(isRecord(queue) && [
|
|
338
|
+
"concurrency",
|
|
339
|
+
"maxQueued",
|
|
340
|
+
"timeoutMs",
|
|
341
|
+
"maxFailures"
|
|
342
|
+
].every((key) => {
|
|
343
|
+
const value = queue[key];
|
|
344
|
+
return value === void 0 || typeof value === "number" && Number.isSafeInteger(value) && value > 0;
|
|
345
|
+
}), "INVALID_CONFIG", "Fevex config \"observability.exportQueue\" must contain positive safe integers");
|
|
346
|
+
}
|
|
335
347
|
}
|
|
336
348
|
const models = /* @__PURE__ */ new Map();
|
|
337
349
|
const agents = /* @__PURE__ */ new Map();
|
|
@@ -624,7 +636,8 @@ function createComposition(config) {
|
|
|
624
636
|
...config.observability.content ? { content: {
|
|
625
637
|
include: [...config.observability.content.include],
|
|
626
638
|
...config.observability.content.redact ? { redact: config.observability.content.redact } : {}
|
|
627
|
-
} } : {}
|
|
639
|
+
} } : {},
|
|
640
|
+
...config.observability.exportQueue ? { exportQueue: { ...config.observability.exportQueue } } : {}
|
|
628
641
|
}
|
|
629
642
|
};
|
|
630
643
|
}
|
|
@@ -890,8 +903,9 @@ function addWorkflowBudget(first, second) {
|
|
|
890
903
|
*/
|
|
891
904
|
function createAgentEngine(composition, core) {
|
|
892
905
|
const { models, agents, tools, contextProviders, memoryStore, runStore, credentialStore, sandbox, artifacts, policies } = composition;
|
|
893
|
-
const { activeRuns, activeSessions, runtimeOwner, admitStart, markInternalRun, resolveModel, resolveCheckpointModel, notifyObserver, createEvent, emitEvent, releaseExecution, commit, startLease, cancelExecution, authorize } = core;
|
|
894
|
-
const prepareExecutionBody = async (name, request, internal = false) => {
|
|
906
|
+
const { activeRuns, activeSessions, runtimeOwner, isClosed, admitStart, markInternalRun, resolveModel, resolveCheckpointModel, notifyObserver, createEvent, emitEvent, releaseExecution, commit, startLease, cancelExecution, authorize } = core;
|
|
907
|
+
const prepareExecutionBody = async (name, request, internal = false, correlation = {}) => {
|
|
908
|
+
if (!internal && isClosed()) throw new FevexRunError("RUNTIME_CLOSED", "Runtime is not accepting new runs");
|
|
895
909
|
const agent = agents.get(name);
|
|
896
910
|
if (!agent) throw new FevexRunError("AGENT_NOT_FOUND", `Agent "${name}" is not registered`);
|
|
897
911
|
const { modelName, model } = resolveModel(agent, request.model);
|
|
@@ -920,6 +934,8 @@ function createAgentEngine(composition, core) {
|
|
|
920
934
|
agentName: name,
|
|
921
935
|
modelName,
|
|
922
936
|
...model.metadata === void 0 ? {} : { modelMetadata: structuredClone(model.metadata) },
|
|
937
|
+
...correlation.parentRunId === void 0 ? {} : { parentRunId: correlation.parentRunId },
|
|
938
|
+
...correlation.rootRunId === void 0 ? {} : { rootRunId: correlation.rootRunId },
|
|
923
939
|
status: "running",
|
|
924
940
|
revision: 0,
|
|
925
941
|
createdAt: now,
|
|
@@ -1010,7 +1026,10 @@ function createAgentEngine(composition, core) {
|
|
|
1010
1026
|
const prepareExecution = async (name, request, options = {}) => {
|
|
1011
1027
|
const release = options.admit === false ? void 0 : await admitStart("agent", name, request);
|
|
1012
1028
|
try {
|
|
1013
|
-
return await prepareExecutionBody(name, request, options.admit === false
|
|
1029
|
+
return await prepareExecutionBody(name, request, options.admit === false, {
|
|
1030
|
+
...options.parentRunId === void 0 ? {} : { parentRunId: options.parentRunId },
|
|
1031
|
+
...options.rootRunId === void 0 ? {} : { rootRunId: options.rootRunId }
|
|
1032
|
+
});
|
|
1014
1033
|
} finally {
|
|
1015
1034
|
release?.();
|
|
1016
1035
|
}
|
|
@@ -2053,16 +2072,31 @@ function scopedArtifacts(store, options) {
|
|
|
2053
2072
|
const TERMINAL_TYPES = /* @__PURE__ */ new Set([
|
|
2054
2073
|
"run.completed",
|
|
2055
2074
|
"run.failed",
|
|
2056
|
-
"run.cancelled"
|
|
2075
|
+
"run.cancelled",
|
|
2076
|
+
"workflow.run.completed",
|
|
2077
|
+
"workflow.run.failed",
|
|
2078
|
+
"workflow.run.cancelled",
|
|
2079
|
+
"team.run.completed",
|
|
2080
|
+
"team.run.failed",
|
|
2081
|
+
"team.run.cancelled"
|
|
2057
2082
|
]);
|
|
2058
2083
|
const SENSITIVE_KEY = /api[-_]?key|authorization|cookie|credential|password|secret|token/i;
|
|
2084
|
+
function isTraceTerminalEvent(event) {
|
|
2085
|
+
return TERMINAL_TYPES.has(event.type);
|
|
2086
|
+
}
|
|
2059
2087
|
function durationMs(startedAt, endedAt) {
|
|
2060
2088
|
return Math.max(0, Date.parse(endedAt) - Date.parse(startedAt));
|
|
2061
2089
|
}
|
|
2062
2090
|
function traceStatus(event) {
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2091
|
+
switch (event.type) {
|
|
2092
|
+
case "run.completed":
|
|
2093
|
+
case "workflow.run.completed":
|
|
2094
|
+
case "team.run.completed": return "completed";
|
|
2095
|
+
case "run.cancelled":
|
|
2096
|
+
case "workflow.run.cancelled":
|
|
2097
|
+
case "team.run.cancelled": return "cancelled";
|
|
2098
|
+
default: return "failed";
|
|
2099
|
+
}
|
|
2066
2100
|
}
|
|
2067
2101
|
function redactKeys(value) {
|
|
2068
2102
|
if (Array.isArray(value)) return value.map(redactKeys);
|
|
@@ -2169,20 +2203,74 @@ function annotation(event) {
|
|
|
2169
2203
|
toolName: event.payload.toolName
|
|
2170
2204
|
}
|
|
2171
2205
|
};
|
|
2206
|
+
case "workflow.run.paused":
|
|
2207
|
+
case "team.run.paused": {
|
|
2208
|
+
const stepId = event.type === "workflow.run.paused" ? event.payload.stepId : event.payload.delegationId;
|
|
2209
|
+
return {
|
|
2210
|
+
name: event.type,
|
|
2211
|
+
timestamp: event.timestamp,
|
|
2212
|
+
attributes: {
|
|
2213
|
+
stepId,
|
|
2214
|
+
reason: event.payload.reason,
|
|
2215
|
+
...event.payload.childRunId === void 0 ? {} : { childRunId: event.payload.childRunId }
|
|
2216
|
+
}
|
|
2217
|
+
};
|
|
2218
|
+
}
|
|
2219
|
+
case "workflow.run.resumed":
|
|
2220
|
+
case "team.run.resumed": return {
|
|
2221
|
+
name: event.type,
|
|
2222
|
+
timestamp: event.timestamp
|
|
2223
|
+
};
|
|
2224
|
+
case "team.handoff.created": return {
|
|
2225
|
+
name: event.type,
|
|
2226
|
+
timestamp: event.timestamp,
|
|
2227
|
+
attributes: {
|
|
2228
|
+
delegationId: event.payload.delegationId,
|
|
2229
|
+
from: event.payload.from,
|
|
2230
|
+
to: event.payload.to,
|
|
2231
|
+
reason: event.payload.reason
|
|
2232
|
+
}
|
|
2233
|
+
};
|
|
2172
2234
|
default: return;
|
|
2173
2235
|
}
|
|
2174
2236
|
}
|
|
2175
|
-
function
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
if (
|
|
2237
|
+
function terminalContent(options, terminal) {
|
|
2238
|
+
if (terminal.type === "run.completed" || terminal.type === "workflow.run.completed" || terminal.type === "team.run.completed") {
|
|
2239
|
+
const output = content(options, "run.output", terminal.payload.output);
|
|
2240
|
+
return output ? [output] : [];
|
|
2241
|
+
}
|
|
2242
|
+
if (terminal.type === "run.failed" || terminal.type === "workflow.run.failed" || terminal.type === "team.run.failed") {
|
|
2243
|
+
const error = content(options, "error.message", terminal.payload.error);
|
|
2244
|
+
return error ? [error] : [];
|
|
2245
|
+
}
|
|
2246
|
+
return [];
|
|
2247
|
+
}
|
|
2248
|
+
function sortedEvents(rawEvents) {
|
|
2249
|
+
return [...rawEvents].sort((left, right) => left.sequence - right.sequence);
|
|
2250
|
+
}
|
|
2251
|
+
function terminalEvent(runId, events) {
|
|
2252
|
+
const terminal = [...events].reverse().find((event) => isTraceTerminalEvent(event));
|
|
2253
|
+
if (!terminal) throw new TypeError(`Run "${runId}" has no terminal event`);
|
|
2254
|
+
return terminal;
|
|
2255
|
+
}
|
|
2256
|
+
function startEvent(events) {
|
|
2257
|
+
const started = events.find((event) => event.type === "run.started" || event.type === "workflow.run.started" || event.type === "team.run.started") ?? events[0];
|
|
2258
|
+
if (!started) throw new TypeError("Run has no events");
|
|
2259
|
+
return started;
|
|
2260
|
+
}
|
|
2261
|
+
function traceKind(run) {
|
|
2262
|
+
if (isTeamRun(run)) return "team";
|
|
2263
|
+
return run.kind === "workflow" ? "workflow" : "agent";
|
|
2264
|
+
}
|
|
2265
|
+
function buildAgentTrace(run, events, modelRegistryName, model, options) {
|
|
2266
|
+
const terminal = terminalEvent(run.id, events);
|
|
2267
|
+
const started = startEvent(events);
|
|
2181
2268
|
const status = traceStatus(terminal);
|
|
2182
2269
|
const annotations = [];
|
|
2183
2270
|
const spans = [];
|
|
2184
2271
|
const openModels = /* @__PURE__ */ new Map();
|
|
2185
2272
|
const openTools = /* @__PURE__ */ new Map();
|
|
2273
|
+
const modelSpanByStep = /* @__PURE__ */ new Map();
|
|
2186
2274
|
const previousUsage = {};
|
|
2187
2275
|
const closeModel = (step, endedAt, spanStatus) => {
|
|
2188
2276
|
const open = openModels.get(step);
|
|
@@ -2213,6 +2301,7 @@ function buildRunTrace(run, rawEvents, modelRegistryName, model, options) {
|
|
|
2213
2301
|
const spanCost = costFor(options, modelRegistryName, model, usage);
|
|
2214
2302
|
if (spanCost) span.cost = spanCost;
|
|
2215
2303
|
spans.push(span);
|
|
2304
|
+
modelSpanByStep.set(step, span.id);
|
|
2216
2305
|
};
|
|
2217
2306
|
const findOpenTool = (toolCallId) => {
|
|
2218
2307
|
const entries = [...openTools.entries()];
|
|
@@ -2232,7 +2321,7 @@ function buildRunTrace(run, rawEvents, modelRegistryName, model, options) {
|
|
|
2232
2321
|
const errorContent = error ? content(options, "error.message", error) : void 0;
|
|
2233
2322
|
spans.push({
|
|
2234
2323
|
id: event.id,
|
|
2235
|
-
parentId: run.id,
|
|
2324
|
+
parentId: modelSpanByStep.get(event.payload.step) ?? run.id,
|
|
2236
2325
|
kind: "tool",
|
|
2237
2326
|
name: event.payload.toolName,
|
|
2238
2327
|
startedAt: event.timestamp,
|
|
@@ -2297,19 +2386,15 @@ function buildRunTrace(run, rawEvents, modelRegistryName, model, options) {
|
|
|
2297
2386
|
for (const open of [...openTools.values()]) if (open.event.type === "tool.started") closeTool(open.event.payload.toolCallId, terminal.timestamp, status);
|
|
2298
2387
|
const finalUsage = run.usage ?? previousUsage;
|
|
2299
2388
|
const totalCost = costFor(options, modelRegistryName, model, finalUsage);
|
|
2300
|
-
const traceContent =
|
|
2301
|
-
if (terminal.type === "run.completed") {
|
|
2302
|
-
const output = content(options, "run.output", terminal.payload.output);
|
|
2303
|
-
if (output) traceContent.push(output);
|
|
2304
|
-
} else if (terminal.type === "run.failed") {
|
|
2305
|
-
const error = content(options, "error.message", terminal.payload.error);
|
|
2306
|
-
if (error) traceContent.push(error);
|
|
2307
|
-
}
|
|
2389
|
+
const traceContent = terminalContent(options, terminal);
|
|
2308
2390
|
return {
|
|
2309
2391
|
schemaVersion: "1",
|
|
2392
|
+
kind: "agent",
|
|
2310
2393
|
traceId: run.id,
|
|
2311
2394
|
runId: run.id,
|
|
2312
2395
|
sessionId: run.sessionId,
|
|
2396
|
+
...run.parentRunId === void 0 ? {} : { parentRunId: run.parentRunId },
|
|
2397
|
+
rootRunId: run.rootRunId ?? run.parentRunId ?? run.id,
|
|
2313
2398
|
agentName: run.agentName,
|
|
2314
2399
|
modelRegistryName,
|
|
2315
2400
|
...model ? { model: { ...model } } : {},
|
|
@@ -2329,6 +2414,249 @@ function buildRunTrace(run, rawEvents, modelRegistryName, model, options) {
|
|
|
2329
2414
|
...traceContent.length ? { content: traceContent } : {}
|
|
2330
2415
|
};
|
|
2331
2416
|
}
|
|
2417
|
+
function buildCoordinatorTrace(run, events, options) {
|
|
2418
|
+
const terminal = terminalEvent(run.id, events);
|
|
2419
|
+
const started = startEvent(events);
|
|
2420
|
+
const status = traceStatus(terminal);
|
|
2421
|
+
const annotations = [];
|
|
2422
|
+
const spans = [];
|
|
2423
|
+
const openSteps = /* @__PURE__ */ new Map();
|
|
2424
|
+
const stepKey = (scope, stepId) => `${scope}:${stepId}`;
|
|
2425
|
+
const modelCallCount = events.filter(({ type }) => type === "model.completed").length;
|
|
2426
|
+
const toolCallCount = events.filter(({ type }) => type === "tool.completed" || type === "tool.failed").length;
|
|
2427
|
+
const openStep = (key, event, name, attributes) => {
|
|
2428
|
+
openSteps.set(key, {
|
|
2429
|
+
event,
|
|
2430
|
+
name,
|
|
2431
|
+
attributes
|
|
2432
|
+
});
|
|
2433
|
+
};
|
|
2434
|
+
const closeStep = (key, endedAt, spanStatus, error) => {
|
|
2435
|
+
const open = openSteps.get(key);
|
|
2436
|
+
if (!open) return;
|
|
2437
|
+
openSteps.delete(key);
|
|
2438
|
+
const errorContent = error ? content(options, "error.message", error) : void 0;
|
|
2439
|
+
spans.push({
|
|
2440
|
+
id: open.event.id,
|
|
2441
|
+
parentId: run.id,
|
|
2442
|
+
kind: "step",
|
|
2443
|
+
name: open.name,
|
|
2444
|
+
startedAt: open.event.timestamp,
|
|
2445
|
+
endedAt,
|
|
2446
|
+
durationMs: durationMs(open.event.timestamp, endedAt),
|
|
2447
|
+
status: spanStatus,
|
|
2448
|
+
attributes: open.attributes,
|
|
2449
|
+
annotations: [],
|
|
2450
|
+
...errorContent ? { content: [errorContent] } : {}
|
|
2451
|
+
});
|
|
2452
|
+
};
|
|
2453
|
+
for (const event of events) {
|
|
2454
|
+
const item = annotation(event);
|
|
2455
|
+
if (item) annotations.push(item);
|
|
2456
|
+
switch (event.type) {
|
|
2457
|
+
case "workflow.step.started":
|
|
2458
|
+
openStep(stepKey("workflow", event.payload.stepId), event, event.payload.stepId, {
|
|
2459
|
+
stepId: event.payload.stepId,
|
|
2460
|
+
stepKind: event.payload.kind,
|
|
2461
|
+
...event.payload.agentName === void 0 ? {} : { agentName: event.payload.agentName },
|
|
2462
|
+
...event.payload.childRunId === void 0 ? {} : { childRunId: event.payload.childRunId }
|
|
2463
|
+
});
|
|
2464
|
+
break;
|
|
2465
|
+
case "workflow.step.completed":
|
|
2466
|
+
closeStep(stepKey("workflow", event.payload.stepId), event.timestamp, "completed");
|
|
2467
|
+
break;
|
|
2468
|
+
case "workflow.step.failed":
|
|
2469
|
+
closeStep(stepKey("workflow", event.payload.stepId), event.timestamp, "failed", event.payload.error);
|
|
2470
|
+
break;
|
|
2471
|
+
case "workflow.wait.started":
|
|
2472
|
+
openStep(stepKey("workflow", event.payload.stepId), event, event.payload.stepId, {
|
|
2473
|
+
stepId: event.payload.stepId,
|
|
2474
|
+
stepKind: "wait",
|
|
2475
|
+
waitKind: event.payload.kind,
|
|
2476
|
+
...event.payload.resumeAt === void 0 ? {} : { resumeAt: event.payload.resumeAt },
|
|
2477
|
+
...event.payload.eventName === void 0 ? {} : { eventName: event.payload.eventName }
|
|
2478
|
+
});
|
|
2479
|
+
break;
|
|
2480
|
+
case "workflow.wait.completed":
|
|
2481
|
+
closeStep(stepKey("workflow", event.payload.stepId), event.timestamp, "completed");
|
|
2482
|
+
break;
|
|
2483
|
+
case "team.agent.assigned":
|
|
2484
|
+
openStep(stepKey("team", event.payload.delegationId), event, event.payload.delegationId, {
|
|
2485
|
+
stepId: event.payload.delegationId,
|
|
2486
|
+
stepKind: "agent",
|
|
2487
|
+
agentName: event.payload.agentName,
|
|
2488
|
+
action: event.payload.action,
|
|
2489
|
+
...event.payload.expectedOutput === void 0 ? {} : { expectedOutput: event.payload.expectedOutput },
|
|
2490
|
+
...event.payload.constraints === void 0 ? {} : { constraints: event.payload.constraints },
|
|
2491
|
+
...event.payload.childRunId === void 0 ? {} : { childRunId: event.payload.childRunId }
|
|
2492
|
+
});
|
|
2493
|
+
break;
|
|
2494
|
+
case "team.task.completed":
|
|
2495
|
+
closeStep(stepKey("team", event.payload.delegationId), event.timestamp, "completed");
|
|
2496
|
+
break;
|
|
2497
|
+
case "team.task.failed":
|
|
2498
|
+
closeStep(stepKey("team", event.payload.delegationId), event.timestamp, "failed", event.payload.error);
|
|
2499
|
+
break;
|
|
2500
|
+
case "team.merge.started":
|
|
2501
|
+
openStep(stepKey("team", event.payload.stepId), event, event.payload.stepId, {
|
|
2502
|
+
stepId: event.payload.stepId,
|
|
2503
|
+
stepKind: "merge",
|
|
2504
|
+
width: event.payload.width
|
|
2505
|
+
});
|
|
2506
|
+
break;
|
|
2507
|
+
case "team.merge.completed":
|
|
2508
|
+
closeStep(stepKey("team", event.payload.stepId), event.timestamp, "completed");
|
|
2509
|
+
break;
|
|
2510
|
+
case "team.merge.failed":
|
|
2511
|
+
closeStep(stepKey("team", event.payload.stepId), event.timestamp, "failed", event.payload.error);
|
|
2512
|
+
break;
|
|
2513
|
+
}
|
|
2514
|
+
}
|
|
2515
|
+
for (const key of [...openSteps.keys()]) closeStep(key, terminal.timestamp, status);
|
|
2516
|
+
const traceContent = terminalContent(options, terminal);
|
|
2517
|
+
return {
|
|
2518
|
+
schemaVersion: "1",
|
|
2519
|
+
kind: traceKind(run),
|
|
2520
|
+
traceId: run.id,
|
|
2521
|
+
runId: run.id,
|
|
2522
|
+
sessionId: run.sessionId,
|
|
2523
|
+
...run.parentRunId === void 0 ? {} : { parentRunId: run.parentRunId },
|
|
2524
|
+
rootRunId: run.rootRunId ?? run.parentRunId ?? run.id,
|
|
2525
|
+
agentName: coordinatorName(run),
|
|
2526
|
+
startedAt: started.timestamp,
|
|
2527
|
+
endedAt: terminal.timestamp,
|
|
2528
|
+
durationMs: durationMs(started.timestamp, terminal.timestamp),
|
|
2529
|
+
status,
|
|
2530
|
+
attributes: {
|
|
2531
|
+
eventCount: events.length,
|
|
2532
|
+
stepCount: spans.filter(({ kind }) => kind === "step").length,
|
|
2533
|
+
modelCallCount,
|
|
2534
|
+
toolCallCount
|
|
2535
|
+
},
|
|
2536
|
+
annotations,
|
|
2537
|
+
spans,
|
|
2538
|
+
...run.usage && Object.keys(run.usage).length ? { usage: { ...run.usage } } : {},
|
|
2539
|
+
...traceContent.length ? { content: traceContent } : {}
|
|
2540
|
+
};
|
|
2541
|
+
}
|
|
2542
|
+
function buildRunTrace(run, rawEvents, modelRegistryName, model, options) {
|
|
2543
|
+
const events = sortedEvents(rawEvents);
|
|
2544
|
+
if (isCoordinatorRun(run)) return buildCoordinatorTrace(run, events, options);
|
|
2545
|
+
if (!modelRegistryName) throw new TypeError(`Run "${run.id}" has no model registry name`);
|
|
2546
|
+
return buildAgentTrace(run, events, modelRegistryName, model, options);
|
|
2547
|
+
}
|
|
2548
|
+
//#endregion
|
|
2549
|
+
//#region src/internal/trace-export.ts
|
|
2550
|
+
const DEFAULT_CONCURRENCY = 4;
|
|
2551
|
+
const DEFAULT_MAX_QUEUED = 100;
|
|
2552
|
+
const DEFAULT_TIMEOUT_MS = 3e4;
|
|
2553
|
+
const DEFAULT_MAX_FAILURES = 100;
|
|
2554
|
+
const DEDUPE_WINDOW = 1e4;
|
|
2555
|
+
function withTimeout(promise, timeoutMs, message) {
|
|
2556
|
+
return new Promise((resolve, reject) => {
|
|
2557
|
+
const timer = setTimeout(() => reject(new Error(message)), timeoutMs);
|
|
2558
|
+
promise.then((value) => {
|
|
2559
|
+
clearTimeout(timer);
|
|
2560
|
+
resolve(value);
|
|
2561
|
+
}, (error) => {
|
|
2562
|
+
clearTimeout(timer);
|
|
2563
|
+
reject(error);
|
|
2564
|
+
});
|
|
2565
|
+
});
|
|
2566
|
+
}
|
|
2567
|
+
function withDefault(value, fallback) {
|
|
2568
|
+
return value ?? fallback;
|
|
2569
|
+
}
|
|
2570
|
+
/**
|
|
2571
|
+
* Bounded, deduplicated trace export queue. Jobs include building the trace
|
|
2572
|
+
* from the store, so a slow store or exporter cannot grow memory without limit.
|
|
2573
|
+
*/
|
|
2574
|
+
function createTraceExportQueue(options = {}) {
|
|
2575
|
+
const concurrency = withDefault(options.concurrency, DEFAULT_CONCURRENCY);
|
|
2576
|
+
const maxQueued = withDefault(options.maxQueued, DEFAULT_MAX_QUEUED);
|
|
2577
|
+
const timeoutMs = withDefault(options.timeoutMs, DEFAULT_TIMEOUT_MS);
|
|
2578
|
+
const maxFailures = withDefault(options.maxFailures, DEFAULT_MAX_FAILURES);
|
|
2579
|
+
const queue = [];
|
|
2580
|
+
const pending = /* @__PURE__ */ new Set();
|
|
2581
|
+
const exportedRuns = /* @__PURE__ */ new Set();
|
|
2582
|
+
const failures = [];
|
|
2583
|
+
let active = 0;
|
|
2584
|
+
let exported = 0;
|
|
2585
|
+
let failed = 0;
|
|
2586
|
+
let dropped = 0;
|
|
2587
|
+
let unreported = 0;
|
|
2588
|
+
const rememberRun = (runId) => {
|
|
2589
|
+
if (exportedRuns.has(runId)) return false;
|
|
2590
|
+
if (exportedRuns.size >= DEDUPE_WINDOW) {
|
|
2591
|
+
const oldest = exportedRuns.values().next().value;
|
|
2592
|
+
if (oldest !== void 0) exportedRuns.delete(oldest);
|
|
2593
|
+
}
|
|
2594
|
+
exportedRuns.add(runId);
|
|
2595
|
+
return true;
|
|
2596
|
+
};
|
|
2597
|
+
const recordFailure = (error) => {
|
|
2598
|
+
failed += 1;
|
|
2599
|
+
unreported += 1;
|
|
2600
|
+
failures.push(error);
|
|
2601
|
+
if (failures.length > maxFailures) failures.shift();
|
|
2602
|
+
};
|
|
2603
|
+
const startNext = () => {
|
|
2604
|
+
while (active < concurrency && queue.length) {
|
|
2605
|
+
const task = queue.shift();
|
|
2606
|
+
active += 1;
|
|
2607
|
+
let job;
|
|
2608
|
+
job = Promise.resolve().then(task).then(() => {
|
|
2609
|
+
exported += 1;
|
|
2610
|
+
}, (error) => {
|
|
2611
|
+
recordFailure(error);
|
|
2612
|
+
}).finally(() => {
|
|
2613
|
+
active -= 1;
|
|
2614
|
+
pending.delete(job);
|
|
2615
|
+
startNext();
|
|
2616
|
+
});
|
|
2617
|
+
pending.add(job);
|
|
2618
|
+
}
|
|
2619
|
+
};
|
|
2620
|
+
return {
|
|
2621
|
+
timeoutMs,
|
|
2622
|
+
enqueue(runId, task) {
|
|
2623
|
+
if (!rememberRun(runId)) return;
|
|
2624
|
+
if (queue.length >= maxQueued) {
|
|
2625
|
+
dropped += 1;
|
|
2626
|
+
recordFailure(/* @__PURE__ */ new Error(`Observability export queue is full; trace for run "${runId}" was dropped`));
|
|
2627
|
+
return;
|
|
2628
|
+
}
|
|
2629
|
+
queue.push(task);
|
|
2630
|
+
startNext();
|
|
2631
|
+
},
|
|
2632
|
+
async flush(flushOptions) {
|
|
2633
|
+
const timeout = flushOptions?.timeoutMs;
|
|
2634
|
+
if (timeout !== void 0 && (typeof timeout !== "number" || !Number.isSafeInteger(timeout) || timeout <= 0)) throw new Error("Observability flush timeoutMs must be a positive safe integer");
|
|
2635
|
+
const drain = async () => {
|
|
2636
|
+
while (pending.size) await Promise.all([...pending]);
|
|
2637
|
+
};
|
|
2638
|
+
if (timeout === void 0) await drain();
|
|
2639
|
+
else await withTimeout(drain(), timeout, `Observability flush timed out after ${timeout}ms`);
|
|
2640
|
+
if (unreported === 0) return;
|
|
2641
|
+
const errors = [...failures];
|
|
2642
|
+
const omitted = unreported - failures.length;
|
|
2643
|
+
if (omitted > 0) errors.push(/* @__PURE__ */ new Error(`${omitted} additional export failures were not retained`));
|
|
2644
|
+
failures.length = 0;
|
|
2645
|
+
unreported = 0;
|
|
2646
|
+
throw new AggregateError(errors, `Observability export failed (${failed} failure(s), ${dropped} dropped trace(s))`);
|
|
2647
|
+
},
|
|
2648
|
+
stats() {
|
|
2649
|
+
return {
|
|
2650
|
+
exported,
|
|
2651
|
+
failed,
|
|
2652
|
+
dropped,
|
|
2653
|
+
queued: queue.length,
|
|
2654
|
+
active,
|
|
2655
|
+
retainedFailures: failures.length
|
|
2656
|
+
};
|
|
2657
|
+
}
|
|
2658
|
+
};
|
|
2659
|
+
}
|
|
2332
2660
|
//#endregion
|
|
2333
2661
|
//#region src/internal/run-core.ts
|
|
2334
2662
|
/**
|
|
@@ -2347,11 +2675,25 @@ function createRunCore({ models, agents, tools, runStore, policies, onEvent, obs
|
|
|
2347
2675
|
const activeSessions = /* @__PURE__ */ new Set();
|
|
2348
2676
|
const internalRuns = /* @__PURE__ */ new Set();
|
|
2349
2677
|
const pendingTenantStarts = /* @__PURE__ */ new Map();
|
|
2678
|
+
const idleWaiters = /* @__PURE__ */ new Set();
|
|
2350
2679
|
let pendingStarts = 0;
|
|
2351
|
-
|
|
2352
|
-
const
|
|
2353
|
-
const exportedRuns = /* @__PURE__ */ new Set();
|
|
2680
|
+
let closed = false;
|
|
2681
|
+
const traceExports = createTraceExportQueue(observability?.exportQueue);
|
|
2354
2682
|
const runtimeOwner = crypto.randomUUID();
|
|
2683
|
+
const isIdle = () => activeRuns.size === 0 && activeWorkflowRuns.size === 0;
|
|
2684
|
+
const notifyIdle = () => {
|
|
2685
|
+
if (!isIdle()) return;
|
|
2686
|
+
for (const resolve of idleWaiters) resolve();
|
|
2687
|
+
idleWaiters.clear();
|
|
2688
|
+
};
|
|
2689
|
+
const waitForIdle = () => {
|
|
2690
|
+
if (isIdle()) return Promise.resolve();
|
|
2691
|
+
return new Promise((resolve) => idleWaiters.add(resolve));
|
|
2692
|
+
};
|
|
2693
|
+
const closeAdmission = () => {
|
|
2694
|
+
closed = true;
|
|
2695
|
+
};
|
|
2696
|
+
const isClosed = () => closed;
|
|
2355
2697
|
const unboundedEvents = /* @__PURE__ */ new Set([
|
|
2356
2698
|
"run.started",
|
|
2357
2699
|
"run.recovered",
|
|
@@ -2403,6 +2745,7 @@ function createRunCore({ models, agents, tools, runStore, policies, onEvent, obs
|
|
|
2403
2745
|
return count;
|
|
2404
2746
|
};
|
|
2405
2747
|
const admitStart = async (kind, name, request) => {
|
|
2748
|
+
if (closed) throw new FevexRunError("RUNTIME_CLOSED", "Runtime is not accepting new runs");
|
|
2406
2749
|
if (!admission) return () => {};
|
|
2407
2750
|
const running = activeTopLevelRuns() + pendingStarts;
|
|
2408
2751
|
const tenant = tenantOf(request.context);
|
|
@@ -2459,35 +2802,30 @@ function createRunCore({ models, agents, tools, runStore, policies, onEvent, obs
|
|
|
2459
2802
|
}
|
|
2460
2803
|
};
|
|
2461
2804
|
const scheduleTraceExport = (event) => {
|
|
2462
|
-
if (!observability || !
|
|
2463
|
-
|
|
2464
|
-
"run.failed",
|
|
2465
|
-
"run.cancelled"
|
|
2466
|
-
].includes(event.type) || exportedRuns.has(event.runId)) return;
|
|
2467
|
-
exportedRuns.add(event.runId);
|
|
2468
|
-
let task;
|
|
2469
|
-
task = (async () => {
|
|
2805
|
+
if (!observability || !isTraceTerminalEvent(event)) return;
|
|
2806
|
+
traceExports.enqueue(event.runId, async () => {
|
|
2470
2807
|
const run = await runStore.getRun(event.runId);
|
|
2471
2808
|
if (!run) throw new Error(`Run "${event.runId}" does not exist`);
|
|
2472
|
-
|
|
2473
|
-
|
|
2474
|
-
let
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2809
|
+
const coordinator = isCoordinatorRun(run);
|
|
2810
|
+
let modelRegistryName;
|
|
2811
|
+
let modelMetadata;
|
|
2812
|
+
if (!coordinator) {
|
|
2813
|
+
const agentRun = run;
|
|
2814
|
+
modelRegistryName = agentRun.modelName;
|
|
2815
|
+
modelMetadata = agentRun.modelMetadata;
|
|
2816
|
+
if (modelRegistryName === void 0) {
|
|
2817
|
+
const agent = agents.get(agentRun.agentName);
|
|
2818
|
+
if (!agent) throw new Error(`Agent "${agentRun.agentName}" is not registered`);
|
|
2819
|
+
const checkpoint = isDurableRunStore(runStore) ? await runStore.getCheckpoint(agentRun.id) : void 0;
|
|
2820
|
+
const resolved = resolveModel(agent, checkpoint?.modelName);
|
|
2821
|
+
modelRegistryName = resolved.modelName;
|
|
2822
|
+
modelMetadata = resolved.model.metadata;
|
|
2823
|
+
}
|
|
2483
2824
|
}
|
|
2484
|
-
const trace = buildRunTrace(
|
|
2485
|
-
const failures = (await Promise.allSettled(observability.exporters.map((exporter) => Promise.resolve().then(() => exporter.export(trace))))).filter((result) => result.status === "rejected").map(({ reason }) => reason);
|
|
2825
|
+
const trace = buildRunTrace(run, await runStore.listEvents(run.id), modelRegistryName, modelMetadata, observability);
|
|
2826
|
+
const failures = (await Promise.allSettled(observability.exporters.map((exporter) => withTimeout(Promise.resolve().then(() => exporter.export(trace)), traceExports.timeoutMs, `Trace exporter timed out after ${traceExports.timeoutMs}ms for run "${run.id}"`)))).filter((result) => result.status === "rejected").map(({ reason }) => reason);
|
|
2486
2827
|
if (failures.length) throw new AggregateError(failures, "Trace export failed");
|
|
2487
|
-
})
|
|
2488
|
-
exportFailures.push(error);
|
|
2489
|
-
}).finally(() => pendingExports.delete(task));
|
|
2490
|
-
pendingExports.add(task);
|
|
2828
|
+
});
|
|
2491
2829
|
};
|
|
2492
2830
|
const notifyObserver = (event) => {
|
|
2493
2831
|
scheduleTraceExport(event);
|
|
@@ -2526,6 +2864,7 @@ function createRunCore({ models, agents, tools, runStore, policies, onEvent, obs
|
|
|
2526
2864
|
state.leaseTimer = void 0;
|
|
2527
2865
|
state.leaseExpiryTimer = void 0;
|
|
2528
2866
|
if (state.lease && isDurableRunStore(runStore)) await runStore.releaseLease(state.run.id, state.lease.ownerId, state.lease.generation).catch(() => {});
|
|
2867
|
+
notifyIdle();
|
|
2529
2868
|
};
|
|
2530
2869
|
const commit = async (state, options = {}) => {
|
|
2531
2870
|
if (!isDurableRunStore(runStore)) throw new FevexRunError("DURABLE_STORE_REQUIRED", "This run requires a DurableRunStore", state.run.id);
|
|
@@ -2615,6 +2954,7 @@ function createRunCore({ models, agents, tools, runStore, policies, onEvent, obs
|
|
|
2615
2954
|
state.leaseTimer = void 0;
|
|
2616
2955
|
state.leaseExpiryTimer = void 0;
|
|
2617
2956
|
if (state.lease && isDurableRunStore(runStore)) await runStore.releaseLease(state.run.id, state.lease.ownerId, state.lease.generation).catch(() => {});
|
|
2957
|
+
notifyIdle();
|
|
2618
2958
|
};
|
|
2619
2959
|
const commitWorkflow = async (state, update, events = []) => {
|
|
2620
2960
|
state.commitQueue = state.commitQueue.then(async () => {
|
|
@@ -2648,8 +2988,11 @@ function createRunCore({ models, agents, tools, runStore, policies, onEvent, obs
|
|
|
2648
2988
|
activeRuns,
|
|
2649
2989
|
activeWorkflowRuns,
|
|
2650
2990
|
activeSessions,
|
|
2651
|
-
|
|
2652
|
-
|
|
2991
|
+
isIdle,
|
|
2992
|
+
waitForIdle,
|
|
2993
|
+
closeAdmission,
|
|
2994
|
+
isClosed,
|
|
2995
|
+
traceExports,
|
|
2653
2996
|
runtimeOwner,
|
|
2654
2997
|
admitStart,
|
|
2655
2998
|
markInternalRun,
|
|
@@ -2680,7 +3023,7 @@ function createRunCore({ models, agents, tools, runStore, policies, onEvent, obs
|
|
|
2680
3023
|
*/
|
|
2681
3024
|
function createWorkflowEngine(composition, core, agentEngine) {
|
|
2682
3025
|
const { models, agents, workflows, teams, runStore } = composition;
|
|
2683
|
-
const { activeRuns, activeWorkflowRuns, activeSessions, runtimeOwner, admitStart, createEvent, createCoordinatorEvent, notifyObserver, commit, startLease, releaseWorkflowExecution, commitWorkflow } = core;
|
|
3026
|
+
const { activeRuns, activeWorkflowRuns, activeSessions, runtimeOwner, isClosed, admitStart, createEvent, createCoordinatorEvent, notifyObserver, commit, startLease, releaseWorkflowExecution, commitWorkflow } = core;
|
|
2684
3027
|
const { prepareExecution, executeAgent, nextEvent, resumeAgent, cancelStoredAgent } = agentEngine;
|
|
2685
3028
|
const cancelWorkflowExecution = async (state, reason = cancellationReason(state.request.signal)) => {
|
|
2686
3029
|
if (state.leaseLost) {
|
|
@@ -2772,6 +3115,7 @@ function createWorkflowEngine(composition, core, agentEngine) {
|
|
|
2772
3115
|
}
|
|
2773
3116
|
};
|
|
2774
3117
|
const prepareWorkflowExecutionBody = async (name, request, kind = "workflow") => {
|
|
3118
|
+
if (isClosed()) throw new FevexRunError("RUNTIME_CLOSED", "Runtime is not accepting new runs");
|
|
2775
3119
|
const workflow = workflows.get(name);
|
|
2776
3120
|
const team = kind === "team" ? teams.get(name) : void 0;
|
|
2777
3121
|
if (!workflow || kind === "team" && !team || kind === "workflow" && teams.has(name)) throw new FevexRunError(kind === "team" ? "TEAM_NOT_FOUND" : "WORKFLOW_NOT_FOUND", `${kind === "team" ? "Team" : "Workflow"} "${name}" is not registered`);
|
|
@@ -3072,7 +3416,11 @@ function createWorkflowEngine(composition, core, agentEngine) {
|
|
|
3072
3416
|
context: mergeExecutionContext(state.request.context, request.context),
|
|
3073
3417
|
limits: combineLimits(request.limits, remainingWorkflowLimits(state.checkpoint.limits, state.checkpoint.budget)),
|
|
3074
3418
|
signal: childSignal
|
|
3075
|
-
}, {
|
|
3419
|
+
}, {
|
|
3420
|
+
admit: false,
|
|
3421
|
+
parentRunId: state.run.id,
|
|
3422
|
+
rootRunId: state.run.rootRunId ?? state.run.id
|
|
3423
|
+
});
|
|
3076
3424
|
const action = options?.metadata?.teamAction === "handoff" ? "handoff" : "delegate";
|
|
3077
3425
|
const lifecycleEvents = [];
|
|
3078
3426
|
if (isTeamRun(state.run) && action === "handoff") lifecycleEvents.push(createEvent(state, "team.handoff.created", {
|
|
@@ -3084,11 +3432,13 @@ function createWorkflowEngine(composition, core, agentEngine) {
|
|
|
3084
3432
|
const started = createCoordinatorEvent(state, "workflow.step.started", {
|
|
3085
3433
|
stepId,
|
|
3086
3434
|
kind: "agent",
|
|
3087
|
-
agentName
|
|
3435
|
+
agentName,
|
|
3436
|
+
childRunId: childState.run.id
|
|
3088
3437
|
}, "team.agent.assigned", {
|
|
3089
3438
|
delegationId: stepId,
|
|
3090
3439
|
agentName,
|
|
3091
3440
|
action,
|
|
3441
|
+
childRunId: childState.run.id,
|
|
3092
3442
|
...typeof options?.metadata?.expectedOutput === "string" ? { expectedOutput: options.metadata.expectedOutput } : {},
|
|
3093
3443
|
...Array.isArray(options?.metadata?.constraints) ? { constraints: options.metadata.constraints } : {}
|
|
3094
3444
|
});
|
|
@@ -3772,24 +4122,76 @@ function createWorkflowEngine(composition, core, agentEngine) {
|
|
|
3772
4122
|
}
|
|
3773
4123
|
//#endregion
|
|
3774
4124
|
//#region src/internal/runtime.ts
|
|
4125
|
+
const DEFAULT_SHUTDOWN_TIMEOUT_MS = 3e4;
|
|
4126
|
+
const SHUTDOWN_CLEANUP_MS = 5e3;
|
|
3775
4127
|
function createRuntime(composition) {
|
|
3776
4128
|
const { models, agents, workflows, teams, tools, contextProviders, memoryStore, runStore, credentialStore, sandbox, policies } = composition;
|
|
3777
4129
|
const core = createRunCore(composition);
|
|
3778
|
-
const { activeRuns, activeWorkflowRuns, activeSessions,
|
|
4130
|
+
const { activeRuns, activeWorkflowRuns, activeSessions, isIdle, waitForIdle, closeAdmission, isClosed, traceExports, runtimeOwner, createEvent, createCoordinatorEvent, notifyObserver, commit, startLease, cancelExecution, releaseWorkflowExecution, commitWorkflow } = core;
|
|
3779
4131
|
const agentEngine = createAgentEngine(composition, core);
|
|
3780
4132
|
const { prepareExecution, executeAgent, nextEvent, drainExecution, resumeAgent, cancelStoredAgent } = agentEngine;
|
|
3781
4133
|
const { prepareWorkflowExecution, executeWorkflow, nextWorkflowEvent, drainWorkflowExecution, resumeWorkflow, cancelWorkflowExecution, cancelStoredWorkflow } = createWorkflowEngine(composition, core, agentEngine);
|
|
3782
4134
|
const resumeRun = async (runId, resolution) => {
|
|
4135
|
+
if (isClosed()) throw new FevexRunError("RUNTIME_CLOSED", "Runtime is not accepting new runs", runId);
|
|
3783
4136
|
const run = await runStore.getRun(runId);
|
|
3784
4137
|
if (run && isCoordinatorRun(run)) return resumeWorkflow(runId, resolution);
|
|
3785
4138
|
return resumeAgent(runId, resolution);
|
|
3786
4139
|
};
|
|
3787
4140
|
const recoverRun = async (runId, actor) => {
|
|
4141
|
+
if (isClosed()) throw new FevexRunError("RUNTIME_CLOSED", "Runtime is not accepting new runs", runId);
|
|
3788
4142
|
const run = await runStore.getRun(runId);
|
|
3789
4143
|
if (!run) throw new FevexRunError("RUN_NOT_RECOVERABLE", `Run "${runId}" cannot be recovered`, runId);
|
|
3790
4144
|
if (isCoordinatorRun(run)) return resumeWorkflow(runId, void 0, actor);
|
|
3791
4145
|
return resumeAgent(runId, void 0, false, actor);
|
|
3792
4146
|
};
|
|
4147
|
+
const waitForIdleUntil = async (deadline) => {
|
|
4148
|
+
if (isIdle()) return true;
|
|
4149
|
+
const remaining = deadline - Date.now();
|
|
4150
|
+
if (remaining <= 0) return false;
|
|
4151
|
+
return new Promise((resolve) => {
|
|
4152
|
+
let settled = false;
|
|
4153
|
+
let timer;
|
|
4154
|
+
const finish = (idle) => {
|
|
4155
|
+
if (settled) return;
|
|
4156
|
+
settled = true;
|
|
4157
|
+
if (timer) clearTimeout(timer);
|
|
4158
|
+
resolve(idle);
|
|
4159
|
+
};
|
|
4160
|
+
timer = setTimeout(() => finish(false), remaining);
|
|
4161
|
+
waitForIdle().then(() => finish(true));
|
|
4162
|
+
});
|
|
4163
|
+
};
|
|
4164
|
+
const shutdown = async (options = {}) => {
|
|
4165
|
+
const timeoutMs = options.timeoutMs ?? DEFAULT_SHUTDOWN_TIMEOUT_MS;
|
|
4166
|
+
if (!Number.isSafeInteger(timeoutMs) || timeoutMs < 0) throw new TypeError("Shutdown timeoutMs must be a non-negative safe integer");
|
|
4167
|
+
closeAdmission();
|
|
4168
|
+
const deadline = Date.now() + timeoutMs;
|
|
4169
|
+
let cleanupDeadline = deadline;
|
|
4170
|
+
let timedOut = false;
|
|
4171
|
+
const cancelled = /* @__PURE__ */ new Set();
|
|
4172
|
+
if (!await waitForIdleUntil(deadline)) {
|
|
4173
|
+
timedOut = true;
|
|
4174
|
+
cleanupDeadline = Date.now() + SHUTDOWN_CLEANUP_MS;
|
|
4175
|
+
for (const { run } of activeWorkflowRuns.values()) cancelled.add(run.id);
|
|
4176
|
+
for (const { run } of activeRuns.values()) cancelled.add(run.id);
|
|
4177
|
+
for (const state of [...activeWorkflowRuns.values(), ...activeRuns.values()]) if (!state.request.signal.aborted) state.controller.abort(new DOMException("Run cancelled", "AbortError"));
|
|
4178
|
+
for (const state of [...activeWorkflowRuns.values()]) if (!state.advancing) await cancelWorkflowExecution(state).catch(() => {});
|
|
4179
|
+
for (const state of [...activeRuns.values()]) if (!state.advancing) await cancelExecution(state).catch(() => {});
|
|
4180
|
+
await waitForIdleUntil(cleanupDeadline);
|
|
4181
|
+
}
|
|
4182
|
+
let exportError;
|
|
4183
|
+
try {
|
|
4184
|
+
await traceExports.flush({ timeoutMs: Math.max(1, cleanupDeadline - Date.now()) });
|
|
4185
|
+
} catch (error) {
|
|
4186
|
+
exportError = error;
|
|
4187
|
+
}
|
|
4188
|
+
return {
|
|
4189
|
+
cancelledRunIds: [...cancelled],
|
|
4190
|
+
timedOut,
|
|
4191
|
+
...exportError === void 0 ? {} : { exportError },
|
|
4192
|
+
observability: traceExports.stats()
|
|
4193
|
+
};
|
|
4194
|
+
};
|
|
3793
4195
|
return {
|
|
3794
4196
|
async startAgent(name, request) {
|
|
3795
4197
|
const state = await prepareExecution(name, request);
|
|
@@ -3921,13 +4323,13 @@ function createRuntime(composition) {
|
|
|
3921
4323
|
await runStore.saveSession(session);
|
|
3922
4324
|
return structuredClone(session);
|
|
3923
4325
|
},
|
|
3924
|
-
|
|
3925
|
-
|
|
3926
|
-
|
|
3927
|
-
|
|
3928
|
-
|
|
3929
|
-
|
|
3930
|
-
|
|
4326
|
+
flushObservability(options) {
|
|
4327
|
+
return traceExports.flush(options);
|
|
4328
|
+
},
|
|
4329
|
+
getObservabilityStats() {
|
|
4330
|
+
return traceExports.stats();
|
|
4331
|
+
},
|
|
4332
|
+
shutdown
|
|
3931
4333
|
};
|
|
3932
4334
|
}
|
|
3933
4335
|
//#endregion
|