effect-agent 0.1.0-beta.144 → 0.1.0-beta.149

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.
Files changed (83) hide show
  1. package/dist/{Admin-CQMppCcy.d.mts → Admin-B8ISZyYf.d.mts} +37 -22
  2. package/dist/Agent-1DMSO_Fl.mjs.map +1 -1
  3. package/dist/{Agent-BWhD4Dvu.d.mts → Agent-Cjd_ZveM.d.mts} +7 -3
  4. package/dist/{AgentRuntime-xeCUXutN.mjs → AgentRuntime-D8U9gl9Q.mjs} +23 -18
  5. package/dist/AgentRuntime-D8U9gl9Q.mjs.map +1 -0
  6. package/dist/{AgentRuntime-B4kIzmSF.d.mts → AgentRuntime-sXpKcyxu.d.mts} +5 -5
  7. package/dist/{DurableAgentRuntime-D8GI66mP.mjs → DurableAgentRuntime-DLa4IwFi.mjs} +87 -49
  8. package/dist/DurableAgentRuntime-DLa4IwFi.mjs.map +1 -0
  9. package/dist/{EventSource-w9PonN9X.d.mts → EventSource-CkN05NT3.d.mts} +2 -2
  10. package/dist/{Messaging-Dnmk31yq.d.mts → Messaging-ccQURKCf.d.mts} +3 -3
  11. package/dist/{MessagingHost-CajpPDPG.d.mts → MessagingHost-D04wE-7W.d.mts} +2 -2
  12. package/dist/{Output-DhtWbBcw.d.mts → Output-CFD1CPfU.d.mts} +2 -2
  13. package/dist/{PreparedInputAdmission-BfcLy_k4.d.mts → PreparedInputAdmission-fctZOTnn.d.mts} +3 -3
  14. package/dist/{RunOptions-IlEXLG5F.d.mts → RunOptions-Bv9NpkPZ.d.mts} +10 -2
  15. package/dist/{Subagent-Cl8D1mFM.d.mts → Subagent-VHrANXFy.d.mts} +5 -5
  16. package/dist/{Subagent-8RzJkqJ9.mjs → Subagent-hG9lJ7tJ.mjs} +2 -2
  17. package/dist/{Subagent-8RzJkqJ9.mjs.map → Subagent-hG9lJ7tJ.mjs.map} +1 -1
  18. package/dist/{SubagentHost-B6f4PBC2.d.mts → SubagentHost-C-4A7tA2.d.mts} +2 -2
  19. package/dist/{Subscription-ClkC4_T0.d.mts → Subscription-B16A-48F.d.mts} +2 -2
  20. package/dist/{SubscriptionInput-CMjEKL1z.d.mts → SubscriptionInput-DIU7CiXE.d.mts} +2 -2
  21. package/dist/capabilities/Commands.d.mts +1 -1
  22. package/dist/capabilities/Messaging.d.mts +1 -1
  23. package/dist/capabilities/RunHooks.d.mts +1 -1
  24. package/dist/capabilities/Subagent.d.mts +1 -1
  25. package/dist/capabilities/Subagent.mjs +1 -1
  26. package/dist/core/Agent.d.mts +1 -1
  27. package/dist/durable/Admin.d.mts +1 -1
  28. package/dist/durable/AgentRegistration.d.mts +1 -1
  29. package/dist/durable/Certification.d.mts +1 -1
  30. package/dist/durable/CommittedActivity.d.mts +1 -1
  31. package/dist/durable/DurableAgentRuntime.d.mts +1 -1
  32. package/dist/durable/DurableAgentRuntime.mjs +1 -1
  33. package/dist/durable/EventSource.d.mts +1 -1
  34. package/dist/durable/GitHubWorkflowSource.d.mts +3 -3
  35. package/dist/durable/LifecyclePublication.d.mts +2 -2
  36. package/dist/durable/LifecyclePublication.mjs +32 -12
  37. package/dist/durable/LifecyclePublication.mjs.map +1 -1
  38. package/dist/durable/MessageDelivery.d.mts +3 -3
  39. package/dist/durable/MessageDeliveryStoreConformance.d.mts +1 -1
  40. package/dist/durable/PersistentHistory.d.mts +1 -1
  41. package/dist/durable/PreparedInputAdmission.d.mts +1 -1
  42. package/dist/durable/Recovery.d.mts +1 -1
  43. package/dist/durable/RunJournal.d.mts +1 -1
  44. package/dist/durable/Scheduling.d.mts +1 -1
  45. package/dist/durable/SubmissionLedger.d.mts +1 -1
  46. package/dist/durable/SubmissionLedgerConformance.d.mts +1 -1
  47. package/dist/durable/SubmissionStatus.d.mts +1 -1
  48. package/dist/durable/Subscription.d.mts +1 -1
  49. package/dist/durable/SubscriptionInput.d.mts +1 -1
  50. package/dist/durable/SubscriptionStoreConformance.d.mts +1 -1
  51. package/dist/durable/SubscriptionTools.d.mts +2 -2
  52. package/dist/durable/SubscriptionTransition.d.mts +1 -1
  53. package/dist/durable/Subscriptions.d.mts +5 -5
  54. package/dist/durable/ThreadContextHistory.d.mts +1 -1
  55. package/dist/durable/ThreadInvariants.d.mts +1 -1
  56. package/dist/durable/ThreadProjectionMaintenance.d.mts +1 -1
  57. package/dist/durable/ThreadStore.d.mts +1 -1
  58. package/dist/durable/ThreadStoreConformance.d.mts +1 -1
  59. package/dist/durable/WorkerHost.d.mts +25 -5
  60. package/dist/durable/WorkerHost.mjs.map +1 -1
  61. package/dist/engine/AgentRuntime.d.mts +1 -1
  62. package/dist/engine/AgentRuntime.mjs +1 -1
  63. package/dist/engine/MessagingHost.d.mts +1 -1
  64. package/dist/engine/Output.d.mts +1 -1
  65. package/dist/engine/Output.mjs +1 -1
  66. package/dist/engine/RunOptions.d.mts +1 -1
  67. package/dist/engine/RunOptions.mjs.map +1 -1
  68. package/dist/engine/SubagentHost.d.mts +1 -1
  69. package/dist/index.d.mts +13 -13
  70. package/dist/index.mjs +3 -3
  71. package/dist/{output-contract-CANJJGA5.mjs → output-contract-DS-S8mTv.mjs} +46 -10
  72. package/dist/{output-contract-CANJJGA5.mjs.map → output-contract-DS-S8mTv.mjs.map} +1 -1
  73. package/package.json +1 -1
  74. package/src/core/Agent.ts +6 -2
  75. package/src/durable/DurableAgentRuntime.ts +86 -78
  76. package/src/durable/LifecyclePublication.ts +79 -25
  77. package/src/durable/WorkerHost.ts +23 -1
  78. package/src/durable/internal/worker-host.ts +169 -17
  79. package/src/engine/RunOptions.ts +8 -0
  80. package/src/engine/internal/agent-runtime.ts +80 -18
  81. package/src/engine/internal/output-contract.ts +67 -8
  82. package/dist/AgentRuntime-xeCUXutN.mjs.map +0 -1
  83. package/dist/DurableAgentRuntime-D8GI66mP.mjs.map +0 -1
