@zhivex-ai/core 1.5.0 → 1.6.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/README.md +3 -0
- package/dist/agent.d.ts +1 -0
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +320 -193
- package/dist/agent.js.map +1 -1
- package/dist/api-stability.d.ts.map +1 -1
- package/dist/api-stability.js +32 -25
- package/dist/api-stability.js.map +1 -1
- package/dist/artifact.d.ts +32 -9
- package/dist/artifact.d.ts.map +1 -1
- package/dist/artifact.js +427 -81
- package/dist/artifact.js.map +1 -1
- package/dist/catalog.d.ts +34 -2
- package/dist/catalog.d.ts.map +1 -1
- package/dist/catalog.js +262 -7
- package/dist/catalog.js.map +1 -1
- package/dist/index.d.ts +7 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/middleware.d.ts.map +1 -1
- package/dist/middleware.js +138 -52
- package/dist/middleware.js.map +1 -1
- package/dist/observability.d.ts +57 -10
- package/dist/observability.d.ts.map +1 -1
- package/dist/observability.js +535 -114
- package/dist/observability.js.map +1 -1
- package/dist/types.d.ts +71 -3
- package/dist/types.d.ts.map +1 -1
- package/dist/workflow-observability.d.ts +13 -0
- package/dist/workflow-observability.d.ts.map +1 -0
- package/dist/workflow-observability.js +186 -0
- package/dist/workflow-observability.js.map +1 -0
- package/dist/workflow.d.ts +49 -0
- package/dist/workflow.d.ts.map +1 -1
- package/dist/workflow.js +255 -78
- package/dist/workflow.js.map +1 -1
- package/package.json +9 -1
package/dist/agent.js
CHANGED
|
@@ -416,6 +416,71 @@ const finalizeState = (agent, state, result, newSteps, newToolResults) => {
|
|
|
416
416
|
const emitTelemetryEvent = async (agent, event) => {
|
|
417
417
|
await invokeOperationalHook(agent, "telemetry", event.type, event.runId, agent.onTelemetryEvent ? () => agent.onTelemetryEvent(event) : undefined, undefined);
|
|
418
418
|
};
|
|
419
|
+
const emitInvocationStartTelemetry = async (agent, runId, startedAt, maxSteps) => {
|
|
420
|
+
try {
|
|
421
|
+
await agent.onTelemetryEvent?.startInvocation?.({
|
|
422
|
+
runId,
|
|
423
|
+
agentId: agent.id,
|
|
424
|
+
agentName: agent.name,
|
|
425
|
+
provider: agent.model.provider,
|
|
426
|
+
modelId: agent.model.modelId,
|
|
427
|
+
maxSteps,
|
|
428
|
+
startedAt
|
|
429
|
+
});
|
|
430
|
+
}
|
|
431
|
+
catch {
|
|
432
|
+
// Invocation telemetry is best-effort and cannot replace setup/business errors.
|
|
433
|
+
}
|
|
434
|
+
};
|
|
435
|
+
const emitInvocationFinishTelemetry = async (agent, runId, status, error) => {
|
|
436
|
+
try {
|
|
437
|
+
await agent.onTelemetryEvent?.finishInvocation?.({
|
|
438
|
+
runId,
|
|
439
|
+
agentId: agent.id,
|
|
440
|
+
agentName: agent.name,
|
|
441
|
+
status,
|
|
442
|
+
error,
|
|
443
|
+
finishedAt: Date.now()
|
|
444
|
+
});
|
|
445
|
+
}
|
|
446
|
+
catch {
|
|
447
|
+
// Invocation telemetry is best-effort and cannot replace setup/business errors.
|
|
448
|
+
}
|
|
449
|
+
};
|
|
450
|
+
const withAgentTelemetryRunContext = (agent, runId, callback) => {
|
|
451
|
+
const telemetryObserver = agent.onTelemetryEvent;
|
|
452
|
+
const wrapper = telemetryObserver?.withRunContext;
|
|
453
|
+
if (!wrapper)
|
|
454
|
+
return Promise.resolve().then(callback);
|
|
455
|
+
let execution;
|
|
456
|
+
let callbackError;
|
|
457
|
+
let callbackFailed = false;
|
|
458
|
+
const executeOnce = () => {
|
|
459
|
+
execution ??= Promise.resolve()
|
|
460
|
+
.then(callback)
|
|
461
|
+
.catch((error) => {
|
|
462
|
+
callbackFailed = true;
|
|
463
|
+
callbackError = error;
|
|
464
|
+
throw error;
|
|
465
|
+
});
|
|
466
|
+
return execution;
|
|
467
|
+
};
|
|
468
|
+
return Promise.resolve()
|
|
469
|
+
.then(async () => {
|
|
470
|
+
await wrapper.call(telemetryObserver, runId, executeOnce);
|
|
471
|
+
return executeOnce();
|
|
472
|
+
})
|
|
473
|
+
.catch(async (wrapperError) => {
|
|
474
|
+
if (callbackFailed)
|
|
475
|
+
throw callbackError;
|
|
476
|
+
try {
|
|
477
|
+
return await executeOnce();
|
|
478
|
+
}
|
|
479
|
+
catch (executionError) {
|
|
480
|
+
throw callbackFailed ? callbackError : executionError ?? wrapperError;
|
|
481
|
+
}
|
|
482
|
+
});
|
|
483
|
+
};
|
|
419
484
|
const subAgentToolInputSchema = z.object({
|
|
420
485
|
prompt: z.string().min(1),
|
|
421
486
|
system: z.string().optional()
|
|
@@ -1171,6 +1236,7 @@ const createGenerateOptions = (agent, state, input, messages, maxSteps, context,
|
|
|
1171
1236
|
context,
|
|
1172
1237
|
runId: state.runId,
|
|
1173
1238
|
agentId: state.agentId,
|
|
1239
|
+
agentName: agent.name,
|
|
1174
1240
|
scope: state.scope,
|
|
1175
1241
|
metadata: state.metadata,
|
|
1176
1242
|
executionEnvironment: executionEnvironmentSession
|
|
@@ -1206,19 +1272,27 @@ const createGenerateOptions = (agent, state, input, messages, maxSteps, context,
|
|
|
1206
1272
|
return compacted.messages;
|
|
1207
1273
|
}
|
|
1208
1274
|
: undefined,
|
|
1209
|
-
onBeforeModelStep: ({ step }) => {
|
|
1210
|
-
if (
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
requestedOutputTokens: maxTokens
|
|
1216
|
-
});
|
|
1217
|
-
if (trigger) {
|
|
1218
|
-
throw new GuardrailTriggeredError("input", trigger.reason ?? "Agent model budget preflight failed.", {
|
|
1219
|
-
metadata: trigger.metadata
|
|
1275
|
+
onBeforeModelStep: async ({ step }) => {
|
|
1276
|
+
if (budget) {
|
|
1277
|
+
const trigger = evaluateAgentBudgetPreflight(state, budget, {
|
|
1278
|
+
operation: "model",
|
|
1279
|
+
requiredSteps: Math.max(1, step - state.currentStep),
|
|
1280
|
+
requestedOutputTokens: maxTokens
|
|
1220
1281
|
});
|
|
1282
|
+
if (trigger) {
|
|
1283
|
+
throw new GuardrailTriggeredError("input", trigger.reason ?? "Agent model budget preflight failed.", {
|
|
1284
|
+
metadata: trigger.metadata
|
|
1285
|
+
});
|
|
1286
|
+
}
|
|
1221
1287
|
}
|
|
1288
|
+
await emitTelemetryEvent(agent, {
|
|
1289
|
+
type: "step-start",
|
|
1290
|
+
runId: state.runId,
|
|
1291
|
+
agentId: state.agentId,
|
|
1292
|
+
agentName: agent.name,
|
|
1293
|
+
stepIndex: step,
|
|
1294
|
+
startedAt: Date.now()
|
|
1295
|
+
});
|
|
1222
1296
|
},
|
|
1223
1297
|
onModelStep: async ({ request, response, step, toolCalls, approvalRequests }) => {
|
|
1224
1298
|
if (!agent.store)
|
|
@@ -1285,17 +1359,28 @@ const createGenerateOptions = (agent, state, input, messages, maxSteps, context,
|
|
|
1285
1359
|
state.revision = checkpointState.revision;
|
|
1286
1360
|
},
|
|
1287
1361
|
stepOffset: state.currentStep,
|
|
1288
|
-
onBeforeToolExecution: ({ toolCalls }) => {
|
|
1289
|
-
if (
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1362
|
+
onBeforeToolExecution: async ({ step, toolCalls }) => {
|
|
1363
|
+
if (budget) {
|
|
1364
|
+
reservedToolCalls += toolCalls.length;
|
|
1365
|
+
const trigger = evaluateAgentBudgetPreflight(state, budget, {
|
|
1366
|
+
operation: "tool",
|
|
1367
|
+
requiredToolCalls: reservedToolCalls
|
|
1368
|
+
});
|
|
1369
|
+
if (trigger) {
|
|
1370
|
+
throw new GuardrailTriggeredError("input", trigger.reason ?? "Agent tool budget preflight failed.", {
|
|
1371
|
+
metadata: trigger.metadata
|
|
1372
|
+
});
|
|
1373
|
+
}
|
|
1374
|
+
}
|
|
1375
|
+
for (const toolCall of toolCalls) {
|
|
1376
|
+
await emitTelemetryEvent(agent, {
|
|
1377
|
+
type: "tool-start",
|
|
1378
|
+
runId: state.runId,
|
|
1379
|
+
agentId: state.agentId,
|
|
1380
|
+
agentName: agent.name,
|
|
1381
|
+
stepIndex: step,
|
|
1382
|
+
toolCall,
|
|
1383
|
+
startedAt: Date.now()
|
|
1299
1384
|
});
|
|
1300
1385
|
}
|
|
1301
1386
|
},
|
|
@@ -1500,14 +1585,16 @@ const acquireAgentExecutionLease = async (agent, state, policy) => {
|
|
|
1500
1585
|
}
|
|
1501
1586
|
};
|
|
1502
1587
|
};
|
|
1503
|
-
const emitRunStartTelemetry = async (agent, state, memoryMessages, approvals) => {
|
|
1588
|
+
const emitRunStartTelemetry = async (agent, state, memoryMessages, approvals, invocationStartedAt) => {
|
|
1504
1589
|
await emitTelemetryEvent(agent, {
|
|
1505
1590
|
type: "run-start",
|
|
1506
1591
|
runId: state.runId,
|
|
1507
1592
|
agentId: state.agentId,
|
|
1593
|
+
agentName: agent.name,
|
|
1508
1594
|
provider: state.provider,
|
|
1509
1595
|
modelId: state.modelId,
|
|
1510
|
-
maxSteps: state.maxSteps
|
|
1596
|
+
maxSteps: state.maxSteps,
|
|
1597
|
+
startedAt: invocationStartedAt
|
|
1511
1598
|
});
|
|
1512
1599
|
if (state.handoff) {
|
|
1513
1600
|
await emitTelemetryEvent(agent, {
|
|
@@ -1539,8 +1626,10 @@ const emitRunFinishTelemetry = async (agent, state) => {
|
|
|
1539
1626
|
type: "run-finish",
|
|
1540
1627
|
runId: state.runId,
|
|
1541
1628
|
agentId: state.agentId,
|
|
1629
|
+
agentName: agent.name,
|
|
1542
1630
|
status: state.status,
|
|
1543
|
-
state: cloneState(state)
|
|
1631
|
+
state: cloneState(state),
|
|
1632
|
+
finishedAt: Date.now()
|
|
1544
1633
|
});
|
|
1545
1634
|
};
|
|
1546
1635
|
export const createAgent = (definition) => ({
|
|
@@ -1549,6 +1638,7 @@ export const createAgent = (definition) => ({
|
|
|
1549
1638
|
});
|
|
1550
1639
|
export class Agent {
|
|
1551
1640
|
id;
|
|
1641
|
+
name;
|
|
1552
1642
|
model;
|
|
1553
1643
|
instructions;
|
|
1554
1644
|
contextSchema;
|
|
@@ -1584,6 +1674,7 @@ export class Agent {
|
|
|
1584
1674
|
toDefinition() {
|
|
1585
1675
|
return createAgent({
|
|
1586
1676
|
id: this.id,
|
|
1677
|
+
name: this.name,
|
|
1587
1678
|
model: this.model,
|
|
1588
1679
|
instructions: this.instructions,
|
|
1589
1680
|
contextSchema: this.contextSchema,
|
|
@@ -1788,175 +1879,203 @@ export const cancelAgentRunTree = async (store, runId, options = {}) => {
|
|
|
1788
1879
|
};
|
|
1789
1880
|
};
|
|
1790
1881
|
export const runAgent = async (agent, input = {}) => {
|
|
1791
|
-
const
|
|
1792
|
-
const
|
|
1793
|
-
const
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
}
|
|
1805
|
-
const supportsLeases = Boolean(agent.store?.acquireLease && agent.store.renewLease && agent.store.releaseLease);
|
|
1806
|
-
if (!context.fresh && currentStatus === "running" && !supportsLeases) {
|
|
1807
|
-
return toOutput(context.state);
|
|
1808
|
-
}
|
|
1809
|
-
const freshRequiresExistingClaim = context.fresh && Boolean(context.state.idempotencyKey);
|
|
1810
|
-
if (context.fresh && !freshRequiresExistingClaim) {
|
|
1811
|
-
await claimAgentExecution(agent, context.state);
|
|
1812
|
-
}
|
|
1813
|
-
const executionLease = await acquireAgentExecutionLease(agent, context.state, policy);
|
|
1814
|
-
if (!executionLease) {
|
|
1815
|
-
if (input.state) {
|
|
1816
|
-
throw new ConflictError(`Agent run "${context.state.runId}" is already owned by another worker.`);
|
|
1882
|
+
const invocationStartedAt = Date.now();
|
|
1883
|
+
const telemetryRunId = input.runId ?? input.state?.runId ?? randomId("run");
|
|
1884
|
+
const invocationInput = input.runId || input.state
|
|
1885
|
+
? input
|
|
1886
|
+
: { ...input, runId: telemetryRunId };
|
|
1887
|
+
let invocationStatus = "completed";
|
|
1888
|
+
let invocationError;
|
|
1889
|
+
const returnInvocationOutput = (output) => {
|
|
1890
|
+
invocationStatus = output.status;
|
|
1891
|
+
if (output.status === "failed" || output.status === "timed_out") {
|
|
1892
|
+
invocationError = new Error(output.error?.message ?? `Agent invocation ${output.status}.`);
|
|
1893
|
+
if (output.status === "timed_out")
|
|
1894
|
+
invocationError.name = "TimeoutError";
|
|
1817
1895
|
}
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1896
|
+
else {
|
|
1897
|
+
invocationError = undefined;
|
|
1898
|
+
}
|
|
1899
|
+
return output;
|
|
1900
|
+
};
|
|
1901
|
+
await emitInvocationStartTelemetry(agent, telemetryRunId, invocationStartedAt, Math.max(1, input.maxSteps ?? input.state?.maxSteps ?? agent.maxSteps ?? 1));
|
|
1821
1902
|
try {
|
|
1822
|
-
|
|
1903
|
+
const context = await resolveContext(agent, invocationInput);
|
|
1904
|
+
const currentStatus = normalizeApprovalStatus(context.state.status);
|
|
1905
|
+
const policy = resolveRunPolicy(agent, input);
|
|
1906
|
+
if (currentStatus === "completed" ||
|
|
1907
|
+
currentStatus === "cancelled" ||
|
|
1908
|
+
currentStatus === "cancel_requested" ||
|
|
1909
|
+
currentStatus === "timed_out") {
|
|
1910
|
+
context.state.status = currentStatus;
|
|
1911
|
+
invocationStatus = currentStatus;
|
|
1912
|
+
return returnInvocationOutput(toOutput(context.state));
|
|
1913
|
+
}
|
|
1914
|
+
if (currentStatus === "waiting_approval" && context.state.pendingApprovals.length > 0) {
|
|
1915
|
+
context.state.status = currentStatus;
|
|
1916
|
+
invocationStatus = currentStatus;
|
|
1917
|
+
return returnInvocationOutput(toOutput(context.state));
|
|
1918
|
+
}
|
|
1919
|
+
const supportsLeases = Boolean(agent.store?.acquireLease && agent.store.renewLease && agent.store.releaseLease);
|
|
1920
|
+
if (!context.fresh && currentStatus === "running" && !supportsLeases) {
|
|
1921
|
+
invocationStatus = currentStatus;
|
|
1922
|
+
return returnInvocationOutput(toOutput(context.state));
|
|
1923
|
+
}
|
|
1924
|
+
const freshRequiresExistingClaim = context.fresh && Boolean(context.state.idempotencyKey);
|
|
1925
|
+
if (context.fresh && !freshRequiresExistingClaim) {
|
|
1823
1926
|
await claimAgentExecution(agent, context.state);
|
|
1824
1927
|
}
|
|
1825
|
-
await
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
}
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1928
|
+
const executionLease = await acquireAgentExecutionLease(agent, context.state, policy);
|
|
1929
|
+
if (!executionLease) {
|
|
1930
|
+
if (input.state) {
|
|
1931
|
+
throw new ConflictError(`Agent run "${context.state.runId}" is already owned by another worker.`);
|
|
1932
|
+
}
|
|
1933
|
+
const activeState = await agent.store?.load(context.state.runId, context.state.scope);
|
|
1934
|
+
const outputState = activeState ? normalizeAgentRunState(activeState) : context.state;
|
|
1935
|
+
invocationStatus = outputState.status;
|
|
1936
|
+
return returnInvocationOutput(toOutput(outputState));
|
|
1937
|
+
}
|
|
1938
|
+
try {
|
|
1939
|
+
if (!context.fresh || freshRequiresExistingClaim) {
|
|
1940
|
+
await claimAgentExecution(agent, context.state);
|
|
1941
|
+
}
|
|
1942
|
+
await emitRunStartTelemetry(agent, context.state, context.memoryMessages, input.approvals, invocationStartedAt);
|
|
1943
|
+
}
|
|
1944
|
+
catch (error) {
|
|
1945
|
+
await executionLease.release();
|
|
1946
|
+
throw error;
|
|
1947
|
+
}
|
|
1948
|
+
if (context.remainingSteps === 0) {
|
|
1949
|
+
const state = createFailedState(context.state, "Agent exhausted maxSteps before reaching a terminal response.");
|
|
1950
|
+
await persistState(agent, state, policy);
|
|
1951
|
+
await emitRunFinishTelemetry(agent, state);
|
|
1952
|
+
await executionLease.release();
|
|
1953
|
+
return returnInvocationOutput(toOutput(state));
|
|
1954
|
+
}
|
|
1955
|
+
let inputGuardrail;
|
|
1956
|
+
try {
|
|
1957
|
+
inputGuardrail = await runGuardrails(agent, context.state, "input", agent.inputGuardrails, () => ({
|
|
1958
|
+
runId: context.state.runId,
|
|
1959
|
+
agentId: context.state.agentId,
|
|
1960
|
+
context: context.context,
|
|
1961
|
+
state: cloneState(context.state),
|
|
1962
|
+
messages: context.messages,
|
|
1963
|
+
metadata: context.state.metadata
|
|
1964
|
+
}));
|
|
1965
|
+
}
|
|
1966
|
+
catch (error) {
|
|
1967
|
+
await executionLease.release();
|
|
1968
|
+
throw error;
|
|
1969
|
+
}
|
|
1970
|
+
if (inputGuardrail) {
|
|
1971
|
+
const failedState = applyGuardrailFailure(context.state, "input", inputGuardrail);
|
|
1972
|
+
await persistState(agent, failedState, policy);
|
|
1973
|
+
await emitRunFinishTelemetry(agent, failedState);
|
|
1974
|
+
await executionLease.release();
|
|
1975
|
+
return returnInvocationOutput(toOutput(failedState));
|
|
1976
|
+
}
|
|
1977
|
+
const abortContext = createAgentAbortContext(mergeAbortSignals(input.abortSignal, executionLease.signal), policy);
|
|
1978
|
+
let executionEnvironmentSession;
|
|
1979
|
+
let executionEnvironmentStatus = "failed";
|
|
1980
|
+
let executionEnvironmentError;
|
|
1981
|
+
try {
|
|
1982
|
+
executionEnvironmentSession = await acquireExecutionEnvironment(context.executionEnvironment, context.state, context.context, abortContext.signal);
|
|
1983
|
+
}
|
|
1984
|
+
catch (error) {
|
|
1985
|
+
await executionLease.release();
|
|
1986
|
+
throw error;
|
|
1987
|
+
}
|
|
1988
|
+
try {
|
|
1989
|
+
const result = await withAgentTelemetryRunContext(agent, context.state.runId, () => withAgentPolicyTimeout(generateText(createGenerateOptions(agent, context.state, input, context.messages, context.remainingSteps, context.context, executionEnvironmentSession, abortContext.signal)), abortContext));
|
|
1990
|
+
const cancelled = executionLease.cancelledState();
|
|
1991
|
+
if (cancelled) {
|
|
1992
|
+
executionEnvironmentStatus = cancelled.status;
|
|
1993
|
+
await emitRunFinishTelemetry(agent, cancelled);
|
|
1994
|
+
return returnInvocationOutput(toOutput(cancelled));
|
|
1995
|
+
}
|
|
1996
|
+
if (executionLease.leaseLost()) {
|
|
1997
|
+
throw new ConflictError(`Agent run "${context.state.runId}" lost its worker lease.`);
|
|
1998
|
+
}
|
|
1999
|
+
const newSteps = mapSteps(result.steps, context.state.currentStep, result.toolResults);
|
|
2000
|
+
let output = finalizeState(agent, context.state, result, newSteps, result.toolResults);
|
|
2001
|
+
const outputGuardrail = await runGuardrails(agent, output.state, "output", agent.outputGuardrails, () => ({
|
|
2002
|
+
runId: output.state.runId,
|
|
2003
|
+
agentId: output.state.agentId,
|
|
2004
|
+
context: context.context,
|
|
2005
|
+
state: cloneState(output.state),
|
|
2006
|
+
output,
|
|
2007
|
+
metadata: output.state.metadata
|
|
2008
|
+
}));
|
|
2009
|
+
if (outputGuardrail) {
|
|
2010
|
+
output = toOutput(applyGuardrailFailure(output.state, "output", outputGuardrail));
|
|
2011
|
+
}
|
|
2012
|
+
await emitFinalizedStepTelemetry(agent, output.state, newSteps);
|
|
2013
|
+
await emitApprovalTelemetry(agent, output.state, [
|
|
2014
|
+
...(result.approvalRequests ?? []),
|
|
2015
|
+
...approvalsFromEvents(newSteps.flatMap((step) => step.response?.messages ?? []))
|
|
2016
|
+
]);
|
|
2017
|
+
await persistState(agent, output.state, policy);
|
|
2018
|
+
await emitRunFinishTelemetry(agent, output.state);
|
|
2019
|
+
executionEnvironmentStatus = output.status;
|
|
2020
|
+
return returnInvocationOutput(output);
|
|
2021
|
+
}
|
|
2022
|
+
catch (error) {
|
|
2023
|
+
executionEnvironmentError = {
|
|
2024
|
+
message: error instanceof Error ? error.message : String(error)
|
|
2025
|
+
};
|
|
2026
|
+
const cancelled = executionLease.cancelledState();
|
|
2027
|
+
if (cancelled) {
|
|
2028
|
+
executionEnvironmentStatus = cancelled.status;
|
|
2029
|
+
await emitRunFinishTelemetry(agent, cancelled);
|
|
2030
|
+
return returnInvocationOutput(toOutput(cancelled));
|
|
2031
|
+
}
|
|
2032
|
+
if (executionLease.leaseLost()) {
|
|
2033
|
+
throw new ConflictError(`Agent run "${context.state.runId}" lost its worker lease.`);
|
|
2034
|
+
}
|
|
2035
|
+
if (error instanceof AgentPolicyTimeoutError || abortContext.isTimedOut()) {
|
|
2036
|
+
const status = policy?.onTimeout === "cancel-requested" ? "cancel_requested" : "timed_out";
|
|
2037
|
+
const message = error instanceof Error ? error.message : `Agent run timed out after ${policy?.timeoutMs}ms.`;
|
|
2038
|
+
const durableState = agent.store
|
|
2039
|
+
? normalizeAgentRunState((await agent.store.load(context.state.runId, context.state.scope)) ?? context.state)
|
|
2040
|
+
: context.state;
|
|
2041
|
+
const timedOutState = createTerminalState(durableState, status, message);
|
|
2042
|
+
await persistState(agent, timedOutState, policy);
|
|
2043
|
+
await emitRunFinishTelemetry(agent, timedOutState);
|
|
2044
|
+
executionEnvironmentStatus = timedOutState.status;
|
|
2045
|
+
return returnInvocationOutput(toOutput(timedOutState));
|
|
2046
|
+
}
|
|
1933
2047
|
const durableState = agent.store
|
|
1934
2048
|
? normalizeAgentRunState((await agent.store.load(context.state.runId, context.state.scope)) ?? context.state)
|
|
1935
2049
|
: context.state;
|
|
1936
|
-
const
|
|
1937
|
-
await persistState(agent,
|
|
1938
|
-
await emitRunFinishTelemetry(agent,
|
|
1939
|
-
executionEnvironmentStatus =
|
|
1940
|
-
|
|
1941
|
-
}
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
2050
|
+
const failedState = createFailedState(durableState, error instanceof Error ? error.message : String(error));
|
|
2051
|
+
await persistState(agent, failedState, policy);
|
|
2052
|
+
await emitRunFinishTelemetry(agent, failedState);
|
|
2053
|
+
executionEnvironmentStatus = failedState.status;
|
|
2054
|
+
throw error;
|
|
2055
|
+
}
|
|
2056
|
+
finally {
|
|
2057
|
+
await executionEnvironmentSession?.release?.({
|
|
2058
|
+
status: executionEnvironmentStatus,
|
|
2059
|
+
error: executionEnvironmentError
|
|
2060
|
+
});
|
|
2061
|
+
await executionLease.release();
|
|
2062
|
+
}
|
|
2063
|
+
}
|
|
2064
|
+
catch (error) {
|
|
2065
|
+
invocationStatus = "failed";
|
|
2066
|
+
invocationError = error instanceof Error ? error : new Error(String(error));
|
|
1949
2067
|
throw error;
|
|
1950
2068
|
}
|
|
1951
2069
|
finally {
|
|
1952
|
-
await
|
|
1953
|
-
status: executionEnvironmentStatus,
|
|
1954
|
-
error: executionEnvironmentError
|
|
1955
|
-
});
|
|
1956
|
-
await executionLease.release();
|
|
2070
|
+
await emitInvocationFinishTelemetry(agent, telemetryRunId, invocationStatus, invocationError);
|
|
1957
2071
|
}
|
|
1958
2072
|
};
|
|
1959
2073
|
export const streamAgent = (agent, input = {}) => {
|
|
2074
|
+
const invocationStartedAt = Date.now();
|
|
2075
|
+
const telemetryRunId = input.runId ?? input.state?.runId ?? randomId("run");
|
|
2076
|
+
const invocationInput = input.runId || input.state
|
|
2077
|
+
? input
|
|
2078
|
+
: { ...input, runId: telemetryRunId };
|
|
1960
2079
|
const policy = resolveRunPolicy(agent, input);
|
|
1961
2080
|
const broadcast = new BoundedReplayBroadcast({
|
|
1962
2081
|
maxHistory: policy?.maxStreamEvents ?? 4096
|
|
@@ -1964,12 +2083,19 @@ export const streamAgent = (agent, input = {}) => {
|
|
|
1964
2083
|
const publish = (event, terminal = false) => broadcast.publish(event, { terminal });
|
|
1965
2084
|
let activeLease;
|
|
1966
2085
|
let activeExecutionEnvironment;
|
|
2086
|
+
let invocationFinishPromise;
|
|
2087
|
+
const finishInvocation = (status, error) => {
|
|
2088
|
+
invocationFinishPromise ??= emitInvocationFinishTelemetry(agent, telemetryRunId, status, error);
|
|
2089
|
+
return invocationFinishPromise;
|
|
2090
|
+
};
|
|
1967
2091
|
const runner = (async () => {
|
|
1968
|
-
|
|
2092
|
+
await emitInvocationStartTelemetry(agent, telemetryRunId, invocationStartedAt, Math.max(1, input.maxSteps ?? input.state?.maxSteps ?? agent.maxSteps ?? 1));
|
|
2093
|
+
const context = await resolveContext(agent, invocationInput);
|
|
1969
2094
|
const currentStatus = normalizeApprovalStatus(context.state.status);
|
|
1970
2095
|
const supportsLeases = Boolean(agent.store?.acquireLease && agent.store.renewLease && agent.store.releaseLease);
|
|
1971
2096
|
if (!context.fresh && currentStatus === "running" && !supportsLeases) {
|
|
1972
2097
|
broadcast.close();
|
|
2098
|
+
await finishInvocation(currentStatus);
|
|
1973
2099
|
return {
|
|
1974
2100
|
output: toOutput(context.state),
|
|
1975
2101
|
textStream: emptyAsyncIterable()
|
|
@@ -1981,6 +2107,7 @@ export const streamAgent = (agent, input = {}) => {
|
|
|
1981
2107
|
currentStatus === "timed_out") {
|
|
1982
2108
|
context.state.status = currentStatus;
|
|
1983
2109
|
broadcast.close();
|
|
2110
|
+
await finishInvocation(currentStatus);
|
|
1984
2111
|
return {
|
|
1985
2112
|
output: toOutput(context.state),
|
|
1986
2113
|
textStream: emptyAsyncIterable()
|
|
@@ -1989,6 +2116,7 @@ export const streamAgent = (agent, input = {}) => {
|
|
|
1989
2116
|
if (currentStatus === "waiting_approval" && context.state.pendingApprovals.length > 0) {
|
|
1990
2117
|
context.state.status = currentStatus;
|
|
1991
2118
|
broadcast.close();
|
|
2119
|
+
await finishInvocation(currentStatus);
|
|
1992
2120
|
return {
|
|
1993
2121
|
output: toOutput(context.state),
|
|
1994
2122
|
textStream: emptyAsyncIterable()
|
|
@@ -2005,8 +2133,10 @@ export const streamAgent = (agent, input = {}) => {
|
|
|
2005
2133
|
}
|
|
2006
2134
|
const activeState = await agent.store?.load(context.state.runId, context.state.scope);
|
|
2007
2135
|
broadcast.close();
|
|
2136
|
+
const outputState = activeState ? normalizeAgentRunState(activeState) : context.state;
|
|
2137
|
+
await finishInvocation(outputState.status);
|
|
2008
2138
|
return {
|
|
2009
|
-
output: toOutput(
|
|
2139
|
+
output: toOutput(outputState),
|
|
2010
2140
|
textStream: emptyAsyncIterable()
|
|
2011
2141
|
};
|
|
2012
2142
|
}
|
|
@@ -2015,7 +2145,7 @@ export const streamAgent = (agent, input = {}) => {
|
|
|
2015
2145
|
if (!context.fresh || freshRequiresExistingClaim) {
|
|
2016
2146
|
await claimAgentExecution(agent, context.state);
|
|
2017
2147
|
}
|
|
2018
|
-
await emitRunStartTelemetry(agent, context.state, context.memoryMessages, input.approvals);
|
|
2148
|
+
await emitRunStartTelemetry(agent, context.state, context.memoryMessages, input.approvals, invocationStartedAt);
|
|
2019
2149
|
}
|
|
2020
2150
|
catch (error) {
|
|
2021
2151
|
await executionLease.release();
|
|
@@ -2027,6 +2157,7 @@ export const streamAgent = (agent, input = {}) => {
|
|
|
2027
2157
|
await emitRunFinishTelemetry(agent, state);
|
|
2028
2158
|
await executionLease.release();
|
|
2029
2159
|
broadcast.close();
|
|
2160
|
+
await finishInvocation(state.status);
|
|
2030
2161
|
return {
|
|
2031
2162
|
output: toOutput(state),
|
|
2032
2163
|
textStream: emptyAsyncIterable()
|
|
@@ -2064,6 +2195,7 @@ export const streamAgent = (agent, input = {}) => {
|
|
|
2064
2195
|
}, true);
|
|
2065
2196
|
broadcast.close();
|
|
2066
2197
|
await executionLease.release();
|
|
2198
|
+
await finishInvocation(failedState.status);
|
|
2067
2199
|
return {
|
|
2068
2200
|
output: toOutput(failedState),
|
|
2069
2201
|
textStream: emptyAsyncIterable()
|
|
@@ -2084,12 +2216,6 @@ export const streamAgent = (agent, input = {}) => {
|
|
|
2084
2216
|
type: "agent-step-start",
|
|
2085
2217
|
stepIndex: context.state.currentStep + 1
|
|
2086
2218
|
});
|
|
2087
|
-
await emitTelemetryEvent(agent, {
|
|
2088
|
-
type: "step-start",
|
|
2089
|
-
runId: context.state.runId,
|
|
2090
|
-
agentId: context.state.agentId,
|
|
2091
|
-
stepIndex: context.state.currentStep + 1
|
|
2092
|
-
});
|
|
2093
2219
|
const abortContext = createAgentAbortContext(mergeAbortSignals(input.abortSignal, executionLease.signal), policy);
|
|
2094
2220
|
const executionEnvironmentSession = await acquireExecutionEnvironment(context.executionEnvironment, context.state, context.context, abortContext.signal);
|
|
2095
2221
|
activeExecutionEnvironment = executionEnvironmentSession;
|
|
@@ -2117,7 +2243,7 @@ export const streamAgent = (agent, input = {}) => {
|
|
|
2117
2243
|
throw error;
|
|
2118
2244
|
}
|
|
2119
2245
|
const approvalRequests = [];
|
|
2120
|
-
const eventRelay = (async () => {
|
|
2246
|
+
const eventRelay = withAgentTelemetryRunContext(agent, context.state.runId, async () => {
|
|
2121
2247
|
for await (const event of streamResult.eventStream) {
|
|
2122
2248
|
await publish(event);
|
|
2123
2249
|
if (event.type === "tool-approval-request") {
|
|
@@ -2162,7 +2288,7 @@ export const streamAgent = (agent, input = {}) => {
|
|
|
2162
2288
|
});
|
|
2163
2289
|
}
|
|
2164
2290
|
}
|
|
2165
|
-
})
|
|
2291
|
+
});
|
|
2166
2292
|
const output = (async () => {
|
|
2167
2293
|
try {
|
|
2168
2294
|
const final = await withAgentPolicyTimeout(eventRelay.then(() => streamResult.collect()), abortContext);
|
|
@@ -2291,12 +2417,13 @@ export const streamAgent = (agent, input = {}) => {
|
|
|
2291
2417
|
activeExecutionEnvironment = undefined;
|
|
2292
2418
|
await executionLease.release();
|
|
2293
2419
|
}
|
|
2294
|
-
})();
|
|
2420
|
+
})().finally(() => finishInvocation(executionEnvironmentStatus, executionEnvironmentError ? new Error(executionEnvironmentError.message) : undefined));
|
|
2295
2421
|
return {
|
|
2296
2422
|
output,
|
|
2297
2423
|
textStream: streamResult.textStream
|
|
2298
2424
|
};
|
|
2299
2425
|
})().catch(async (error) => {
|
|
2426
|
+
await finishInvocation("failed", error instanceof Error ? error : new Error(String(error)));
|
|
2300
2427
|
await activeExecutionEnvironment?.release?.({
|
|
2301
2428
|
status: "failed",
|
|
2302
2429
|
error: { message: error instanceof Error ? error.message : String(error) }
|