stitchkit 0.87.1 → 0.89.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/CHANGELOG.md +190 -0
- package/dist/agent-runtime/child-blocking.d.ts +17 -0
- package/dist/agent-runtime/child-blocking.d.ts.map +1 -0
- package/dist/agent-runtime/child-budget-policy.d.ts +23 -0
- package/dist/agent-runtime/child-budget-policy.d.ts.map +1 -0
- package/dist/agent-runtime/children-contract.d.ts +155 -0
- package/dist/agent-runtime/children-contract.d.ts.map +1 -0
- package/dist/agent-runtime/children.d.ts +4 -99
- package/dist/agent-runtime/children.d.ts.map +1 -1
- package/dist/agent-runtime/coding-shell-process.d.ts +33 -0
- package/dist/agent-runtime/coding-shell-process.d.ts.map +1 -0
- package/dist/agent-runtime/coding-tool-contract.d.ts +18 -0
- package/dist/agent-runtime/coding-tool-contract.d.ts.map +1 -1
- package/dist/agent-runtime/coding-tool-files.d.ts.map +1 -1
- package/dist/agent-runtime/coding-tool-listing.d.ts.map +1 -1
- package/dist/agent-runtime/coding-tool-paths.d.ts +1 -1
- package/dist/agent-runtime/coding-tool-paths.d.ts.map +1 -1
- package/dist/agent-runtime/coding-tool-search-patch.d.ts.map +1 -1
- package/dist/agent-runtime/coding-tool-shell.d.ts.map +1 -1
- package/dist/agent-runtime/coding-tool-utf8.d.ts +28 -0
- package/dist/agent-runtime/coding-tool-utf8.d.ts.map +1 -0
- package/dist/agent-runtime/contained-files.d.ts +20 -0
- package/dist/agent-runtime/contained-files.d.ts.map +1 -1
- package/dist/agent-runtime/durability-contract.d.ts +176 -0
- package/dist/agent-runtime/durability-contract.d.ts.map +1 -0
- package/dist/agent-runtime/durability-json.d.ts +3 -0
- package/dist/agent-runtime/durability-json.d.ts.map +1 -0
- package/dist/agent-runtime/durability-ledger.d.ts +16 -0
- package/dist/agent-runtime/durability-ledger.d.ts.map +1 -0
- package/dist/agent-runtime/durability-scheduler.d.ts +29 -0
- package/dist/agent-runtime/durability-scheduler.d.ts.map +1 -0
- package/dist/agent-runtime/durability.d.ts +14 -0
- package/dist/agent-runtime/durability.d.ts.map +1 -0
- package/dist/agent-runtime/event-search.d.ts.map +1 -1
- package/dist/agent-runtime/harness-contract.d.ts +37 -0
- package/dist/agent-runtime/harness-contract.d.ts.map +1 -1
- package/dist/agent-runtime/harness.d.ts +8 -0
- package/dist/agent-runtime/harness.d.ts.map +1 -1
- package/dist/agent-runtime/models.d.ts +14 -0
- package/dist/agent-runtime/models.d.ts.map +1 -1
- package/dist/agent-runtime/observability.d.ts +8 -0
- package/dist/agent-runtime/observability.d.ts.map +1 -1
- package/dist/agent-runtime/owned-provider-stream.d.ts +16 -0
- package/dist/agent-runtime/owned-provider-stream.d.ts.map +1 -0
- package/dist/agent-runtime/prompt.d.ts +23 -0
- package/dist/agent-runtime/prompt.d.ts.map +1 -1
- package/dist/agent-runtime/run-execution.d.ts.map +1 -1
- package/dist/agent-runtime/runtime-internals.d.ts +16 -0
- package/dist/agent-runtime/runtime-internals.d.ts.map +1 -1
- package/dist/agent-runtime/runtime.d.ts +25 -0
- package/dist/agent-runtime/runtime.d.ts.map +1 -1
- package/dist/agent-runtime/sandbox-broker.d.ts +7 -0
- package/dist/agent-runtime/sandbox-broker.d.ts.map +1 -0
- package/dist/agent-runtime/sandbox-bubblewrap-args.d.ts +9 -0
- package/dist/agent-runtime/sandbox-bubblewrap-args.d.ts.map +1 -0
- package/dist/agent-runtime/sandbox-bubblewrap-storage.d.ts +22 -0
- package/dist/agent-runtime/sandbox-bubblewrap-storage.d.ts.map +1 -0
- package/dist/agent-runtime/sandbox-bubblewrap.d.ts +14 -0
- package/dist/agent-runtime/sandbox-bubblewrap.d.ts.map +1 -0
- package/dist/agent-runtime/sandbox-coding-adapter.d.ts +15 -0
- package/dist/agent-runtime/sandbox-coding-adapter.d.ts.map +1 -0
- package/dist/agent-runtime/sandbox-coding.d.ts +15 -0
- package/dist/agent-runtime/sandbox-coding.d.ts.map +1 -0
- package/dist/agent-runtime/sandbox-contract.d.ts +93 -0
- package/dist/agent-runtime/sandbox-contract.d.ts.map +1 -0
- package/dist/agent-runtime/sandbox-process-owner.d.ts +11 -0
- package/dist/agent-runtime/sandbox-process-owner.d.ts.map +1 -0
- package/dist/agent-runtime/sandbox-process.d.ts +8 -0
- package/dist/agent-runtime/sandbox-process.d.ts.map +1 -0
- package/dist/agent-runtime/sandbox-session.d.ts +5 -0
- package/dist/agent-runtime/sandbox-session.d.ts.map +1 -0
- package/dist/agent-runtime/sandbox.d.ts +19 -0
- package/dist/agent-runtime/sandbox.d.ts.map +1 -1
- package/dist/agent-runtime/schemas.d.ts +6 -0
- package/dist/agent-runtime/schemas.d.ts.map +1 -1
- package/dist/agent-runtime/sqlite-purge.d.ts.map +1 -1
- package/dist/agent-runtime/sqlite.d.ts.map +1 -1
- package/dist/agent-runtime/store-driver.d.ts +127 -0
- package/dist/agent-runtime/store-driver.d.ts.map +1 -1
- package/dist/agent-runtime/store-events.d.ts +106 -0
- package/dist/agent-runtime/store-events.d.ts.map +1 -1
- package/dist/agent-runtime/store-migrations/v2-to-v3.d.ts +14 -0
- package/dist/agent-runtime/store-migrations/v2-to-v3.d.ts.map +1 -0
- package/dist/agent-runtime/store.d.ts +115 -0
- package/dist/agent-runtime/store.d.ts.map +1 -1
- package/dist/agent-runtime-browser.js +5 -3
- package/dist/agent-runtime-coding-tools.js +11 -1236
- package/dist/agent-runtime-harness.d.ts +1 -1
- package/dist/agent-runtime-harness.d.ts.map +1 -1
- package/dist/agent-runtime-harness.js +69 -19
- package/dist/agent-runtime-openrouter.d.ts +3 -12
- package/dist/agent-runtime-openrouter.d.ts.map +1 -1
- package/dist/agent-runtime-openrouter.js +22 -9
- package/dist/agent-runtime-sandbox.d.ts +5 -0
- package/dist/agent-runtime-sandbox.d.ts.map +1 -0
- package/dist/agent-runtime-sandbox.js +797 -0
- package/dist/agent-runtime-sqlite-bun.js +5 -5
- package/dist/agent-runtime-sqlite-node.js +5 -5
- package/dist/agent-runtime.d.ts +6 -5
- package/dist/agent-runtime.d.ts.map +1 -1
- package/dist/agent-runtime.js +266 -69
- package/dist/application.js +26 -26
- package/dist/cli.js +8 -8
- package/dist/{index-rcgsnrr6.js → index-31jw8fjq.js} +3 -3
- package/dist/{index-9hw9eq48.js → index-7601qfg1.js} +14 -14
- package/dist/{index-3xnq72rz.js → index-7rkhw9ec.js} +14 -1
- package/dist/{index-0vfdh685.js → index-8c3a7m4g.js} +1 -1
- package/dist/{index-t7gh5w3v.js → index-bn2cjajt.js} +27 -6
- package/dist/{index-z2452tsw.js → index-bt14acb5.js} +2 -2
- package/dist/index-cp20z0n6.js +1351 -0
- package/dist/{index-9553432s.js → index-crykmqkr.js} +1 -1
- package/dist/{index-6g273pqx.js → index-fadnxwna.js} +89 -7
- package/dist/{index-p1b1y93x.js → index-gtj3zc53.js} +5 -1
- package/dist/{index-5wezxcxx.js → index-hrbajay7.js} +107 -5
- package/dist/{index-35aefxby.js → index-hw2chdvy.js} +768 -49
- package/dist/{index-0ydchz76.js → index-mnm4qp0p.js} +5 -5
- package/dist/{index-tg3m2ec5.js → index-mqv3b5rh.js} +4 -1
- package/dist/{index-1szetq6f.js → index-q3ve2d1k.js} +30 -8
- package/dist/{index-hkm6wysp.js → index-y64k3s0h.js} +1 -1
- package/dist/{index-z1m86vc8.js → index-zwkgfq1s.js} +97 -86
- package/dist/{index-wn9cb82y.js → index-zyvby92n.js} +12 -9
- package/dist/index.js +13 -13
- package/dist/server/index.js +9 -9
- package/dist/testing/agent-store-conformance.d.ts.map +1 -1
- package/dist/testing.js +69 -24
- package/dist/tool-invoker.js +6 -6
- package/dist/tools/agent.d.ts +6 -0
- package/dist/tools/agent.d.ts.map +1 -1
- package/dist/tools/connections/define.d.ts +6 -0
- package/dist/tools/connections/define.d.ts.map +1 -0
- package/dist/tools/connections/errors.d.ts +50 -0
- package/dist/tools/connections/errors.d.ts.map +1 -0
- package/dist/tools/connections/http.d.ts +3 -0
- package/dist/tools/connections/http.d.ts.map +1 -0
- package/dist/tools/connections/index.d.ts +19 -0
- package/dist/tools/connections/index.d.ts.map +1 -0
- package/dist/tools/connections/index.js +1047 -0
- package/dist/tools/connections/instance.d.ts +3 -0
- package/dist/tools/connections/instance.d.ts.map +1 -0
- package/dist/tools/connections/json-rpc.d.ts +8 -0
- package/dist/tools/connections/json-rpc.d.ts.map +1 -0
- package/dist/tools/connections/limits.d.ts +36 -0
- package/dist/tools/connections/limits.d.ts.map +1 -0
- package/dist/tools/connections/mcp-client.d.ts +44 -0
- package/dist/tools/connections/mcp-client.d.ts.map +1 -0
- package/dist/tools/connections/mcp.d.ts +5 -0
- package/dist/tools/connections/mcp.d.ts.map +1 -0
- package/dist/tools/connections/mount.d.ts +12 -0
- package/dist/tools/connections/mount.d.ts.map +1 -0
- package/dist/tools/connections/openapi-document.d.ts +4 -0
- package/dist/tools/connections/openapi-document.d.ts.map +1 -0
- package/dist/tools/connections/openapi.d.ts +5 -0
- package/dist/tools/connections/openapi.d.ts.map +1 -0
- package/dist/tools/connections/runtime.d.ts +29 -0
- package/dist/tools/connections/runtime.d.ts.map +1 -0
- package/dist/tools/connections/schema-budget.d.ts +8 -0
- package/dist/tools/connections/schema-budget.d.ts.map +1 -0
- package/dist/tools/connections/sse-frames.d.ts +7 -0
- package/dist/tools/connections/sse-frames.d.ts.map +1 -0
- package/dist/tools/connections/sse-session.d.ts +26 -0
- package/dist/tools/connections/sse-session.d.ts.map +1 -0
- package/dist/tools/connections/ssrf.d.ts +15 -0
- package/dist/tools/connections/ssrf.d.ts.map +1 -0
- package/dist/tools/connections/types.d.ts +60 -0
- package/dist/tools/connections/types.d.ts.map +1 -0
- package/dist/tools/durability-context.d.ts +7 -0
- package/dist/tools/durability-context.d.ts.map +1 -0
- package/dist/tools/execute.d.ts +2 -0
- package/dist/tools/execute.d.ts.map +1 -1
- package/dist/tools/registry.d.ts +38 -0
- package/dist/tools/registry.d.ts.map +1 -0
- package/dist/tools/runtime-tool.d.ts +4 -0
- package/dist/tools/runtime-tool.d.ts.map +1 -1
- package/dist/tools.d.ts +1 -0
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +83 -26
- package/llms-full.txt +329 -14
- package/llms.txt +1 -0
- package/package.json +9 -1
- package/dist/{index-evcnmsc3.js → index-t7fkyxcr.js} +3 -3
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
import {
|
|
5
5
|
AgentRuntimeEventSchema,
|
|
6
6
|
agentDurableEventId
|
|
7
|
-
} from "./index-
|
|
7
|
+
} from "./index-y64k3s0h.js";
|
|
8
8
|
import {
|
|
9
9
|
advanceToolChronology,
|
|
10
10
|
assistantStatus,
|
|
@@ -13,28 +13,30 @@ import {
|
|
|
13
13
|
createToolChronology,
|
|
14
14
|
isAssistantHistoryEvidence,
|
|
15
15
|
isCompleteAgentHistoryTurn
|
|
16
|
-
} from "./index-
|
|
16
|
+
} from "./index-zwkgfq1s.js";
|
|
17
17
|
import {
|
|
18
18
|
AgentAssistantPlaceholderSchema,
|
|
19
19
|
AgentJsonObjectSchema,
|
|
20
20
|
AgentMessagePartSchema,
|
|
21
21
|
AgentMessageSchema,
|
|
22
22
|
AgentProvenanceSchema,
|
|
23
|
+
AgentProviderResponseSchema,
|
|
23
24
|
AgentRunOperationSchema,
|
|
24
25
|
AgentRunSchema,
|
|
25
26
|
AgentSnapshotSchema,
|
|
26
27
|
runStateForTerminalReason
|
|
27
|
-
} from "./index-
|
|
28
|
+
} from "./index-gtj3zc53.js";
|
|
28
29
|
import {
|
|
29
30
|
createBoundedSinkManager
|
|
30
31
|
} from "./index-wnfk50r0.js";
|
|
31
32
|
import {
|
|
33
|
+
createToolDurabilityContext,
|
|
32
34
|
isAgentToolError
|
|
33
|
-
} from "./index-
|
|
35
|
+
} from "./index-7rkhw9ec.js";
|
|
34
36
|
import {
|
|
35
37
|
ToolExecutionControlError,
|
|
36
38
|
isToolExecutionControlError
|
|
37
|
-
} from "./index-
|
|
39
|
+
} from "./index-zyvby92n.js";
|
|
38
40
|
import {
|
|
39
41
|
isRecord,
|
|
40
42
|
transportResult
|
|
@@ -314,6 +316,479 @@ function createAgentSessionCoordinator() {
|
|
|
314
316
|
};
|
|
315
317
|
}
|
|
316
318
|
|
|
319
|
+
// src/agent-runtime/durability-contract.ts
|
|
320
|
+
import { z } from "zod";
|
|
321
|
+
var DURABILITY_STEP_EVENT_KIND = "durability/step";
|
|
322
|
+
var DURABILITY_PARK_EVENT_KIND = "durability/park";
|
|
323
|
+
var DURABILITY_EVENT_EVENT_KIND = "durability/event";
|
|
324
|
+
var StepEventPayloadSchema = z.object({
|
|
325
|
+
runId: z.string().min(1),
|
|
326
|
+
stepName: z.string().min(1),
|
|
327
|
+
encoded: z.string()
|
|
328
|
+
});
|
|
329
|
+
var SleepParkSchema = z.object({
|
|
330
|
+
runId: z.string().min(1),
|
|
331
|
+
kind: z.literal("sleep"),
|
|
332
|
+
name: z.string().min(1),
|
|
333
|
+
deadline: z.number()
|
|
334
|
+
});
|
|
335
|
+
var WaitParkSchema = z.object({
|
|
336
|
+
runId: z.string().min(1),
|
|
337
|
+
kind: z.literal("wait"),
|
|
338
|
+
event: z.string().min(1),
|
|
339
|
+
id: z.string().min(1)
|
|
340
|
+
});
|
|
341
|
+
var ParkEventPayloadSchema = z.discriminatedUnion("kind", [
|
|
342
|
+
SleepParkSchema,
|
|
343
|
+
WaitParkSchema
|
|
344
|
+
]);
|
|
345
|
+
var DeliveredEventPayloadSchema = z.object({
|
|
346
|
+
runId: z.string().min(1),
|
|
347
|
+
event: z.string().min(1),
|
|
348
|
+
id: z.string().min(1),
|
|
349
|
+
encoded: z.string()
|
|
350
|
+
});
|
|
351
|
+
|
|
352
|
+
class StepResultDecodeError extends Error {
|
|
353
|
+
constructor(message, options) {
|
|
354
|
+
super(message, options);
|
|
355
|
+
this.name = "StepResultDecodeError";
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
class StepResultNotSerializableError extends Error {
|
|
360
|
+
constructor(stepName, cause) {
|
|
361
|
+
super(`Step "${stepName}" returned a value that is not JSON-serializable`, {
|
|
362
|
+
cause
|
|
363
|
+
});
|
|
364
|
+
this.name = "StepResultNotSerializableError";
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
class StepAbortedError extends Error {
|
|
369
|
+
constructor(stepName) {
|
|
370
|
+
super(`Step "${stepName}" was aborted before it started`);
|
|
371
|
+
this.name = "StepAbortedError";
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
class ParkRecordDecodeError extends Error {
|
|
376
|
+
constructor(message, options) {
|
|
377
|
+
super(message, options);
|
|
378
|
+
this.name = "ParkRecordDecodeError";
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
class ParkAbortedError extends Error {
|
|
383
|
+
constructor(park) {
|
|
384
|
+
super(`Park "${park}" was aborted before it was satisfied`);
|
|
385
|
+
this.name = "ParkAbortedError";
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
// src/agent-runtime/durability-json.ts
|
|
390
|
+
import { z as z2 } from "zod";
|
|
391
|
+
function losslessJson(value, ancestors = new Set, depth = 0) {
|
|
392
|
+
if (depth > 100)
|
|
393
|
+
return false;
|
|
394
|
+
if (value === null || typeof value === "string" || typeof value === "boolean")
|
|
395
|
+
return true;
|
|
396
|
+
if (typeof value === "number")
|
|
397
|
+
return Number.isFinite(value) && !Object.is(value, -0);
|
|
398
|
+
if (typeof value !== "object" || ancestors.has(value))
|
|
399
|
+
return false;
|
|
400
|
+
const array = Array.isArray(value);
|
|
401
|
+
const prototype = Object.getPrototypeOf(value);
|
|
402
|
+
if (array ? prototype !== Array.prototype : prototype !== Object.prototype && prototype !== null)
|
|
403
|
+
return false;
|
|
404
|
+
ancestors.add(value);
|
|
405
|
+
try {
|
|
406
|
+
const descriptors = Object.getOwnPropertyDescriptors(value);
|
|
407
|
+
const keys = Reflect.ownKeys(descriptors);
|
|
408
|
+
if (array && keys.length !== value.length + 1)
|
|
409
|
+
return false;
|
|
410
|
+
for (const key of keys) {
|
|
411
|
+
if (array && key === "length")
|
|
412
|
+
continue;
|
|
413
|
+
if (typeof key !== "string")
|
|
414
|
+
return false;
|
|
415
|
+
if (array && (!/^(0|[1-9][0-9]*)$/.test(key) || Number(key) >= value.length))
|
|
416
|
+
return false;
|
|
417
|
+
const descriptor = descriptors[key];
|
|
418
|
+
if (!descriptor?.enumerable || !("value" in descriptor))
|
|
419
|
+
return false;
|
|
420
|
+
if (!losslessJson(descriptor.value, ancestors, depth + 1))
|
|
421
|
+
return false;
|
|
422
|
+
}
|
|
423
|
+
return true;
|
|
424
|
+
} finally {
|
|
425
|
+
ancestors.delete(value);
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
var DurableJsonSchema = z2.custom((value) => losslessJson(value), "Expected lossless JSON data (finite numbers, plain objects and dense arrays; no accessors)");
|
|
429
|
+
|
|
430
|
+
// src/agent-runtime/durability-ledger.ts
|
|
431
|
+
function stepKey(conversationId, runId, stepName) {
|
|
432
|
+
return JSON.stringify([conversationId, runId, stepName]);
|
|
433
|
+
}
|
|
434
|
+
function sleepParkKey(conversationId, runId, name) {
|
|
435
|
+
return JSON.stringify([conversationId, runId, "sleep", name]);
|
|
436
|
+
}
|
|
437
|
+
function waitParkKey(conversationId, runId, event, id) {
|
|
438
|
+
return JSON.stringify([conversationId, runId, "wait", event, id]);
|
|
439
|
+
}
|
|
440
|
+
function parkEventKey(conversationId, payload) {
|
|
441
|
+
return payload.kind === "sleep" ? sleepParkKey(conversationId, payload.runId, payload.name) : waitParkKey(conversationId, payload.runId, payload.event, payload.id);
|
|
442
|
+
}
|
|
443
|
+
function encodeStepResult(stepName, value) {
|
|
444
|
+
let encoded;
|
|
445
|
+
try {
|
|
446
|
+
encoded = JSON.stringify(DurableJsonSchema.parse(value));
|
|
447
|
+
} catch (cause) {
|
|
448
|
+
throw new StepResultNotSerializableError(stepName, cause);
|
|
449
|
+
}
|
|
450
|
+
if (encoded === undefined) {
|
|
451
|
+
throw new StepResultNotSerializableError(stepName, value);
|
|
452
|
+
}
|
|
453
|
+
return encoded;
|
|
454
|
+
}
|
|
455
|
+
function encodeDeliveredPayload(event, id, payload) {
|
|
456
|
+
let encoded;
|
|
457
|
+
try {
|
|
458
|
+
encoded = JSON.stringify(DurableJsonSchema.parse(payload === undefined ? null : payload));
|
|
459
|
+
} catch (cause) {
|
|
460
|
+
throw new TypeError(`Delivered event "${event}#${id}" payload is not JSON-serializable`, {
|
|
461
|
+
cause
|
|
462
|
+
});
|
|
463
|
+
}
|
|
464
|
+
if (encoded === undefined) {
|
|
465
|
+
throw new TypeError(`Delivered event "${event}#${id}" payload is not JSON-serializable`);
|
|
466
|
+
}
|
|
467
|
+
return encoded;
|
|
468
|
+
}
|
|
469
|
+
function decodeStepPayload(event) {
|
|
470
|
+
const parsed = StepEventPayloadSchema.safeParse(event.payload);
|
|
471
|
+
if (!parsed.success) {
|
|
472
|
+
throw new StepResultDecodeError(`Recorded step event ${event.eventId} in conversation ${event.conversationId} is malformed`, { cause: parsed.error });
|
|
473
|
+
}
|
|
474
|
+
return parsed.data;
|
|
475
|
+
}
|
|
476
|
+
function decodeRecordedResult(payload, event) {
|
|
477
|
+
try {
|
|
478
|
+
return DurableJsonSchema.parse(JSON.parse(payload.encoded));
|
|
479
|
+
} catch (cause) {
|
|
480
|
+
throw new StepResultDecodeError(`Recorded result for step "${payload.stepName}" (run ${payload.runId}, ` + `event ${event.eventId}) is not decodable JSON`, { cause });
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
function decodeParkPayload(event) {
|
|
484
|
+
const parsed = ParkEventPayloadSchema.safeParse(event.payload);
|
|
485
|
+
if (!parsed.success) {
|
|
486
|
+
throw new ParkRecordDecodeError(`Recorded park event ${event.eventId} in conversation ${event.conversationId} is malformed`, { cause: parsed.error });
|
|
487
|
+
}
|
|
488
|
+
return parsed.data;
|
|
489
|
+
}
|
|
490
|
+
function decodeDeliveredPayload(event) {
|
|
491
|
+
const parsed = DeliveredEventPayloadSchema.safeParse(event.payload);
|
|
492
|
+
if (!parsed.success) {
|
|
493
|
+
throw new ParkRecordDecodeError(`Delivered event ${event.eventId} in conversation ${event.conversationId} is malformed`, { cause: parsed.error });
|
|
494
|
+
}
|
|
495
|
+
return parsed.data;
|
|
496
|
+
}
|
|
497
|
+
function decodeDeliveredResult(payload, event) {
|
|
498
|
+
try {
|
|
499
|
+
return JSON.parse(payload.encoded);
|
|
500
|
+
} catch (cause) {
|
|
501
|
+
throw new ParkRecordDecodeError(`Delivered payload for "${payload.event}#${payload.id}" (run ${payload.runId}, ` + `event ${event.eventId}) is not decodable JSON`, { cause });
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
async function readDurabilityLedger(store, conversationId, view) {
|
|
505
|
+
const { steps, parks, deliveries } = view;
|
|
506
|
+
let fromSeq = view.nextSeq;
|
|
507
|
+
for (;; ) {
|
|
508
|
+
const page = await store.readEvents({
|
|
509
|
+
conversationId,
|
|
510
|
+
...fromSeq !== undefined && { fromSeq },
|
|
511
|
+
limit: 1e4
|
|
512
|
+
});
|
|
513
|
+
for (const event of page.items) {
|
|
514
|
+
if (event.kind === DURABILITY_STEP_EVENT_KIND) {
|
|
515
|
+
const payload = decodeStepPayload(event);
|
|
516
|
+
steps.set(stepKey(event.conversationId, payload.runId, payload.stepName), decodeRecordedResult(payload, event));
|
|
517
|
+
} else if (event.kind === DURABILITY_PARK_EVENT_KIND) {
|
|
518
|
+
const payload = decodeParkPayload(event);
|
|
519
|
+
parks.set(parkEventKey(event.conversationId, payload), payload);
|
|
520
|
+
} else if (event.kind === DURABILITY_EVENT_EVENT_KIND) {
|
|
521
|
+
const payload = decodeDeliveredPayload(event);
|
|
522
|
+
const key = waitParkKey(event.conversationId, payload.runId, payload.event, payload.id);
|
|
523
|
+
if (!deliveries.has(key))
|
|
524
|
+
deliveries.set(key, decodeDeliveredResult(payload, event));
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
const last = page.items.at(-1);
|
|
528
|
+
if (last)
|
|
529
|
+
view.nextSeq = last.seq + 1;
|
|
530
|
+
if (page.nextSeq === undefined)
|
|
531
|
+
break;
|
|
532
|
+
fromSeq = page.nextSeq;
|
|
533
|
+
}
|
|
534
|
+
return view;
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
// src/agent-runtime/durability-scheduler.ts
|
|
538
|
+
var systemClock = {
|
|
539
|
+
now: () => Date.now(),
|
|
540
|
+
schedule(callback, delayMs) {
|
|
541
|
+
const timer = setTimeout(callback, Math.min(delayMs, 2147483647));
|
|
542
|
+
timer.unref();
|
|
543
|
+
return { cancel: () => clearTimeout(timer) };
|
|
544
|
+
}
|
|
545
|
+
};
|
|
546
|
+
var stores = new WeakMap;
|
|
547
|
+
function notifyWaiters(parkWaiters, key) {
|
|
548
|
+
const waiters = parkWaiters.get(key);
|
|
549
|
+
if (!waiters)
|
|
550
|
+
return;
|
|
551
|
+
for (const wake of [...waiters])
|
|
552
|
+
wake();
|
|
553
|
+
}
|
|
554
|
+
function waitForTimer(clock, delayMs, signal) {
|
|
555
|
+
return new Promise((resolve) => {
|
|
556
|
+
let timer;
|
|
557
|
+
let settled = false;
|
|
558
|
+
const finish = (outcome) => {
|
|
559
|
+
if (settled)
|
|
560
|
+
return;
|
|
561
|
+
settled = true;
|
|
562
|
+
timer?.cancel();
|
|
563
|
+
signal?.removeEventListener("abort", onAbort);
|
|
564
|
+
resolve(outcome);
|
|
565
|
+
};
|
|
566
|
+
const onAbort = () => finish("aborted");
|
|
567
|
+
timer = clock.schedule(() => finish("elapsed"), delayMs);
|
|
568
|
+
if (signal) {
|
|
569
|
+
if (signal.aborted)
|
|
570
|
+
onAbort();
|
|
571
|
+
else
|
|
572
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
573
|
+
}
|
|
574
|
+
});
|
|
575
|
+
}
|
|
576
|
+
async function waitForDeadline(clock, deadline, park, signal) {
|
|
577
|
+
for (;; ) {
|
|
578
|
+
if (signal?.aborted)
|
|
579
|
+
throw new ParkAbortedError(park);
|
|
580
|
+
const remaining = deadline - clock.now();
|
|
581
|
+
if (remaining <= 0)
|
|
582
|
+
return;
|
|
583
|
+
const outcome = await waitForTimer(clock, remaining, signal);
|
|
584
|
+
if (outcome === "aborted")
|
|
585
|
+
throw new ParkAbortedError(park);
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
function createParkWaiter(parkWaiters, key, signal) {
|
|
589
|
+
const waiters = parkWaiters.get(key) ?? new Set;
|
|
590
|
+
parkWaiters.set(key, waiters);
|
|
591
|
+
let settle;
|
|
592
|
+
const outcome = new Promise((resolve) => {
|
|
593
|
+
settle = resolve;
|
|
594
|
+
});
|
|
595
|
+
let settled = false;
|
|
596
|
+
const cleanup = () => {
|
|
597
|
+
waiters.delete(onWake);
|
|
598
|
+
if (waiters.size === 0)
|
|
599
|
+
parkWaiters.delete(key);
|
|
600
|
+
signal?.removeEventListener("abort", onAbort);
|
|
601
|
+
};
|
|
602
|
+
const finish = (result) => {
|
|
603
|
+
if (settled)
|
|
604
|
+
return;
|
|
605
|
+
settled = true;
|
|
606
|
+
cleanup();
|
|
607
|
+
settle(result);
|
|
608
|
+
};
|
|
609
|
+
const onWake = () => finish("woke");
|
|
610
|
+
const onAbort = () => finish("aborted");
|
|
611
|
+
waiters.add(onWake);
|
|
612
|
+
if (signal) {
|
|
613
|
+
if (signal.aborted)
|
|
614
|
+
onAbort();
|
|
615
|
+
else
|
|
616
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
617
|
+
}
|
|
618
|
+
return { outcome, cancel: cleanup };
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
// src/agent-runtime/durability.ts
|
|
622
|
+
function releaseSettled(registry, key, pending) {
|
|
623
|
+
const release = () => {
|
|
624
|
+
if (registry.get(key) === pending)
|
|
625
|
+
registry.delete(key);
|
|
626
|
+
};
|
|
627
|
+
pending.then(release, release);
|
|
628
|
+
}
|
|
629
|
+
function detachedResult(pending) {
|
|
630
|
+
return pending.then((value) => JSON.parse(JSON.stringify(value)));
|
|
631
|
+
}
|
|
632
|
+
function createLocalStepDurability(options) {
|
|
633
|
+
const { store, conversationId, runId } = options;
|
|
634
|
+
const inFlight = stores.get(store) ?? {
|
|
635
|
+
steps: new Map,
|
|
636
|
+
parks: new Map,
|
|
637
|
+
waiters: new Map
|
|
638
|
+
};
|
|
639
|
+
stores.set(store, inFlight);
|
|
640
|
+
const { steps: inFlightSteps, parks: inFlightParks, waiters: parkWaiters } = inFlight;
|
|
641
|
+
const clock = options.clock ?? systemClock;
|
|
642
|
+
const view = {
|
|
643
|
+
steps: new Map,
|
|
644
|
+
parks: new Map,
|
|
645
|
+
deliveries: new Map,
|
|
646
|
+
nextSeq: 1
|
|
647
|
+
};
|
|
648
|
+
let reading = Promise.resolve(view);
|
|
649
|
+
const readLedger = () => {
|
|
650
|
+
reading = reading.catch(() => view).then(() => readDurabilityLedger(store, conversationId, view));
|
|
651
|
+
return reading;
|
|
652
|
+
};
|
|
653
|
+
const readRecordedStep = async (name) => {
|
|
654
|
+
const key = stepKey(conversationId, runId, name);
|
|
655
|
+
const records = await readLedger();
|
|
656
|
+
const value = records.steps.get(key);
|
|
657
|
+
return value === undefined ? undefined : JSON.parse(JSON.stringify(value));
|
|
658
|
+
};
|
|
659
|
+
const execute = async (name, body, runOptions) => {
|
|
660
|
+
const recorded = await readRecordedStep(name);
|
|
661
|
+
if (recorded !== undefined) {
|
|
662
|
+
return recorded;
|
|
663
|
+
}
|
|
664
|
+
if (runOptions?.signal?.aborted || options.signal?.aborted)
|
|
665
|
+
throw new StepAbortedError(name);
|
|
666
|
+
const value = await body();
|
|
667
|
+
const encoded = encodeStepResult(name, value);
|
|
668
|
+
await store.appendEvent({
|
|
669
|
+
conversationId,
|
|
670
|
+
kind: DURABILITY_STEP_EVENT_KIND,
|
|
671
|
+
payload: { runId, stepName: name, encoded }
|
|
672
|
+
});
|
|
673
|
+
return JSON.parse(encoded);
|
|
674
|
+
};
|
|
675
|
+
const step = (name, body, runOptions) => {
|
|
676
|
+
const key = stepKey(conversationId, runId, name);
|
|
677
|
+
const existing = inFlightSteps.get(key);
|
|
678
|
+
if (existing) {
|
|
679
|
+
return detachedResult(existing);
|
|
680
|
+
}
|
|
681
|
+
const pending = execute(name, body, runOptions);
|
|
682
|
+
inFlightSteps.set(key, pending);
|
|
683
|
+
releaseSettled(inFlightSteps, key, pending);
|
|
684
|
+
return detachedResult(pending);
|
|
685
|
+
};
|
|
686
|
+
const executeSleep = async (name, seconds, runOptions) => {
|
|
687
|
+
const key = sleepParkKey(conversationId, runId, name);
|
|
688
|
+
const signal = options.signal && runOptions?.signal ? AbortSignal.any([options.signal, runOptions.signal]) : runOptions?.signal ?? options.signal;
|
|
689
|
+
const ledger = await readLedger();
|
|
690
|
+
const existing = ledger.parks.get(key);
|
|
691
|
+
let deadline;
|
|
692
|
+
if (existing) {
|
|
693
|
+
if (existing.kind !== "sleep") {
|
|
694
|
+
throw new ParkRecordDecodeError(`Recorded park "${name}" is not a sleep record`);
|
|
695
|
+
}
|
|
696
|
+
deadline = existing.deadline;
|
|
697
|
+
} else {
|
|
698
|
+
deadline = clock.now() + seconds * 1000;
|
|
699
|
+
if (!Number.isSafeInteger(Math.ceil(deadline)))
|
|
700
|
+
throw new TypeError("Sleep deadline exceeds the supported clock range");
|
|
701
|
+
await store.appendEvent({
|
|
702
|
+
conversationId,
|
|
703
|
+
kind: DURABILITY_PARK_EVENT_KIND,
|
|
704
|
+
payload: { runId, kind: "sleep", name, deadline }
|
|
705
|
+
});
|
|
706
|
+
}
|
|
707
|
+
if (signal?.aborted)
|
|
708
|
+
throw new ParkAbortedError(name);
|
|
709
|
+
await waitForDeadline(clock, deadline, name, signal);
|
|
710
|
+
};
|
|
711
|
+
const sleep = (input, runOptions) => {
|
|
712
|
+
const { seconds } = input;
|
|
713
|
+
if (!Number.isFinite(seconds) || seconds < 0) {
|
|
714
|
+
throw new TypeError(`sleep seconds must be a non-negative finite number, got ${String(seconds)}`);
|
|
715
|
+
}
|
|
716
|
+
const name = input.name ?? `sleep:${seconds}`;
|
|
717
|
+
const key = sleepParkKey(conversationId, runId, name);
|
|
718
|
+
const existing = inFlightParks.get(key);
|
|
719
|
+
if (existing) {
|
|
720
|
+
return existing;
|
|
721
|
+
}
|
|
722
|
+
const pending = executeSleep(name, seconds, runOptions);
|
|
723
|
+
inFlightParks.set(key, pending);
|
|
724
|
+
releaseSettled(inFlightParks, key, pending);
|
|
725
|
+
return pending;
|
|
726
|
+
};
|
|
727
|
+
const executeWait = async (eventName, id, runOptions) => {
|
|
728
|
+
const key = waitParkKey(conversationId, runId, eventName, id);
|
|
729
|
+
const park = `${eventName}#${id}`;
|
|
730
|
+
const signal = options.signal && runOptions?.signal ? AbortSignal.any([options.signal, runOptions.signal]) : runOptions?.signal ?? options.signal;
|
|
731
|
+
for (;; ) {
|
|
732
|
+
if (signal?.aborted)
|
|
733
|
+
throw new ParkAbortedError(park);
|
|
734
|
+
const waiter = createParkWaiter(parkWaiters, key, signal);
|
|
735
|
+
let unsubscribe;
|
|
736
|
+
try {
|
|
737
|
+
unsubscribe = options.subscribe?.(() => notifyWaiters(parkWaiters, key));
|
|
738
|
+
const ledger = await readLedger();
|
|
739
|
+
if (ledger.deliveries.has(key)) {
|
|
740
|
+
return JSON.parse(JSON.stringify(ledger.deliveries.get(key)));
|
|
741
|
+
}
|
|
742
|
+
if (!ledger.parks.has(key)) {
|
|
743
|
+
await store.appendEvent({
|
|
744
|
+
conversationId,
|
|
745
|
+
kind: DURABILITY_PARK_EVENT_KIND,
|
|
746
|
+
payload: { runId, kind: "wait", event: eventName, id }
|
|
747
|
+
});
|
|
748
|
+
}
|
|
749
|
+
const outcome = await waiter.outcome;
|
|
750
|
+
if (outcome === "aborted")
|
|
751
|
+
throw new ParkAbortedError(park);
|
|
752
|
+
} finally {
|
|
753
|
+
waiter.cancel();
|
|
754
|
+
unsubscribe?.();
|
|
755
|
+
}
|
|
756
|
+
}
|
|
757
|
+
};
|
|
758
|
+
const waitFor = (input, runOptions) => {
|
|
759
|
+
const key = waitParkKey(conversationId, runId, input.event, input.id);
|
|
760
|
+
const existing = inFlightParks.get(key);
|
|
761
|
+
if (existing) {
|
|
762
|
+
return detachedResult(existing);
|
|
763
|
+
}
|
|
764
|
+
const pending = executeWait(input.event, input.id, runOptions);
|
|
765
|
+
inFlightParks.set(key, pending);
|
|
766
|
+
releaseSettled(inFlightParks, key, pending);
|
|
767
|
+
return detachedResult(pending);
|
|
768
|
+
};
|
|
769
|
+
const deliver = async (input) => {
|
|
770
|
+
const key = waitParkKey(conversationId, runId, input.event, input.id);
|
|
771
|
+
const ledger = await readLedger();
|
|
772
|
+
if (!ledger.deliveries.has(key)) {
|
|
773
|
+
const encoded = encodeDeliveredPayload(input.event, input.id, input.payload);
|
|
774
|
+
await store.appendEvent({
|
|
775
|
+
conversationId,
|
|
776
|
+
kind: DURABILITY_EVENT_EVENT_KIND,
|
|
777
|
+
payload: { runId, event: input.event, id: input.id, encoded }
|
|
778
|
+
});
|
|
779
|
+
}
|
|
780
|
+
notifyWaiters(parkWaiters, key);
|
|
781
|
+
};
|
|
782
|
+
return {
|
|
783
|
+
step,
|
|
784
|
+
readRecordedStep,
|
|
785
|
+
hasRecordedStep: async (name) => await readRecordedStep(name) !== undefined,
|
|
786
|
+
sleep,
|
|
787
|
+
waitFor,
|
|
788
|
+
deliver
|
|
789
|
+
};
|
|
790
|
+
}
|
|
791
|
+
|
|
317
792
|
// src/agent-runtime/events.ts
|
|
318
793
|
function createAgentRuntimeEventSink(config) {
|
|
319
794
|
const manager = createBoundedSinkManager({
|
|
@@ -629,9 +1104,9 @@ function createAgentToolFenceLifecycle(config) {
|
|
|
629
1104
|
}
|
|
630
1105
|
|
|
631
1106
|
// src/agent-runtime/prompt.ts
|
|
632
|
-
import { z } from "zod";
|
|
633
|
-
var AgentTokenCountSchema =
|
|
634
|
-
value:
|
|
1107
|
+
import { z as z3 } from "zod";
|
|
1108
|
+
var AgentTokenCountSchema = z3.object({
|
|
1109
|
+
value: z3.int().nonnegative().optional(),
|
|
635
1110
|
provenance: AgentProvenanceSchema.extract([
|
|
636
1111
|
"measured",
|
|
637
1112
|
"computed",
|
|
@@ -751,13 +1226,22 @@ function knownValue(value) {
|
|
|
751
1226
|
}
|
|
752
1227
|
function composeAgentPrompt(sections) {
|
|
753
1228
|
return async (options) => {
|
|
1229
|
+
const event = z3.enum(["session.started", "turn.started"]).parse(options.event ?? "turn.started");
|
|
754
1230
|
const rendered = [];
|
|
755
|
-
let
|
|
756
|
-
let
|
|
757
|
-
let
|
|
1231
|
+
let systemTotal = 0;
|
|
1232
|
+
let userTotal = 0;
|
|
1233
|
+
let systemUnavailable = false;
|
|
1234
|
+
let userUnavailable = false;
|
|
1235
|
+
let systemEstimated = false;
|
|
1236
|
+
let userEstimated = false;
|
|
758
1237
|
for (const section of sections) {
|
|
759
|
-
const
|
|
760
|
-
|
|
1238
|
+
const role = section.role ?? "system";
|
|
1239
|
+
const text = await section.render({
|
|
1240
|
+
context: options.context,
|
|
1241
|
+
signal: options.signal,
|
|
1242
|
+
event
|
|
1243
|
+
});
|
|
1244
|
+
rendered.push({ name: section.name, stability: section.stability, role, text });
|
|
761
1245
|
let count;
|
|
762
1246
|
if (section.estimateTokens) {
|
|
763
1247
|
count = AgentTokenCountSchema.parse(await section.estimateTokens(text));
|
|
@@ -766,14 +1250,24 @@ function composeAgentPrompt(sections) {
|
|
|
766
1250
|
} else
|
|
767
1251
|
count = { provenance: "unavailable" };
|
|
768
1252
|
const value = knownValue(count);
|
|
769
|
-
if (
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
1253
|
+
if (role === "user") {
|
|
1254
|
+
if (value === undefined)
|
|
1255
|
+
userUnavailable = true;
|
|
1256
|
+
else
|
|
1257
|
+
userTotal += value;
|
|
1258
|
+
if (count.provenance === "estimated")
|
|
1259
|
+
userEstimated = true;
|
|
1260
|
+
} else {
|
|
1261
|
+
if (value === undefined)
|
|
1262
|
+
systemUnavailable = true;
|
|
1263
|
+
else
|
|
1264
|
+
systemTotal += value;
|
|
1265
|
+
if (count.provenance === "estimated")
|
|
1266
|
+
systemEstimated = true;
|
|
1267
|
+
}
|
|
775
1268
|
}
|
|
776
|
-
const instructionTokens =
|
|
1269
|
+
const instructionTokens = systemUnavailable ? { provenance: "unavailable" } : { value: systemTotal, provenance: systemEstimated ? "estimated" : "computed" };
|
|
1270
|
+
const userInstructionTokens = userUnavailable ? { provenance: "unavailable" } : { value: userTotal, provenance: userEstimated ? "estimated" : "computed" };
|
|
777
1271
|
let availableHistoryTokens;
|
|
778
1272
|
let contextDecision = "unavailable";
|
|
779
1273
|
if (options.budget) {
|
|
@@ -800,13 +1294,25 @@ function composeAgentPrompt(sections) {
|
|
|
800
1294
|
}
|
|
801
1295
|
}
|
|
802
1296
|
}
|
|
803
|
-
const instructionText = rendered.map((section) => section.text).join(`
|
|
1297
|
+
const instructionText = rendered.filter((section) => section.role === "system").map((section) => section.text).join(`
|
|
804
1298
|
|
|
805
1299
|
`);
|
|
1300
|
+
const userInstructions = rendered.filter((section) => section.role === "user" && section.text.trim().length > 0).map((section) => ({ name: section.name, text: section.text }));
|
|
806
1301
|
return {
|
|
807
1302
|
instructions: options.adaptInstructions ? await options.adaptInstructions(instructionText) : instructionText,
|
|
808
1303
|
sections: rendered,
|
|
1304
|
+
userInstructions,
|
|
809
1305
|
instructionTokens,
|
|
1306
|
+
userInstructionTokens,
|
|
1307
|
+
finalizeSeed: (inserted) => {
|
|
1308
|
+
const seedTokens = inserted ? knownValue(userInstructionTokens) : 0;
|
|
1309
|
+
if (availableHistoryTokens === undefined || seedTokens === undefined)
|
|
1310
|
+
return { contextDecision: "unavailable" };
|
|
1311
|
+
const available = availableHistoryTokens - seedTokens;
|
|
1312
|
+
const history = options.historyTokens ? knownValue(options.historyTokens) : undefined;
|
|
1313
|
+
const decision = history === undefined ? "unavailable" : available < 0 ? "oversized" : history <= available ? "fits" : options.oversizePolicy === "compact" ? "requires-compaction" : "oversized";
|
|
1314
|
+
return { availableHistoryTokens: available, contextDecision: decision };
|
|
1315
|
+
},
|
|
810
1316
|
contextDecision,
|
|
811
1317
|
...availableHistoryTokens !== undefined && { availableHistoryTokens }
|
|
812
1318
|
};
|
|
@@ -923,7 +1429,7 @@ async function recordAgentRetryDecision(input) {
|
|
|
923
1429
|
}
|
|
924
1430
|
|
|
925
1431
|
// src/agent-runtime/state-slots.ts
|
|
926
|
-
import { z as
|
|
1432
|
+
import { z as z4 } from "zod";
|
|
927
1433
|
function defineStateSlot(input) {
|
|
928
1434
|
if (input.name.length === 0)
|
|
929
1435
|
throw new TypeError("State slot name must not be empty");
|
|
@@ -938,11 +1444,11 @@ function defineStateSlot(input) {
|
|
|
938
1444
|
...input.description && { description: input.description }
|
|
939
1445
|
};
|
|
940
1446
|
}
|
|
941
|
-
var StateSetPayloadSchema =
|
|
942
|
-
name:
|
|
943
|
-
version:
|
|
944
|
-
value:
|
|
945
|
-
actor:
|
|
1447
|
+
var StateSetPayloadSchema = z4.object({
|
|
1448
|
+
name: z4.string().min(1),
|
|
1449
|
+
version: z4.int().positive(),
|
|
1450
|
+
value: z4.json(),
|
|
1451
|
+
actor: z4.enum(["agent", "human", "system"])
|
|
946
1452
|
}).strict();
|
|
947
1453
|
function slotRegistry(definitions) {
|
|
948
1454
|
const result = new Map;
|
|
@@ -1024,18 +1530,18 @@ function renderAgentStateSlots(values) {
|
|
|
1024
1530
|
var agentGoalStateSlot = defineStateSlot({
|
|
1025
1531
|
name: "goal",
|
|
1026
1532
|
description: "The durable objective and lifecycle of this conversation.",
|
|
1027
|
-
schema:
|
|
1028
|
-
objective:
|
|
1029
|
-
status:
|
|
1533
|
+
schema: z4.object({
|
|
1534
|
+
objective: z4.string().min(1),
|
|
1535
|
+
status: z4.enum(["active", "complete", "blocked"])
|
|
1030
1536
|
}).strict()
|
|
1031
1537
|
});
|
|
1032
1538
|
var agentTodoStateSlot = defineStateSlot({
|
|
1033
1539
|
name: "todo",
|
|
1034
1540
|
description: "The durable ordered work plan for this conversation.",
|
|
1035
|
-
schema:
|
|
1036
|
-
items:
|
|
1037
|
-
step:
|
|
1038
|
-
status:
|
|
1541
|
+
schema: z4.object({
|
|
1542
|
+
items: z4.array(z4.object({
|
|
1543
|
+
step: z4.string().min(1),
|
|
1544
|
+
status: z4.enum(["pending", "in_progress", "completed"])
|
|
1039
1545
|
}).strict())
|
|
1040
1546
|
}).strict()
|
|
1041
1547
|
});
|
|
@@ -1167,6 +1673,47 @@ function repairedSearchCall(toolCall, searchName) {
|
|
|
1167
1673
|
};
|
|
1168
1674
|
}
|
|
1169
1675
|
|
|
1676
|
+
// src/agent-runtime/owned-provider-stream.ts
|
|
1677
|
+
var DEFAULT_CLEANUP_TIMEOUT_MS = 1000;
|
|
1678
|
+
async function settleCleanup(operation, timeoutMs) {
|
|
1679
|
+
let timeout;
|
|
1680
|
+
const deadline = new Promise((_resolve, reject) => {
|
|
1681
|
+
timeout = setTimeout(() => reject(new Error(`Provider stream cleanup exceeded ${timeoutMs} ms`)), timeoutMs);
|
|
1682
|
+
});
|
|
1683
|
+
try {
|
|
1684
|
+
await Promise.race([operation, deadline]);
|
|
1685
|
+
} finally {
|
|
1686
|
+
if (timeout !== undefined)
|
|
1687
|
+
clearTimeout(timeout);
|
|
1688
|
+
}
|
|
1689
|
+
}
|
|
1690
|
+
async function* ownedProviderStream(input) {
|
|
1691
|
+
const iterator = input.stream[Symbol.asyncIterator]();
|
|
1692
|
+
let completed = false;
|
|
1693
|
+
try {
|
|
1694
|
+
for (;; ) {
|
|
1695
|
+
const next = await iterator.next();
|
|
1696
|
+
if (next.done) {
|
|
1697
|
+
completed = true;
|
|
1698
|
+
return;
|
|
1699
|
+
}
|
|
1700
|
+
yield next.value;
|
|
1701
|
+
}
|
|
1702
|
+
} finally {
|
|
1703
|
+
if (!completed) {
|
|
1704
|
+
input.abort();
|
|
1705
|
+
const cleanup = iterator.return?.();
|
|
1706
|
+
if (cleanup) {
|
|
1707
|
+
try {
|
|
1708
|
+
await settleCleanup(cleanup, input.cleanupTimeoutMs ?? DEFAULT_CLEANUP_TIMEOUT_MS);
|
|
1709
|
+
} catch (error) {
|
|
1710
|
+
input.onCleanupFailure(error);
|
|
1711
|
+
}
|
|
1712
|
+
}
|
|
1713
|
+
}
|
|
1714
|
+
}
|
|
1715
|
+
}
|
|
1716
|
+
|
|
1170
1717
|
// src/agent-runtime/provider-origin.ts
|
|
1171
1718
|
import {
|
|
1172
1719
|
InvalidToolApprovalError,
|
|
@@ -1204,7 +1751,7 @@ function createRunMutationQueue() {
|
|
|
1204
1751
|
import { wrapLanguageModel } from "ai";
|
|
1205
1752
|
|
|
1206
1753
|
// src/agent-runtime/runtime-internals.ts
|
|
1207
|
-
import { z as
|
|
1754
|
+
import { z as z5 } from "zod";
|
|
1208
1755
|
function findRun(runs, runId) {
|
|
1209
1756
|
const run = runs.find((candidate) => candidate.id === runId);
|
|
1210
1757
|
if (!run)
|
|
@@ -1212,7 +1759,7 @@ function findRun(runs, runId) {
|
|
|
1212
1759
|
return run;
|
|
1213
1760
|
}
|
|
1214
1761
|
function jsonValue(value) {
|
|
1215
|
-
const parsed =
|
|
1762
|
+
const parsed = z5.json().safeParse(value);
|
|
1216
1763
|
return parsed.success ? parsed.data : { message: "Non-JSON tool output omitted" };
|
|
1217
1764
|
}
|
|
1218
1765
|
function providerEnvelope(value) {
|
|
@@ -1221,6 +1768,12 @@ function providerEnvelope(value) {
|
|
|
1221
1768
|
return;
|
|
1222
1769
|
return { schemaVersion: 1, provider: "ai-sdk", data: parsed.data };
|
|
1223
1770
|
}
|
|
1771
|
+
function providerResponseIdentity(id, provider) {
|
|
1772
|
+
return AgentProviderResponseSchema.parse({
|
|
1773
|
+
id,
|
|
1774
|
+
...typeof provider === "string" && provider.length > 0 ? { provider } : {}
|
|
1775
|
+
});
|
|
1776
|
+
}
|
|
1224
1777
|
function appendText(parts, text) {
|
|
1225
1778
|
const previous = parts.at(-1);
|
|
1226
1779
|
if (previous?.type === "text") {
|
|
@@ -1324,22 +1877,53 @@ function createIdleDeadline(parent, timeoutMs) {
|
|
|
1324
1877
|
const noop = () => {
|
|
1325
1878
|
return;
|
|
1326
1879
|
};
|
|
1327
|
-
return {
|
|
1880
|
+
return {
|
|
1881
|
+
signal: parent,
|
|
1882
|
+
touch: noop,
|
|
1883
|
+
start: noop,
|
|
1884
|
+
stop: noop,
|
|
1885
|
+
suspend: noop,
|
|
1886
|
+
resume: noop,
|
|
1887
|
+
dispose: noop
|
|
1888
|
+
};
|
|
1328
1889
|
}
|
|
1329
1890
|
const controller = new AbortController;
|
|
1330
1891
|
let timer;
|
|
1331
|
-
|
|
1892
|
+
let active = false;
|
|
1893
|
+
let suspended = 0;
|
|
1894
|
+
const clear = () => {
|
|
1332
1895
|
if (timer !== undefined)
|
|
1333
1896
|
clearTimeout(timer);
|
|
1897
|
+
timer = undefined;
|
|
1898
|
+
};
|
|
1899
|
+
const touch = () => {
|
|
1900
|
+
clear();
|
|
1901
|
+
if (!active || suspended > 0 || controller.signal.aborted)
|
|
1902
|
+
return;
|
|
1334
1903
|
timer = setTimeout(() => controller.abort("timeout"), timeoutMs);
|
|
1335
1904
|
};
|
|
1336
|
-
touch();
|
|
1337
1905
|
return {
|
|
1338
1906
|
signal: AbortSignal.any([parent, controller.signal]),
|
|
1339
1907
|
touch,
|
|
1908
|
+
start() {
|
|
1909
|
+
active = true;
|
|
1910
|
+
touch();
|
|
1911
|
+
},
|
|
1912
|
+
stop() {
|
|
1913
|
+
active = false;
|
|
1914
|
+
clear();
|
|
1915
|
+
},
|
|
1916
|
+
suspend() {
|
|
1917
|
+
suspended += 1;
|
|
1918
|
+
clear();
|
|
1919
|
+
},
|
|
1920
|
+
resume() {
|
|
1921
|
+
suspended = Math.max(0, suspended - 1);
|
|
1922
|
+
touch();
|
|
1923
|
+
},
|
|
1340
1924
|
dispose() {
|
|
1341
|
-
|
|
1342
|
-
|
|
1925
|
+
active = false;
|
|
1926
|
+
clear();
|
|
1343
1927
|
}
|
|
1344
1928
|
};
|
|
1345
1929
|
}
|
|
@@ -1476,6 +2060,19 @@ function snapshotForRunPrompt(snapshot, runId) {
|
|
|
1476
2060
|
messages: snapshot.messages.filter((message) => !ownedIds.has(message.id) || eligibleIds.has(message.id))
|
|
1477
2061
|
});
|
|
1478
2062
|
}
|
|
2063
|
+
var USER_INSTRUCTION_SEED_KEY = "prompt.user-instructions";
|
|
2064
|
+
function seededInstructionMessage(input) {
|
|
2065
|
+
return AgentMessageSchema.parse({
|
|
2066
|
+
schemaVersion: 1,
|
|
2067
|
+
id: createHash("sha256").update(`${input.conversationId}\x00${input.seedKey}\x00${input.index}`).digest("hex"),
|
|
2068
|
+
conversationId: input.conversationId,
|
|
2069
|
+
role: "user",
|
|
2070
|
+
status: "committed",
|
|
2071
|
+
parts: [{ type: "text", text: input.text }],
|
|
2072
|
+
createdAt: input.createdAt,
|
|
2073
|
+
updatedAt: input.createdAt
|
|
2074
|
+
});
|
|
2075
|
+
}
|
|
1479
2076
|
function failureThisRuntimeOwns(error) {
|
|
1480
2077
|
if (error instanceof AgentContextOverflowError)
|
|
1481
2078
|
return "context_overflow";
|
|
@@ -1620,6 +2217,7 @@ function createRunExecutor(dependencies) {
|
|
|
1620
2217
|
let step = 0;
|
|
1621
2218
|
let selectedModel;
|
|
1622
2219
|
let internalCause;
|
|
2220
|
+
let providerStreamCleanupFailure;
|
|
1623
2221
|
let reasoningPartIndex;
|
|
1624
2222
|
let firstOutputAt;
|
|
1625
2223
|
let terminalPolicyName;
|
|
@@ -1770,16 +2368,42 @@ function createRunExecutor(dependencies) {
|
|
|
1770
2368
|
run,
|
|
1771
2369
|
snapshot
|
|
1772
2370
|
});
|
|
1773
|
-
|
|
1774
|
-
const [
|
|
2371
|
+
let promptSnapshot = snapshotForRunPrompt(snapshot, run.id);
|
|
2372
|
+
const [composedPrompt, tools] = await Promise.all([
|
|
1775
2373
|
config.prompt({
|
|
1776
2374
|
context: input.context,
|
|
1777
2375
|
signal: executionSignal,
|
|
2376
|
+
event: promptSnapshot.runs[0]?.id === run.id ? "session.started" : "turn.started",
|
|
1778
2377
|
model: selectedModel,
|
|
1779
2378
|
snapshot: promptSnapshot
|
|
1780
2379
|
}),
|
|
1781
2380
|
config.tools(runtimeContext)
|
|
1782
2381
|
]);
|
|
2382
|
+
let prompt = composedPrompt;
|
|
2383
|
+
let userInstructionsInserted = false;
|
|
2384
|
+
if (prompt.userInstructions && prompt.userInstructions.length > 0) {
|
|
2385
|
+
const seededAt = now().toISOString();
|
|
2386
|
+
const seeded = await config.store.seedConversationInput({
|
|
2387
|
+
conversationId: run.conversationId,
|
|
2388
|
+
seedKey: USER_INSTRUCTION_SEED_KEY,
|
|
2389
|
+
inputs: prompt.userInstructions.map((section, index) => seededInstructionMessage({
|
|
2390
|
+
conversationId: run.conversationId,
|
|
2391
|
+
seedKey: USER_INSTRUCTION_SEED_KEY,
|
|
2392
|
+
index,
|
|
2393
|
+
text: section.text,
|
|
2394
|
+
createdAt: seededAt
|
|
2395
|
+
}))
|
|
2396
|
+
});
|
|
2397
|
+
const seededSnapshot = appliedSnapshot(seeded, "user instruction seed");
|
|
2398
|
+
const previousIds = new Set(snapshot.messages.map((message) => message.id));
|
|
2399
|
+
userInstructionsInserted = seededSnapshot.messages.some((message) => !previousIds.has(message.id) && message.role === "user" && message.runId === undefined);
|
|
2400
|
+
snapshot = seededSnapshot;
|
|
2401
|
+
observedVersion = snapshot.version;
|
|
2402
|
+
run = findRun(snapshot.runs, run.id);
|
|
2403
|
+
promptSnapshot = snapshotForRunPrompt(snapshot, run.id);
|
|
2404
|
+
}
|
|
2405
|
+
if (prompt.finalizeSeed)
|
|
2406
|
+
prompt = { ...prompt, ...prompt.finalizeSeed(userInstructionsInserted) };
|
|
1783
2407
|
if (prompt.contextDecision === "oversized") {
|
|
1784
2408
|
throw new AgentContextOverflowError;
|
|
1785
2409
|
}
|
|
@@ -1839,7 +2463,8 @@ function createRunExecutor(dependencies) {
|
|
|
1839
2463
|
});
|
|
1840
2464
|
return [...detailed.messages];
|
|
1841
2465
|
};
|
|
1842
|
-
const
|
|
2466
|
+
const projectedHistory = await projectHistory(promptSnapshot);
|
|
2467
|
+
const history = [...projectedHistory];
|
|
1843
2468
|
const withCarriedSystem = (instructions) => {
|
|
1844
2469
|
if (carriedSystem.length === 0)
|
|
1845
2470
|
return instructions;
|
|
@@ -1935,21 +2560,67 @@ function createRunExecutor(dependencies) {
|
|
|
1935
2560
|
}
|
|
1936
2561
|
});
|
|
1937
2562
|
};
|
|
2563
|
+
const recordProviderResponse = async (response) => {
|
|
2564
|
+
const identity = providerResponseIdentity(response.id, selectedModel?.resolveResponseProvider?.({
|
|
2565
|
+
providerMetadata: response.providerMetadata
|
|
2566
|
+
}));
|
|
2567
|
+
await config.store.appendEvent({
|
|
2568
|
+
conversationId: run.conversationId,
|
|
2569
|
+
kind: "provider/response",
|
|
2570
|
+
payload: {
|
|
2571
|
+
runId: run.id,
|
|
2572
|
+
attempt: response.attempt,
|
|
2573
|
+
stepNumber: response.stepNumber,
|
|
2574
|
+
response: identity
|
|
2575
|
+
}
|
|
2576
|
+
});
|
|
2577
|
+
return identity;
|
|
2578
|
+
};
|
|
1938
2579
|
for (;; ) {
|
|
1939
2580
|
const attemptPartStart = parts.length;
|
|
1940
2581
|
let retrying = false;
|
|
1941
2582
|
let draining = false;
|
|
2583
|
+
const providerAttempt = retryAttempt;
|
|
2584
|
+
const attemptAbort = new AbortController;
|
|
2585
|
+
const attemptSignal = AbortSignal.any([executionSignal, attemptAbort.signal]);
|
|
1942
2586
|
const result = streamAgentTextBoundary({
|
|
1943
2587
|
model: fallbackModel,
|
|
1944
2588
|
tools,
|
|
2589
|
+
...config.durability && {
|
|
2590
|
+
toolsContext: Object.fromEntries(Object.keys(tools).map((toolName) => [
|
|
2591
|
+
toolName,
|
|
2592
|
+
createToolDurabilityContext((toolCallId, signal) => {
|
|
2593
|
+
const port = config.durability;
|
|
2594
|
+
if (typeof port === "function")
|
|
2595
|
+
return port({
|
|
2596
|
+
store: config.store,
|
|
2597
|
+
conversationId: run.conversationId,
|
|
2598
|
+
runId: run.id,
|
|
2599
|
+
toolName,
|
|
2600
|
+
toolCallId,
|
|
2601
|
+
signal
|
|
2602
|
+
});
|
|
2603
|
+
return createLocalStepDurability({
|
|
2604
|
+
store: config.store,
|
|
2605
|
+
conversationId: run.conversationId,
|
|
2606
|
+
runId: JSON.stringify([run.id, toolName, toolCallId]),
|
|
2607
|
+
signal
|
|
2608
|
+
});
|
|
2609
|
+
})
|
|
2610
|
+
]))
|
|
2611
|
+
},
|
|
1945
2612
|
instructions: withCarriedSystem(prompt.instructions),
|
|
1946
2613
|
messages: history,
|
|
1947
|
-
abortSignal:
|
|
2614
|
+
abortSignal: attemptSignal,
|
|
1948
2615
|
maxRetries: 0,
|
|
1949
2616
|
stopWhen: stopConditions,
|
|
1950
2617
|
onLanguageModelCallStart: (event) => {
|
|
2618
|
+
idleDeadline.start();
|
|
1951
2619
|
operationLifecycle.noteProviderCall(event.callId);
|
|
1952
2620
|
},
|
|
2621
|
+
onLanguageModelCallEnd: () => idleDeadline.stop(),
|
|
2622
|
+
onToolExecutionStart: () => idleDeadline.suspend(),
|
|
2623
|
+
onToolExecutionEnd: () => idleDeadline.resume(),
|
|
1953
2624
|
repairToolCall: deferredToolRepair(config.loop?.prepareStep),
|
|
1954
2625
|
...config.loop?.toolApproval && {
|
|
1955
2626
|
toolApproval: config.loop.toolApproval,
|
|
@@ -1984,17 +2655,29 @@ function createRunExecutor(dependencies) {
|
|
|
1984
2655
|
instructionsOverride = override.system;
|
|
1985
2656
|
await recordProviderRequest({
|
|
1986
2657
|
stepNumber: options.stepNumber,
|
|
1987
|
-
attempt:
|
|
2658
|
+
attempt: providerAttempt,
|
|
1988
2659
|
instructions: instructionsOverride ?? withCarriedSystem(prompt.instructions),
|
|
1989
2660
|
messages: providerMessages
|
|
1990
2661
|
});
|
|
1991
2662
|
return { ...preparedStep, model };
|
|
1992
2663
|
}
|
|
1993
2664
|
});
|
|
1994
|
-
for await (const part of
|
|
2665
|
+
for await (const part of ownedProviderStream({
|
|
2666
|
+
stream: result.stream,
|
|
2667
|
+
abort: () => attemptAbort.abort(new Error("Agent runtime released provider stream")),
|
|
2668
|
+
onCleanupFailure: (error) => {
|
|
2669
|
+
providerStreamCleanupFailure = error;
|
|
2670
|
+
}
|
|
2671
|
+
})) {
|
|
1995
2672
|
idleDeadline.touch();
|
|
1996
2673
|
if (draining) {
|
|
1997
2674
|
if (part.type === "finish-step") {
|
|
2675
|
+
await recordProviderResponse({
|
|
2676
|
+
id: part.response.id,
|
|
2677
|
+
providerMetadata: part.providerMetadata,
|
|
2678
|
+
stepNumber: step,
|
|
2679
|
+
attempt: providerAttempt
|
|
2680
|
+
});
|
|
1998
2681
|
const failedStepUsage = selectedModel.normalizeUsage?.({
|
|
1999
2682
|
usage: part.usage,
|
|
2000
2683
|
providerMetadata: part.providerMetadata
|
|
@@ -2267,6 +2950,12 @@ function createRunExecutor(dependencies) {
|
|
|
2267
2950
|
terminalReason = failureThisRuntimeOwns(part.error) ?? "provider_failure";
|
|
2268
2951
|
internalCause = part.error;
|
|
2269
2952
|
} else if (part.type === "finish-step") {
|
|
2953
|
+
const response = await recordProviderResponse({
|
|
2954
|
+
id: part.response.id,
|
|
2955
|
+
providerMetadata: part.providerMetadata,
|
|
2956
|
+
stepNumber: step,
|
|
2957
|
+
attempt: providerAttempt
|
|
2958
|
+
});
|
|
2270
2959
|
await operationLifecycle.finish(part.finishReason === "error" ? "failed" : "completed");
|
|
2271
2960
|
const stepTrace = trace ? config.observe?.rootTrace(trace) : undefined;
|
|
2272
2961
|
const stepUsage = selectedModel.normalizeUsage?.({
|
|
@@ -2289,6 +2978,7 @@ function createRunExecutor(dependencies) {
|
|
|
2289
2978
|
modelId: selectedModel.descriptor.modelId,
|
|
2290
2979
|
step,
|
|
2291
2980
|
usage: stepUsage,
|
|
2981
|
+
response,
|
|
2292
2982
|
emittedAt: now().toISOString()
|
|
2293
2983
|
});
|
|
2294
2984
|
step += 1;
|
|
@@ -2357,7 +3047,7 @@ function createRunExecutor(dependencies) {
|
|
|
2357
3047
|
}
|
|
2358
3048
|
} catch (error) {
|
|
2359
3049
|
operationLifecycle.failStepCheckpoints(error);
|
|
2360
|
-
internalCause = error;
|
|
3050
|
+
internalCause = providerStreamCleanupFailure === undefined ? error : new AggregateError([error, providerStreamCleanupFailure], `${error instanceof Error ? error.message : String(error)} (provider stream cleanup also failed: ${providerStreamCleanupFailure instanceof Error ? providerStreamCleanupFailure.message : String(providerStreamCleanupFailure)})`);
|
|
2361
3051
|
const latest = await config.store.loadRun({
|
|
2362
3052
|
conversationId: run.conversationId,
|
|
2363
3053
|
runId: run.id
|
|
@@ -2935,6 +3625,35 @@ function createAgentRuntime(config) {
|
|
|
2935
3625
|
}
|
|
2936
3626
|
return requested;
|
|
2937
3627
|
},
|
|
3628
|
+
async abandon(input) {
|
|
3629
|
+
if (input.staleOwner !== true) {
|
|
3630
|
+
throw new TypeError("Abandoning a run requires explicit staleOwner evidence");
|
|
3631
|
+
}
|
|
3632
|
+
const releaseAdmission = beginAdmission();
|
|
3633
|
+
try {
|
|
3634
|
+
const abandoned = await config.store.recoverRun({
|
|
3635
|
+
conversationId: input.conversationId,
|
|
3636
|
+
runId: input.runId,
|
|
3637
|
+
expectedRevision: input.expectedRevision,
|
|
3638
|
+
action: "abandon"
|
|
3639
|
+
});
|
|
3640
|
+
if (abandoned.outcome === "applied") {
|
|
3641
|
+
const abandonedRun = findRun(abandoned.snapshot.runs, input.runId);
|
|
3642
|
+
await publish({
|
|
3643
|
+
type: "run-state",
|
|
3644
|
+
eventId: agentDurableEventId("run-state", abandonedRun.id, abandoned.snapshot.version),
|
|
3645
|
+
conversationId: abandonedRun.conversationId,
|
|
3646
|
+
runId: abandonedRun.id,
|
|
3647
|
+
snapshotVersion: abandoned.snapshot.version,
|
|
3648
|
+
state: abandonedRun.state,
|
|
3649
|
+
emittedAt: now().toISOString()
|
|
3650
|
+
});
|
|
3651
|
+
}
|
|
3652
|
+
return abandoned;
|
|
3653
|
+
} finally {
|
|
3654
|
+
releaseAdmission();
|
|
3655
|
+
}
|
|
3656
|
+
},
|
|
2938
3657
|
async recover(options) {
|
|
2939
3658
|
if (admissionClosed)
|
|
2940
3659
|
throw closedError();
|
|
@@ -3094,4 +3813,4 @@ function createAgentRuntime(config) {
|
|
|
3094
3813
|
};
|
|
3095
3814
|
}
|
|
3096
3815
|
|
|
3097
|
-
export { AgentRuntimeConflictError, normalizeSdkUsage, AgentContextOverflowError, createAgentSessionCoordinator, registerDeferredToolRepair, registerDeferredToolCatalog, deferredToolCatalog, repairedSearchCall, createAgentRuntimeEventSink, projectAgentHistoryDetailed, projectAgentHistory, createAgentToolFenceLifecycle, AgentTokenCountSchema, selectAgentHistory, composeAgentPrompt, AgentProviderStreamCutError, classifyProviderFailure, isToolResultFailure, recordAgentRetryDecision, defineStateSlot, createAgentStateSlotStore, renderAgentStateSlots, agentGoalStateSlot, agentTodoStateSlot, createAgentRuntime };
|
|
3816
|
+
export { AgentRuntimeConflictError, normalizeSdkUsage, AgentContextOverflowError, createAgentSessionCoordinator, registerDeferredToolRepair, registerDeferredToolCatalog, deferredToolCatalog, repairedSearchCall, DURABILITY_STEP_EVENT_KIND, StepResultDecodeError, StepResultNotSerializableError, StepAbortedError, ParkRecordDecodeError, ParkAbortedError, createLocalStepDurability, createAgentRuntimeEventSink, projectAgentHistoryDetailed, projectAgentHistory, createAgentToolFenceLifecycle, AgentTokenCountSchema, selectAgentHistory, composeAgentPrompt, AgentProviderStreamCutError, classifyProviderFailure, isToolResultFailure, recordAgentRetryDecision, defineStateSlot, createAgentStateSlotStore, renderAgentStateSlots, agentGoalStateSlot, agentTodoStateSlot, createAgentRuntime };
|