@@ -8,14 +8,14 @@ import { n as CurrentToolCatalog } from "./ToolExposure-UCN12eCd.mjs";
8
8
  import { s as ToolBroker } from "./ToolBroker-DWs4tZra.mjs";
9
9
  import { a as AgentInputError, c as AgentPolicyError, d as AgentToolAuthorizationDenied, f as ContextBudgetError, m as ModelProtocolError, n as AgentApprovalPending, p as ContextOverflowError, s as AgentOutputError, t as AgentApprovalDenied, u as AgentToolAuthorizationCheckError } from "./AgentError-Bn1ytXRD.mjs";
10
10
  import { t as AgentPolicy } from "./AgentPolicy-BqDoSXO6.mjs";
11
- import { A as ToolUnion, C as OutputSchema, D as RunDispositionFailure, E as RunDispositionDeclaration, N as UpdatesSchema, O as RunDispositionSchema, S as Output, _ as InstructionSource, a as CompletionFromToolDeclaration, c as Definition, d as EncodedInput, f as Failure, m as InputPromptSource, n as Any, r as AnyDefinition, s as CompletionToolDeclaration, t as Agent_d_exports, w as Requirements } from "./Agent-BWhD4Dvu.mjs";
11
+ import { A as ToolUnion, C as OutputSchema, D as RunDispositionFailure, E as RunDispositionDeclaration, N as UpdatesSchema, O as RunDispositionSchema, S as Output, _ as InstructionSource, a as CompletionFromToolDeclaration, c as Definition, d as EncodedInput, f as Failure, m as InputPromptSource, n as Any, r as AnyDefinition, s as CompletionToolDeclaration, t as Agent_d_exports, w as Requirements } from "./Agent-Cjd_ZveM.mjs";
12
12
  import { a as WorkerBudgetScope } from "./Worker-fwWkBg12.mjs";
13
13
  import { a as ContextWindow } from "./ContextWindow-DRQ5Mbm2.mjs";
14
14
  import { n as CompactionError } from "./ContextCompactor-WwSIG_Z2.mjs";
15
15
  import { t as DurableStep } from "./DurableStep-Cry_iol4.mjs";
16
- import { B as RunSubagentChildIdentity, H as RunSubagentEstablishRequest, M as RunOptions, S as RunContextPreparationError, W as RunSubagentJoinRequest, i as ChildEstablishStatus, l as ModelUsageAccounting, t as AgentUpdateAcceptance, x as RunContextPreparation } from "./RunOptions-IlEXLG5F.mjs";
17
- import { t as MessagingHost } from "./MessagingHost-CajpPDPG.mjs";
18
- import { o as SubagentHost } from "./SubagentHost-B6f4PBC2.mjs";
16
+ import { B as RunSubagentChildIdentity, H as RunSubagentEstablishRequest, M as RunOptions, S as RunContextPreparationError, W as RunSubagentJoinRequest, i as ChildEstablishStatus, l as ModelUsageAccounting, t as AgentUpdateAcceptance, x as RunContextPreparation } from "./RunOptions-Bv9NpkPZ.mjs";
17
+ import { t as MessagingHost } from "./MessagingHost-D04wE-7W.mjs";
18
+ import { o as SubagentHost } from "./SubagentHost-C-4A7tA2.mjs";
19
19
  import { t as RunEventSink } from "./RunEventSink-D5aVhISG.mjs";
20
20
  import { AiError, LanguageModel, Model, Prompt, Tool, Toolkit } from "effect/unstable/ai";
21
21
  import { Cause, Context, Effect, Layer, Option, Schema, Scope, Stream, Tracer } from "effect";
@@ -343,4 +343,4 @@ declare namespace AgentRuntime_d_exports {
343
343
  }
344
344
  //#endregion
345
345
  export { start as A, decodeFinalOutput as C, renderInputPrompt as D, projectCompletionOutput as E, withTerminalDefectEvent as F, stream as M, streamUnknown as N, run as O, streamWithUsageAccountingUnknown as P, ToolCallWaiting as S, projectCompletionFromToolOutput as T, SubagentDurability as _, AgentResultSchema as a, SubagentDurabilityError as b, AgentSpawner as c, DetachedRun as d, EngineProvidedToolServices as f, SpawnedChildRun as g, SpawnRunOptions as h, AgentResult as i, startUnknown as j, runUnknown as k, AgentSpawnerParent as l, SpawnDelegation as m, AgentChildPending as n, AgentRuntimeFailure as o, RuntimeBinding as p, AgentCompletionProjectionRequirements as r, AgentRuntimeRequirements as s, AgentRuntime_d_exports as t, AgentSpawnerService as u, SubagentDurabilityDurable as v, encodeRunDisposition as w, SubagentDurabilityService as x, SubagentDurabilityEphemeral as y };
346
- //# sourceMappingURL=AgentRuntime-B4kIzmSF.d.mts.map
346
+ //# sourceMappingURL=AgentRuntime-sXpKcyxu.d.mts.map
@@ -15,7 +15,7 @@ import { a as PeerMessageCapacity, d as MessageAdmission, f as MessagingError, i
15
15
  import { SubagentHost } from "./engine/SubagentHost.mjs";
16
16
  import { ThreadHistory } from "./engine/ThreadHistory.mjs";
17
17
  import { n as RunToolVisibility } from "./ToolExposure-9uF_Yo0T.mjs";
18
- import { f as renderInputPrompt, n as AgentChildPending, y as streamWithUsageAccountingUnknown } from "./AgentRuntime-xeCUXutN.mjs";
18
+ import { f as renderInputPrompt, n as AgentChildPending, y as streamWithUsageAccountingUnknown } from "./AgentRuntime-D8U9gl9Q.mjs";
19
19
  import { ContextRolloverTool } from "./engine/ContextWindow.mjs";
20
20
  import { getToolExecutionClass } from "./engine/DurableStep.mjs";
21
21
  import { CompactionError, ContextCompactor } from "./engine/ContextCompactor.mjs";
@@ -634,6 +634,8 @@ const withinPolicy = (origin, source, target) => {
634
634
  };
635
635
  /** Admission and cancellation enter the owning runtime, never the raw ledger. */
636
636
  var WorkerInputControl = class extends Context.Service()("@effect-agent/thread/internal/WorkerInputControl") {};
637
+ const CurrentStartPreparation = Context.Reference("@effect-agent/thread/internal/CurrentStartPreparation", { defaultValue: () => void 0 });
638
+ const CurrentStartDelivery = Context.Reference("@effect-agent/thread/internal/CurrentStartDelivery", { defaultValue: () => void 0 });
637
639
  /** No in-memory ownership: every mutation is reserved in source canonical history with CAS. */
638
640
  const makeWorkerRuntime = Effect.fn("WorkerHost.make")(function* (options) {
639
641
  const control = yield* WorkerInputControl;
@@ -654,11 +656,17 @@ const makeWorkerRuntime = Effect.fn("WorkerHost.make")(function* (options) {
654
656
  status: Option.getOrUndefined(admission)?.submissionStatus ?? control.status
655
657
  };
656
658
  const withCrypto = (effect) => Effect.provideService(effect, Crypto.Crypto, deps.crypto);
657
- const authorizeBudget = Effect.fn("WorkerHost.authorizeBudget")(function* (origin, principal) {
659
+ const currentStart = Effect.fnUntraced(function* (admission, sourceThreadId, sourceSubmissionId, principal, targetAgentId, continuationOf) {
660
+ if (admission === void 0 || admission.sourceThreadId !== sourceThreadId || admission.sourceSubmissionId !== sourceSubmissionId || admission.principal !== principal && admission.requestedPrincipal !== principal || admission.targetAgentId !== targetAgentId || !Schema.toEquivalence(Schema.UndefinedOr(WorkerContinuation))(admission.continuationOf, continuationOf)) return void 0;
661
+ const tail = yield* deps.store.inspectTail(ThreadTailRequest.make({ threadId: sourceThreadId })).pipe(Effect.mapError(storageFailure("start")));
662
+ return tail.tailSequence === admission.tailSequence && tail.tailDigest === admission.tailDigest ? admission : void 0;
663
+ });
664
+ const authorizeBudget = Effect.fn("WorkerHost.authorizeBudget")(function* (origin, principal, admission) {
658
665
  yield* verifyContinuation(origin);
659
666
  if (origin.budgetScope !== "worker-run") return;
660
667
  if (origin.depth !== 1) return yield* failure("start", "denied");
661
668
  yield* deps.budgetAuthorizer.authorize({
669
+ ...admission === void 0 ? {} : { admission },
662
670
  source: origin.source,
663
671
  principal,
664
672
  worker: origin.worker,
@@ -946,7 +954,7 @@ const makeWorkerRuntime = Effect.fn("WorkerHost.make")(function* (options) {
946
954
  }
947
955
  return yield* failure("start", "storage");
948
956
  });
949
- const reservation = Effect.fn("WorkerHost.reserveInput")(function* (admission, inputDigest, input, principal, retainedFrameworkInput) {
957
+ const reservation = Effect.fn("WorkerHost.reserveInput")(function* (admission, inputDigest, input, principal, retainedFrameworkInput, authorization) {
950
958
  const origin = admission.origin;
951
959
  yield* verifyContinuation(origin);
952
960
  const id = workerInputRecordId(admission.messageId);
@@ -980,6 +988,7 @@ const makeWorkerRuntime = Effect.fn("WorkerHost.make")(function* (options) {
980
988
  const selected = yield* resolveTargetPolicy(admission.messageId === origin.firstMessageId ? {
981
989
  ...targetRequest,
982
990
  _tag: "InitialInput",
991
+ ...authorization === void 0 || authorization.tailSequence !== current.tailSequence || authorization.tailDigest !== current.tailDigest ? {} : { admission: authorization },
983
992
  ...origin.continuationOf === void 0 ? {} : { continuationOf: origin.continuationOf },
984
993
  input,
985
994
  inputDigest,
@@ -1061,7 +1070,10 @@ const makeWorkerRuntime = Effect.fn("WorkerHost.make")(function* (options) {
1061
1070
  yield* validateCompletion(options.messageAdmission, options, agentId, inputDigest);
1062
1071
  }
1063
1072
  yield* verifyContinuation(admission.origin);
1073
+ const delivery = yield* CurrentStartDelivery;
1074
+ const authorization = delivery !== void 0 && sameAdmission(delivery.admission, admission) && delivery.inputDigest === inputDigest ? yield* currentStart(delivery.authorization, admission.origin.source.threadId, admission.sourceSubmissionId, options.principal, agentId, admission.origin.continuationOf) : void 0;
1064
1075
  yield* deps.authorizer.authorize({
1076
+ ...authorization === void 0 ? {} : { admission: authorization },
1065
1077
  sourceThreadId: admission.origin.source.threadId,
1066
1078
  ...admission.sourceSubmissionId === void 0 ? {} : { sourceSubmissionId: admission.sourceSubmissionId },
1067
1079
  principal: options.principal,
@@ -1070,11 +1082,11 @@ const makeWorkerRuntime = Effect.fn("WorkerHost.make")(function* (options) {
1070
1082
  worker: admission.origin.worker,
1071
1083
  ...admission.origin.continuationOf === void 0 ? {} : { continuationOf: admission.origin.continuationOf }
1072
1084
  });
1073
- yield* authorizeBudget(admission.origin, options.principal);
1085
+ yield* authorizeBudget(admission.origin, options.principal, authorization);
1074
1086
  if (admission.origin.worker.threadId !== options.threadId || admission.origin.worker.targetAgentId !== agentId || !definitionDigestsEqual(admission.origin.targetDigests, options.definitions) || options.idempotencyKey !== admission.messageId || admission.deliveryPrincipal !== void 0 && admission.deliveryPrincipal !== options.principal) return yield* failure("start", "worker-mismatch");
1075
1087
  const retainedFrameworkInput = Schema.is(FrameworkMessage)(options.messageAdmission);
1076
1088
  if (retainedFrameworkInput && admission.reportKind !== "update") yield* validateCompletion(options.messageAdmission, options, agentId, inputDigest);
1077
- yield* reservation(admission, inputDigest, input, options.principal, retainedFrameworkInput);
1089
+ yield* reservation(admission, inputDigest, input, options.principal, retainedFrameworkInput, authorization);
1078
1090
  return admission;
1079
1091
  });
1080
1092
  const prepareUpdate = Effect.fn("WorkerHost.prepareUpdate")(function* (update, submission, messageId) {
@@ -1338,7 +1350,9 @@ const makeWorkerRuntime = Effect.fn("WorkerHost.make")(function* (options) {
1338
1350
  return yield* failure("inspect", "storage");
1339
1351
  });
1340
1352
  const facet = (context, principal, sourceSubmissionId) => {
1341
- const authorize = (operation, access, worker, continuationOf) => deps.authorizer.authorize({
1353
+ const requestedPrincipal = principal;
1354
+ const authorize = (operation, access, worker, continuationOf, admission) => deps.authorizer.authorize({
1355
+ ...admission === void 0 ? {} : { admission },
1342
1356
  sourceThreadId: context.source.threadId,
1343
1357
  ...sourceSubmissionId === void 0 ? {} : { sourceSubmissionId },
1344
1358
  principal,
@@ -1349,17 +1363,19 @@ const makeWorkerRuntime = Effect.fn("WorkerHost.make")(function* (options) {
1349
1363
  });
1350
1364
  const binding = (target, operation) => resolveDefinitionBinding(deps.bindings, target).pipe(Effect.mapError((cause) => failure(operation, "declaration-unavailable", cause)));
1351
1365
  const deliveryStatus = (row, operation) => messageStatus(row).pipe(Effect.mapError((cause) => failure(operation, "corrupt", cause)));
1352
- const preparedTarget = Effect.fn("WorkerHost.preparedTarget")(function* (target, encodedInput, continuationOf) {
1366
+ const preparedTarget = Effect.fn("WorkerHost.preparedTarget")(function* (target, encodedInput, continuationOf, authorization) {
1353
1367
  const resolved = yield* binding(target, "start");
1354
1368
  yield* Schema.decodeUnknownEffect(Schema.toEncoded(target.input))(encodedInput).pipe(Effect.mapError((cause) => failure("start", "corrupt", cause)));
1355
1369
  const input = yield* decode(PersistedJson, encodedInput, "start");
1356
1370
  const inputDigest = yield* withCrypto(digestJson(input)).pipe(Effect.mapError(storageFailure("start")));
1357
1371
  const source = yield* sourceAuthority(context.source.threadId, sourceSubmissionId);
1372
+ const admission = yield* currentStart(authorization, context.source.threadId, sourceSubmissionId, principal, target.id, continuationOf);
1358
1373
  return {
1359
1374
  resolved,
1360
1375
  source,
1361
1376
  policy: yield* resolveTargetPolicy({
1362
1377
  _tag: "InitialInput",
1378
+ ...admission === void 0 ? {} : { admission },
1363
1379
  ...continuationOf === void 0 ? {} : { continuationOf },
1364
1380
  definition: resolved.definition,
1365
1381
  definitions: resolved.digests,
@@ -1420,7 +1436,7 @@ const makeWorkerRuntime = Effect.fn("WorkerHost.make")(function* (options) {
1420
1436
  budgetExhausted: result.finishReason === "budget-exhausted"
1421
1437
  };
1422
1438
  });
1423
- const send = Effect.fn("WorkerHost.send")(function* (origin, messageId, encodedInput, encodedParameters, principal, operation) {
1439
+ const send = Effect.fn("WorkerHost.send")(function* (origin, messageId, encodedInput, encodedParameters, principal, operation, authorization) {
1424
1440
  if (Option.isNone(deps.deliveries)) return yield* failure(operation, "unavailable");
1425
1441
  const deliveries = deps.deliveries.value;
1426
1442
  const input = yield* decode(PersistedJson, encodedInput, operation);
@@ -1472,7 +1488,11 @@ const makeWorkerRuntime = Effect.fn("WorkerHost.make")(function* (options) {
1472
1488
  batchSize: 1,
1473
1489
  concurrency: 1
1474
1490
  })), Effect.provideService(MessageDeliveryStore, deliveries), Effect.provideService(PreparedInputAdmission, {
1475
- submit: (prepared) => deps.submit(prepared).pipe(Effect.mapError((error) => error._tag === "AdmissionConflict" || error._tag === "AgentInputError" ? ScheduledInputRefused.make({
1491
+ submit: (prepared) => deps.submit(prepared).pipe(Effect.provideService(CurrentStartDelivery, authorization !== void 0 && prepared.workerAdmission !== void 0 && prepared.admissionKey === messageId && prepared.inputDigest === inputDigest && sameOrigin(prepared.workerAdmission.origin, origin) ? {
1492
+ authorization,
1493
+ admission: prepared.workerAdmission,
1494
+ inputDigest
1495
+ } : void 0), Effect.mapError((error) => error._tag === "AdmissionConflict" || error._tag === "AgentInputError" ? ScheduledInputRefused.make({
1476
1496
  code: error._tag,
1477
1497
  cause: error
1478
1498
  }) : error._tag === "AdmissionPolicyError" && error.reason === "refused" ? ScheduledInputRefused.make({
@@ -1596,12 +1616,25 @@ const makeWorkerRuntime = Effect.fn("WorkerHost.make")(function* (options) {
1596
1616
  }),
1597
1617
  resolveTargetPolicy: Effect.fn("WorkerHost.resolvePreparedTargetPolicy")(function* (request) {
1598
1618
  const previous = request.continuationOf === void 0 ? void 0 : yield* completedContinuation(context.source, request.continuationOf, request.target.id, request.continuationOf.delegationId);
1599
- yield* authorize("start", "send", void 0, previous?.evidence);
1600
- return (yield* preparedTarget(request.target, request.encodedInput, previous?.evidence)).policy;
1619
+ const admission = yield* currentStart(yield* CurrentStartPreparation, context.source.threadId, sourceSubmissionId, principal, request.target.id, previous?.evidence);
1620
+ yield* authorize("start", "send", void 0, previous?.evidence, admission);
1621
+ return (yield* preparedTarget(request.target, request.encodedInput, previous?.evidence, admission)).policy;
1601
1622
  }),
1602
1623
  start: Effect.fn("WorkerHost.start")(function* (command) {
1603
1624
  const previous = command.continuationOf === void 0 ? void 0 : yield* completedContinuation(context.source, command.continuationOf, command.target.id, command.delegationId);
1625
+ const tail = yield* deps.store.inspectTail(ThreadTailRequest.make({ threadId: context.source.threadId })).pipe(Effect.mapError(storageFailure("start")));
1604
1626
  const principal = yield* authorize("start", "send", void 0, previous?.evidence);
1627
+ const startAdmission = {
1628
+ sourceThreadId: context.source.threadId,
1629
+ ...sourceSubmissionId === void 0 ? {} : { sourceSubmissionId },
1630
+ requestedPrincipal,
1631
+ principal,
1632
+ targetAgentId: command.target.id,
1633
+ ...previous === void 0 ? {} : { continuationOf: previous.evidence },
1634
+ access: "send",
1635
+ tailSequence: tail.tailSequence,
1636
+ tailDigest: tail.tailDigest
1637
+ };
1605
1638
  if (context.depth !== 0 && sourceSubmissionId === void 0) return yield* failure("start", "denied");
1606
1639
  const grant = yield* Schema.decodeUnknownEffect(SubagentGrant)(command.encodedGrant).pipe(Effect.mapError((cause) => failure("start", "corrupt", cause)));
1607
1640
  const parameters = yield* decode(PersistedJson, command.encodedParameters, "start");
@@ -1634,14 +1667,14 @@ const makeWorkerRuntime = Effect.fn("WorkerHost.make")(function* (options) {
1634
1667
  if (existing !== null) return yield* replay(existing);
1635
1668
  return yield* Effect.gen(function* () {
1636
1669
  const request = "prepare" in command ? {
1637
- ...yield* command.prepare,
1670
+ ...yield* command.prepare.pipe(Effect.provideService(CurrentStartPreparation, startAdmission)),
1638
1671
  ...command
1639
1672
  } : command;
1640
1673
  const currentPrevious = command.continuationOf === void 0 ? void 0 : yield* completedContinuation(context.source, command.continuationOf, command.target.id, command.delegationId, previous?.evidence);
1641
1674
  if (currentPrevious !== void 0) {
1642
1675
  if ((yield* authorize("start", "send", void 0, currentPrevious.evidence)) !== principal) return yield* failure("start", "denied");
1643
1676
  }
1644
- const prepared = yield* preparedTarget(request.target, request.encodedInput, currentPrevious?.evidence);
1677
+ const prepared = yield* preparedTarget(request.target, request.encodedInput, currentPrevious?.evidence, startAdmission);
1645
1678
  const resolved = prepared.resolved;
1646
1679
  const sourcePolicy = Option.getOrElse(prepared.source.policyOverride, () => context.policy);
1647
1680
  const now = yield* Clock.currentTimeMillis;
@@ -1671,10 +1704,10 @@ const makeWorkerRuntime = Effect.fn("WorkerHost.make")(function* (options) {
1671
1704
  ...reporting === void 0 ? {} : { reporting },
1672
1705
  ...request.toolCallAllowance === void 0 ? {} : { toolCallAllowance: request.toolCallAllowance }
1673
1706
  }, "start");
1674
- yield* authorizeBudget(origin, principal);
1707
+ yield* authorizeBudget(origin, principal, yield* currentStart(startAdmission, context.source.threadId, sourceSubmissionId, principal, request.target.id, currentPrevious?.evidence));
1675
1708
  const targetPolicy = Option.isSome(prepared.policy) ? prepared.policy.value : origin.budgetScope === "worker-run" ? resolved.definition.policy : AgentPolicy.resolve(resolved.definition.policyOverrides ?? resolved.definition.policy, sourcePolicy);
1676
1709
  if (!withinPolicy(origin, origin.budgetScope === "worker-run" ? targetPolicy : sourcePolicy, targetPolicy)) return yield* failure("start", "capacity");
1677
- const delivery = yield* send(origin, messageId, request.encodedInput, request.encodedParameters, principal, "start");
1710
+ const delivery = yield* send(origin, messageId, request.encodedInput, request.encodedParameters, principal, "start", startAdmission);
1678
1711
  return {
1679
1712
  worker: origin.worker,
1680
1713
  delivery
@@ -2338,11 +2371,6 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (bindings) {
2338
2371
  const ledger = yield* SubmissionLedger;
2339
2372
  const submissionScheduling = yield* SubmissionScheduling;
2340
2373
  const store = yield* ThreadStore;
2341
- const publicationPending = (threadId) => store.lifecyclePublications === void 0 ? Effect.succeed(false) : store.lifecyclePublications.pendingDeadlineFor(threadId).pipe(Effect.map(Option.isSome), Effect.mapError((cause) => ThreadStoreError.make({
2342
- operation: "read lifecycle publication gate",
2343
- message: "Native lifecycle publication state is unavailable",
2344
- cause
2345
- })));
2346
2374
  const wake = yield* WakeScheduler;
2347
2375
  const failpoint = yield* DurableRuntimeFailpoint;
2348
2376
  const config = yield* DurableRuntimeConfig;
@@ -4103,7 +4131,6 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (bindings) {
4103
4131
  */
4104
4132
  const runModel = (agent, ctx, submission, tokenRef, records, canonical, canonicalThrough, journalSeed, journalMetadata, lineage, approvalDecisions, runTiming, yieldAfter) => Effect.gen(function* () {
4105
4133
  const submissionId = submission.submissionId;
4106
- if (yield* publicationPending(submission.threadId)) return { _tag: "yielded" };
4107
4134
  const runId = runIdForSubmission(submissionId);
4108
4135
  const boundaries = [];
4109
4136
  const journal = yield* projectRunJournalStream(canonical, runId, (boundary) => boundaries.push(boundary), journalSeed, journalMetadata);
@@ -4461,12 +4488,12 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (bindings) {
4461
4488
  ...state,
4462
4489
  history
4463
4490
  });
4464
- const instructionView = (messages, instructions, insertWhenAbsent) => {
4491
+ const instructionView = (messages, instructions, insertWhenAbsent, priorRunPrefixLength) => {
4465
4492
  const projected = [];
4466
4493
  const lengths = [0];
4467
4494
  let inserted = false;
4468
- for (const message of messages) {
4469
- if (message.role === "system") {
4495
+ for (const [index, message] of messages.entries()) {
4496
+ if (index >= priorRunPrefixLength && message.role === "system") {
4470
4497
  if (!inserted) projected.push(...instructions);
4471
4498
  inserted = true;
4472
4499
  } else projected.push(message);
@@ -4478,11 +4505,21 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (bindings) {
4478
4505
  prefixLength: (length) => lengths[length] ?? projected.length
4479
4506
  };
4480
4507
  };
4481
- const resumeContext = { prepare: ({ source }) => Ref.get(stateRef).pipe(Effect.map((state) => ({ prompt: Prompt.fromMessages([...instructionView(resumeProjection.prompt.content, source.content.slice(0, state.baseLen).filter((message) => message.role === "system"), true).messages, ...source.content.slice(state.baseLen ?? source.content.length)]) }))) };
4508
+ const resumeContext = { prepare: ({ source }) => Ref.get(stateRef).pipe(Effect.map((state) => {
4509
+ const view = instructionView(resumeProjection.prompt.content, source.content.slice(resumeProjection.historyBefore.content.length, state.baseLen).filter((message) => message.role === "system"), true, resumeProjection.historyBefore.content.length);
4510
+ return {
4511
+ prompt: Prompt.fromMessages([...view.messages, ...source.content.slice(state.baseLen ?? source.content.length)]),
4512
+ priorRunPrefixLength: view.prefixLength(resumeProjection.historyBefore.content.length)
4513
+ };
4514
+ })) };
4482
4515
  const externalContext = runContextPreparation.hook;
4483
- const preparedContext = externalContext === void 0 ? journal.committedTurns === 0 ? void 0 : resumeContext : { prepare: (request) => (journal.committedTurns === 0 ? Effect.succeed({ prompt: request.source }) : resumeContext.prepare(request)).pipe(Effect.flatMap(({ prompt }) => externalContext.prepare({
4516
+ const preparedContext = externalContext === void 0 ? journal.committedTurns === 0 ? void 0 : resumeContext : { prepare: (request) => (journal.committedTurns === 0 ? Effect.succeed({
4517
+ prompt: request.source,
4518
+ priorRunPrefixLength: journal.historyBefore.content.length
4519
+ }) : resumeContext.prepare(request)).pipe(Effect.flatMap(({ prompt, priorRunPrefixLength }) => externalContext.prepare({
4484
4520
  ...request,
4485
- source: prompt
4521
+ source: prompt,
4522
+ priorRunPrefixLength
4486
4523
  }))) };
4487
4524
  const durability = {
4488
4525
  noteToolExposure: (turn, snapshot) => Effect.sync(() => {
@@ -4639,7 +4676,7 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (bindings) {
4639
4676
  const coverable = sourceBoundaries.filter((boundary) => commit.kind !== "summarize" || ownerFirstSequence === void 0 || boundary.sequence < ownerFirstSequence);
4640
4677
  if (coverable.length === 0) return yield* CompactionError.make({ message: commit.kind === "rollover" ? "Durable rollover requires complete canonical records" : "Durable compaction requires eligible canonical records" });
4641
4678
  const state = yield* Ref.get(stateRef);
4642
- const comparisonView = instructionView(sourceJournal.prompt.content, state.history?.content.slice(0, state.baseLen).filter((message) => message.role === "system") ?? [], false);
4679
+ const comparisonView = instructionView(sourceJournal.prompt.content, state.history?.content.slice(resumeProjection.historyBefore.content.length, state.baseLen).filter((message) => message.role === "system") ?? [], false, sourceJournal.historyBefore.content.length);
4643
4680
  let matchingPrefix = 0;
4644
4681
  let requiredThrough = 0;
4645
4682
  const comparisonLimit = Math.min(comparisonView.messages.length, commit.through);
@@ -4834,18 +4871,11 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (bindings) {
4834
4871
  const decodedInput = yield* Schema.decodeEffect(agent.definition.input)(encodedInput).pipe(Effect.mapError((cause) => AgentInputError.make({ message: cause.message })));
4835
4872
  return yield* renderInputPrompt(inputPrompt, decodedInput, encodedInput);
4836
4873
  });
4837
- const yieldForPublication = Effect.gen(function* () {
4838
- const pending = yield* Effect.exit(publicationPending(submission.threadId));
4839
- if (Exit.isSuccess(pending) && !pending.value) return;
4840
- yield* recordHalt(commitPendingTurn);
4841
- if (Exit.isFailure(pending)) return yield* recordHalt(Effect.failCause(pending.cause));
4842
- yield* Deferred.succeed(yieldSignal, void 0);
4843
- return yield* Effect.never;
4874
+ const preserveToolResults = Effect.gen(function* () {
4875
+ const state = yield* Ref.get(stateRef);
4876
+ if (state.pendingTurn !== void 0 && knownIds.has(modelResponseRecordId(runId, state.pendingTurn.turn))) yield* commitPendingTurn;
4844
4877
  });
4845
4878
  const input = { drain: (policy) => Effect.gen(function* () {
4846
- const state = yield* Ref.get(stateRef);
4847
- if (state.pendingTurn !== void 0 && knownIds.has(modelResponseRecordId(runId, state.pendingTurn.turn))) yield* recordHalt(commitPendingTurn);
4848
- yield* yieldForPublication;
4849
4879
  const joinedInputs = yield* recordHalt(Effect.gen(function* () {
4850
4880
  const limit = policy === "one" ? 1 : MAX_JOIN_DRAIN;
4851
4881
  const joinedInputs = [];
@@ -4870,6 +4900,7 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (bindings) {
4870
4900
  if (lastHostResponseSequence !== void 0 && lastHostResponseSequence > existing.sequence) continue;
4871
4901
  const payload = existing.record.payload;
4872
4902
  if (payload._tag !== "UserInputRecorded") continue;
4903
+ yield* preserveToolResults;
4873
4904
  joinedInputs.push(payload);
4874
4905
  }
4875
4906
  if (joinedInputs.length < limit) {
@@ -4887,6 +4918,16 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (bindings) {
4887
4918
  yield* ledger.revertJoining(RevertJoiningRequest.make({ submissionId: claim.submissionId }));
4888
4919
  continue;
4889
4920
  }
4921
+ const payload = {
4922
+ input: claim.inputPayload,
4923
+ ...claimSnapshot.submission.messageAdmission === void 0 ? {} : { messageAdmission: claimSnapshot.submission.messageAdmission }
4924
+ };
4925
+ const rendered = yield* Effect.result(renderJoinedInput(payload));
4926
+ if (Result.isFailure(rendered)) {
4927
+ for (const remaining of claims.slice(claims.indexOf(claim))) yield* ledger.revertJoining(RevertJoiningRequest.make({ submissionId: remaining.submissionId }));
4928
+ break;
4929
+ }
4930
+ yield* preserveToolResults;
4890
4931
  const recordId = submissionInputRecordId(claim.submissionId);
4891
4932
  let sequence;
4892
4933
  const existing = joinedInputEnvelopes.get(claim.submissionId);
@@ -4916,15 +4957,14 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (bindings) {
4916
4957
  }));
4917
4958
  deliveredJoinInputs.add(claim.submissionId);
4918
4959
  joinedInputs.push({
4919
- input: claim.inputPayload,
4920
- ...claimSnapshot.submission.messageAdmission === void 0 ? {} : { messageAdmission: claimSnapshot.submission.messageAdmission }
4960
+ ...payload,
4961
+ rendered: rendered.success
4921
4962
  });
4922
4963
  }
4923
4964
  }
4924
4965
  return joinedInputs;
4925
- }));
4926
- yield* yieldForPublication;
4927
- return yield* Effect.forEach(joinedInputs, (joinedInput) => renderJoinedInput(joinedInput).pipe(Effect.map((input) => ({
4966
+ }).pipe(Effect.onExit((exit) => Exit.isFailure(exit) ? preserveToolResults : Effect.void)));
4967
+ return yield* Effect.forEach(joinedInputs, (joinedInput) => (joinedInput.rendered === void 0 ? renderJoinedInput(joinedInput) : Effect.succeed(joinedInput.rendered)).pipe(Effect.map((input) => ({
4928
4968
  kind: "steering",
4929
4969
  input
4930
4970
  }))));
@@ -5216,7 +5256,7 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (bindings) {
5216
5256
  history: pending === void 0 ? journal.historyBefore : resumeProjection.historyBefore,
5217
5257
  onHistory,
5218
5258
  input,
5219
- commandDrainPolicy: submission.workerAdmission === void 0 ? "one" : "all",
5259
+ commandDrainPolicy: "all",
5220
5260
  ...journal.committedTurns > 0 || Schema.is(FrameworkMessage)(submission.messageAdmission) ? { retainedInput: submission.inputPayload } : {},
5221
5261
  ...Schema.is(FrameworkMessage)(submission.messageAdmission) ? { frameworkMessage: submission.messageAdmission } : {},
5222
5262
  approval,
@@ -5246,7 +5286,6 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (bindings) {
5246
5286
  ...preparedContext === void 0 ? {} : { context: preparedContext },
5247
5287
  beforeTurn: () => Effect.gen(function* () {
5248
5288
  yield* recordHalt(commitPendingTurn);
5249
- yield* yieldForPublication;
5250
5289
  if (yieldAfter !== void 0 && (yield* Clock.currentTimeMillis) >= DateTime.toEpochMillis(yieldAfter)) {
5251
5290
  yield* Deferred.succeed(yieldSignal, void 0);
5252
5291
  return yield* Effect.never;
@@ -5503,7 +5542,7 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (bindings) {
5503
5542
  const failure = yield* Ref.get(haltRef);
5504
5543
  if (failure !== void 0) return yield* Effect.fail(failure);
5505
5544
  yield* handleEvent(event);
5506
- }))).pipe(Effect.tapCause((cause) => Option.isSome(agentApprovalPendingOption(cause)) && cause.reasons.every(Cause.isFailReason) ? Effect.flatMap(DurableApprovalSuspension, (retain) => retain === void 0 ? Effect.void : halt(retain)) : Effect.void), Effect.as({ _tag: "run" }));
5545
+ }))).pipe(Effect.onExit((exit) => Exit.hasInterrupts(exit) ? preserveToolResults : Effect.void), Effect.tapCause((cause) => Option.isSome(agentApprovalPendingOption(cause)) && cause.reasons.every(Cause.isFailReason) ? Effect.flatMap(DurableApprovalSuspension, (retain) => retain === void 0 ? Effect.void : halt(retain)) : Effect.void), Effect.as({ _tag: "run" }));
5507
5546
  const abortWatcher = halt(Effect.gen(function* () {
5508
5547
  while (true) {
5509
5548
  yield* Effect.sleep(config.abortPollInterval);
@@ -5522,7 +5561,7 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (bindings) {
5522
5561
  yield* Ref.set(tokenRef, renewal.ownershipToken);
5523
5562
  }).pipe(Effect.uninterruptible), { schedule: Schedule.spaced(config.leaseRenewalInterval) }).pipe(Effect.andThen(Effect.never)));
5524
5563
  const execution = Effect.raceFirst(consume, Effect.raceFirst(abortWatcher, renewal));
5525
- const result = yield* (yieldAfter === void 0 && submissionScheduling.yieldTo === void 0 && store.lifecyclePublications === void 0 ? execution : Effect.raceFirst(execution, Deferred.await(yieldSignal).pipe(Effect.map((nextSubmissionId) => ({
5564
+ const result = yield* (yieldAfter === void 0 && submissionScheduling.yieldTo === void 0 ? execution : Effect.raceFirst(execution, Deferred.await(yieldSignal).pipe(Effect.map((nextSubmissionId) => ({
5526
5565
  _tag: "yielded",
5527
5566
  ...nextSubmissionId === void 0 ? {} : { nextSubmissionId }
5528
5567
  }))))).pipe(Effect.provideService(IdGenerator$1, idGenerator)).pipe(Effect.catchCauseFilter(Cause.findError, (error, cause) => {
@@ -5898,7 +5937,6 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (bindings) {
5898
5937
  let handoff;
5899
5938
  let nextHandoff;
5900
5939
  const attempt = Effect.scoped(Effect.gen(function* () {
5901
- if (yield* publicationPending(threadId)) return Option.none();
5902
5940
  const claimed = yield* acquireClaim(threadId, handoff);
5903
5941
  if (Option.isNone(claimed)) return Option.none();
5904
5942
  const { claim, tokenRef } = claimed.value;
@@ -7180,4 +7218,4 @@ var DurableAgentRuntime = class DurableAgentRuntime extends Context.Service()("@
7180
7218
  //#endregion
7181
7219
  export { DurableApprovalSuspension as a, RecoveryFailure as c, childReservationIdFor as d, isolateRecovery as f, threadCreatedRecordId as g, threadCreatedBatchId as h, DurableApprovalResolver as i, RecoveryReport as l, recoveryRepairRecordId as m, DurableAgentRuntime as n, DurableRuntimeConfig as o, recoveryRepairBatchId as p, DurableAgentRuntime_exports as r, RecoveryBlocked as s, ApprovalSuspensionError as t, RecoverySweepResult as u };
7182
7220
 
7183
- //# sourceMappingURL=DurableAgentRuntime-D8GI66mP.mjs.map
7221
+ //# sourceMappingURL=DurableAgentRuntime-DLa4IwFi.mjs.map