eve 0.39.2 → 0.39.3

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 (43) hide show
  1. package/CHANGELOG.md +11 -1
  2. package/dist/src/channel/delivery-metadata.js +1 -1
  3. package/dist/src/compiler/extension-compatibility.d.ts +2 -2
  4. package/dist/src/compiler/extension-compatibility.js +1 -1
  5. package/dist/src/execution/parked-delivery-wait.js +1 -1
  6. package/dist/src/execution/proxied-deliver-step.js +1 -1
  7. package/dist/src/execution/report-dropped-wire-payload-step.d.ts +13 -0
  8. package/dist/src/execution/report-dropped-wire-payload-step.js +1 -0
  9. package/dist/src/execution/sandbox/bindings/just-bash-runtime.js +1 -1
  10. package/dist/src/execution/session-command-inbox.d.ts +3 -5
  11. package/dist/src/execution/session-command-inbox.js +1 -1
  12. package/dist/src/execution/session-timeout-steps.js +1 -1
  13. package/dist/src/execution/tasks/child/steps.js +1 -1
  14. package/dist/src/execution/turn-control-receiver.js +1 -1
  15. package/dist/src/execution/wire/session-inbox-contract.d.ts +24 -0
  16. package/dist/src/execution/wire/session-inbox-contract.js +1 -0
  17. package/dist/src/execution/wire/session-inbox-encoder.d.ts +23 -0
  18. package/dist/src/execution/wire/session-inbox-encoder.js +1 -0
  19. package/dist/src/execution/wire/session-inbox-resume.d.ts +10 -0
  20. package/dist/src/execution/wire/session-inbox-resume.js +1 -0
  21. package/dist/src/execution/wire/session-inbox-wire.d.ts +29 -0
  22. package/dist/src/execution/wire/session-inbox-wire.js +1 -0
  23. package/dist/src/execution/wire/session-inbox-wire.v0.d.ts +5 -0
  24. package/dist/src/execution/wire/session-inbox-wire.v0.js +1 -0
  25. package/dist/src/execution/wire/session-inbox-wire.v1.d.ts +237 -0
  26. package/dist/src/execution/wire/session-inbox-wire.v1.js +1 -0
  27. package/dist/src/execution/workflow-runtime.js +1 -1
  28. package/dist/src/internal/application/package.js +1 -1
  29. package/dist/src/internal/authored-module-loader.js +3 -3
  30. package/dist/src/internal/nitro/host/extension-external-dependency-plugin.js +1 -1
  31. package/dist/src/public/channels/eve.js +1 -1
  32. package/dist/src/public/channels/slack/slackChannel.d.ts +3 -1
  33. package/dist/src/public/channels/slack/slackChannel.js +1 -1
  34. package/dist/src/public/definitions/channel.d.ts +2 -0
  35. package/dist/src/public/definitions/channel.js +1 -1
  36. package/dist/src/public/sandbox/just-bash-sandbox.d.ts +2 -0
  37. package/dist/src/runtime/actions/types.js +1 -1
  38. package/dist/src/runtime/session-callback-route.js +1 -1
  39. package/dist/src/runtime/task-input-response-route.js +1 -1
  40. package/dist/src/setup/scaffold/create/project.js +1 -1
  41. package/package.json +2 -1
  42. package/dist/src/execution/session-command-wire.d.ts +0 -24
  43. package/dist/src/execution/session-command-wire.js +0 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # eve
2
2
 
3
+ ## 0.39.3
4
+
5
+ ### Patch Changes
6
+
7
+ - c2bfee1: Keep top-level sessions in an independent `agent.session` trace while preserving shared trace context for local and remote subagents.
8
+ - 9a7964b: Add a configurable, development-only `@eve/self-modification` source-editing subagent that mounts authored agent source read-write, exposes its instructions through an extension, and uses structured file tools to inspect and safely update source.
9
+ - 542c380: Preserve the configured `turnPolicy` on built-in and custom channels, and restore the option for Slack channels.
10
+ - 75bd9c8: Allow extension-owned external dependencies to use ESM-only packages that do not expose a CommonJS entry.
11
+ - 6fc904d: Session inbox hook payloads are now a validated, versioned wire format following eve's existing durable-format idioms. Producers inspect the target hook's wire capability and encode the shape its pinned consumer understands, including sessions created by eve 0.30.8; readers migrate legacy shapes forward and reject unknown versions instead of reinterpreting them.
12
+
3
13
  ## 0.39.2
4
14
 
5
15
  ### Patch Changes
@@ -239,7 +249,7 @@
239
249
 
240
250
  ### Patch Changes
241
251
 
242
- - 2a141f0: Keep sessions resumable across eve deployment upgrades: sends now cross durable session hooks as the established `deliver` envelope (with a transitional single-payload mirror for sessions pinned to 0.30.3–0.30.8), and consumers keep accepting payloads persisted by those versions.
252
+ - 2a141f0: Keep sessions resumable across eve deployment upgrades: sends now cross durable session hooks as the established `deliver` envelope (with a transitional single-payload mirror for sessions pinned to 0.30.5–0.30.8), and consumers keep accepting payloads persisted by those versions.
243
253
  - 99982f7: Treat AI SDK `.devtools` like other generated directories: ignore it in `eve dev` watching, agent discovery, and source snapshots so generation writes do not recompile or warn.
244
254
  - a497e8d: Preserve each tool executor's concrete return type through `defineTool`, so non-streaming tools no longer appear to return an async iterable. Allow `ctx.to()` to infer closed receive-target interfaces such as Slack's without requiring an index signature.
245
255
  - fe9e7ef: Consume interactive authorization callback results once and keep targeted connection searches from replaying callbacks for unrelated connections.
@@ -1 +1 @@
1
- function createChannelDeliveryMetadata(e){return{...e,deliveryId:crypto.randomUUID()}}export{createChannelDeliveryMetadata};
1
+ function createChannelDeliveryMetadata(e){let t={channelKind:e.channelKind,channelName:e.channelName,deliveryId:crypto.randomUUID()};return e.requestId!==void 0&&(t.requestId=e.requestId),e.requestTraceContext!==void 0&&(t.requestTraceContext=e.requestTraceContext),t}export{createChannelDeliveryMetadata};
@@ -21,8 +21,8 @@ declare const EXTENSION_CAPABILITY_CONTRACTS: {
21
21
  readonly dropped: {};
22
22
  };
23
23
  readonly channel: {
24
- readonly current: 3;
25
- readonly supported: readonly [1, 2, 3];
24
+ readonly current: 4;
25
+ readonly supported: readonly [1, 2, 3, 4];
26
26
  readonly dropped: {};
27
27
  };
28
28
  readonly schedule: {
@@ -1 +1 @@
1
- import{readFile,writeFile}from"node:fs/promises";import{z}from"#compiled/zod/index.js";import{join}from"node:path";import{formatValidationError}from"#runtime/validation.js";const EXTENSION_COMPATIBILITY_MANIFEST_KIND=`eve-extension`,EXTENSION_COMPATIBILITY_MANIFEST_FORMAT_VERSION=2,EXTENSION_COMPATIBILITY_MANIFEST_FILENAME=`_manifest.json`,EXTENSION_CAPABILITY_CONTRACTS={extension:{current:1,supported:[1],dropped:{}},tool:{current:13,supported:[1,2,3,4,5,6,7,8,9,10,11,12,13],dropped:{}},dynamicTool:{current:18,supported:[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18],dropped:{}},channel:{current:3,supported:[1,2,3],dropped:{}},schedule:{current:2,supported:[1,2],dropped:{}},subagent:{current:2,supported:[1,2],dropped:{}},connection:{current:5,supported:[1,2,3,4,5],dropped:{}},hook:{current:14,supported:[10,11,12,13,14],dropped:{1:`Model identity moved from session.started runtime metadata to step.started call attribution.`,2:`Model identity moved from session.started runtime metadata to step.started call attribution.`,3:`Model identity moved from session.started runtime metadata to step.started call attribution.`,4:`Model identity moved from session.started runtime metadata to step.started call attribution.`,5:`Model identity moved from session.started runtime metadata to step.started call attribution.`,6:`Model identity moved from session.started runtime metadata to step.started call attribution.`,7:`Model identity moved from session.started runtime metadata to step.started call attribution.`,8:`Model identity moved from session.started runtime metadata to step.started call attribution.`,9:`Model identity moved from session.started runtime metadata to step.started call attribution.`}},skill:{current:1,supported:[1],dropped:{}},dynamicSkill:{current:12,supported:[1,2,3,4,5,6,7,8,9,10,11,12],dropped:{}},instructions:{current:2,supported:[1,2],dropped:{}},dynamicInstructions:{current:13,supported:[1,2,3,4,5,6,7,8,9,10,11,12,13],dropped:{}},config:{current:1,supported:[1],dropped:{}},state:{current:3,supported:[1,2,3],dropped:{}}},EXTENSION_CAPABILITY_VERSIONS=Object.fromEntries(Object.entries(EXTENSION_CAPABILITY_CONTRACTS).map(([e,t])=>[e,t.current])),EXTENSION_CAPABILITY_SUPPORT=Object.keys(EXTENSION_CAPABILITY_CONTRACTS).reduce((e,t)=>(e[t]=EXTENSION_CAPABILITY_CONTRACTS[t].supported,e),{}),extensionCompatibilityManifestV1Schema=z.object({kind:z.literal(EXTENSION_COMPATIBILITY_MANIFEST_KIND),formatVersion:z.literal(1),builtWithEve:z.string().min(1),requires:z.record(z.string(),z.number().int().positive())}).strict(),extensionCompatibilityManifestV2Schema=extensionCompatibilityManifestV1Schema.extend({formatVersion:z.literal(2),build:z.object({externalDependencies:z.array(z.string().min(1)).readonly()}).strict().optional()}),extensionCompatibilityManifestSchema=z.union([extensionCompatibilityManifestV1Schema,extensionCompatibilityManifestV2Schema]);function serializeExtensionCompatibilityManifest(e){return`${JSON.stringify(e,null,2)}\n`}function parseExtensionCompatibilityManifest(e,t){let n;try{n=JSON.parse(e)}catch(e){throw Error(`Extension compatibility manifest "${t}" is not valid JSON: ${e instanceof Error?e.message:String(e)}`)}let r=extensionCompatibilityManifestSchema.safeParse(n);if(!r.success)throw Error(`Extension compatibility manifest "${t}" is invalid. ${formatValidationError(r.error)}`);return r.data}async function readExtensionCompatibilityManifest(t){return parseExtensionCompatibilityManifest(await readFile(t,`utf8`),t)}async function writeExtensionCompatibilityManifest(e,n){await writeFile(join(e,EXTENSION_COMPATIBILITY_MANIFEST_FILENAME),serializeExtensionCompatibilityManifest(n),`utf8`)}function findUnsupportedExtensionCapabilities(e,t=EXTENSION_CAPABILITY_SUPPORT){return Object.entries(e.requires).flatMap(([e,n])=>{let r=Object.hasOwn(t,e)?t[e]??[]:[];return r.includes(n)?[]:[{capability:e,requiredVersion:n,supportedVersions:r}]}).sort((e,t)=>e.capability.localeCompare(t.capability))}export{EXTENSION_CAPABILITY_SUPPORT,EXTENSION_CAPABILITY_VERSIONS,EXTENSION_COMPATIBILITY_MANIFEST_FILENAME,EXTENSION_COMPATIBILITY_MANIFEST_FORMAT_VERSION,EXTENSION_COMPATIBILITY_MANIFEST_KIND,findUnsupportedExtensionCapabilities,parseExtensionCompatibilityManifest,readExtensionCompatibilityManifest,serializeExtensionCompatibilityManifest,writeExtensionCompatibilityManifest};
1
+ import{readFile,writeFile}from"node:fs/promises";import{z}from"#compiled/zod/index.js";import{join}from"node:path";import{formatValidationError}from"#runtime/validation.js";const EXTENSION_COMPATIBILITY_MANIFEST_KIND=`eve-extension`,EXTENSION_COMPATIBILITY_MANIFEST_FORMAT_VERSION=2,EXTENSION_COMPATIBILITY_MANIFEST_FILENAME=`_manifest.json`,EXTENSION_CAPABILITY_CONTRACTS={extension:{current:1,supported:[1],dropped:{}},tool:{current:13,supported:[1,2,3,4,5,6,7,8,9,10,11,12,13],dropped:{}},dynamicTool:{current:18,supported:[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18],dropped:{}},channel:{current:4,supported:[1,2,3,4],dropped:{}},schedule:{current:2,supported:[1,2],dropped:{}},subagent:{current:2,supported:[1,2],dropped:{}},connection:{current:5,supported:[1,2,3,4,5],dropped:{}},hook:{current:14,supported:[10,11,12,13,14],dropped:{1:`Model identity moved from session.started runtime metadata to step.started call attribution.`,2:`Model identity moved from session.started runtime metadata to step.started call attribution.`,3:`Model identity moved from session.started runtime metadata to step.started call attribution.`,4:`Model identity moved from session.started runtime metadata to step.started call attribution.`,5:`Model identity moved from session.started runtime metadata to step.started call attribution.`,6:`Model identity moved from session.started runtime metadata to step.started call attribution.`,7:`Model identity moved from session.started runtime metadata to step.started call attribution.`,8:`Model identity moved from session.started runtime metadata to step.started call attribution.`,9:`Model identity moved from session.started runtime metadata to step.started call attribution.`}},skill:{current:1,supported:[1],dropped:{}},dynamicSkill:{current:12,supported:[1,2,3,4,5,6,7,8,9,10,11,12],dropped:{}},instructions:{current:2,supported:[1,2],dropped:{}},dynamicInstructions:{current:13,supported:[1,2,3,4,5,6,7,8,9,10,11,12,13],dropped:{}},config:{current:1,supported:[1],dropped:{}},state:{current:3,supported:[1,2,3],dropped:{}}},EXTENSION_CAPABILITY_VERSIONS=Object.fromEntries(Object.entries(EXTENSION_CAPABILITY_CONTRACTS).map(([e,t])=>[e,t.current])),EXTENSION_CAPABILITY_SUPPORT=Object.keys(EXTENSION_CAPABILITY_CONTRACTS).reduce((e,t)=>(e[t]=EXTENSION_CAPABILITY_CONTRACTS[t].supported,e),{}),extensionCompatibilityManifestV1Schema=z.object({kind:z.literal(EXTENSION_COMPATIBILITY_MANIFEST_KIND),formatVersion:z.literal(1),builtWithEve:z.string().min(1),requires:z.record(z.string(),z.number().int().positive())}).strict(),extensionCompatibilityManifestV2Schema=extensionCompatibilityManifestV1Schema.extend({formatVersion:z.literal(2),build:z.object({externalDependencies:z.array(z.string().min(1)).readonly()}).strict().optional()}),extensionCompatibilityManifestSchema=z.union([extensionCompatibilityManifestV1Schema,extensionCompatibilityManifestV2Schema]);function serializeExtensionCompatibilityManifest(e){return`${JSON.stringify(e,null,2)}\n`}function parseExtensionCompatibilityManifest(e,t){let n;try{n=JSON.parse(e)}catch(e){throw Error(`Extension compatibility manifest "${t}" is not valid JSON: ${e instanceof Error?e.message:String(e)}`)}let r=extensionCompatibilityManifestSchema.safeParse(n);if(!r.success)throw Error(`Extension compatibility manifest "${t}" is invalid. ${formatValidationError(r.error)}`);return r.data}async function readExtensionCompatibilityManifest(t){return parseExtensionCompatibilityManifest(await readFile(t,`utf8`),t)}async function writeExtensionCompatibilityManifest(e,n){await writeFile(join(e,EXTENSION_COMPATIBILITY_MANIFEST_FILENAME),serializeExtensionCompatibilityManifest(n),`utf8`)}function findUnsupportedExtensionCapabilities(e,t=EXTENSION_CAPABILITY_SUPPORT){return Object.entries(e.requires).flatMap(([e,n])=>{let r=Object.hasOwn(t,e)?t[e]??[]:[];return r.includes(n)?[]:[{capability:e,requiredVersion:n,supportedVersions:r}]}).sort((e,t)=>e.capability.localeCompare(t.capability))}export{EXTENSION_CAPABILITY_SUPPORT,EXTENSION_CAPABILITY_VERSIONS,EXTENSION_COMPATIBILITY_MANIFEST_FILENAME,EXTENSION_COMPATIBILITY_MANIFEST_FORMAT_VERSION,EXTENSION_COMPATIBILITY_MANIFEST_KIND,findUnsupportedExtensionCapabilities,parseExtensionCompatibilityManifest,readExtensionCompatibilityManifest,serializeExtensionCompatibilityManifest,writeExtensionCompatibilityManifest};
@@ -1 +1 @@
1
- import{coalesceDeliveries}from"#harness/messages.js";import{routeDeliverToChildren}from"#execution/route-child-delivery.js";import{sendCommandToDelivery}from"#execution/session-command-wire.js";async function nextTurnDelivery(e){if(e.awaitAuthorizationCallbacks!==!0)return await awaitNextTurnDelivery(e);e.commandInbox.setAuthorizationWindow(!0);try{return await awaitNextTurnDelivery(e)}finally{e.commandInbox.setAuthorizationWindow(!1)}}async function awaitNextTurnDelivery(e){let n=e.cancelledTaskIds??new Set,r=e.seenTaskDeliveries??new Set;for(;;){let i=await waitForNextSessionAction({bufferedDeliveries:e.bufferedDeliveries,bufferedSessionControls:e.bufferedSessionControls,cancelledTaskIds:n,commandInbox:e.commandInbox,deferDeliveries:e.deferDeliveries,seenTaskDeliveries:r});if(i.kind===`authorization`)return i;if(i.kind!==`delivery`)return{kind:i.kind};let a=i.delivery;if(a===null)return{kind:`closed`};let o=await routeDeliverToChildren({delivery:a,parentWritable:e.driverWritable,serializedContext:e.stateCursor.serializedContext,sessionState:e.stateCursor.sessionState});if(e.stateCursor.adoptState(o),o.kind===`cancel-turn`)return{kind:`cancel-turn`};if(o.remainder!==void 0)return{delivery:o.remainder,kind:`turn`}}}async function waitForNextSessionAction(e){let t=e.bufferedSessionControls.shift();if(t!==void 0)return{kind:t};for(;e.bufferedDeliveries[0]!==void 0&&isCancelledTaskDelivery(e.bufferedDeliveries[0],e.cancelledTaskIds);)e.bufferedDeliveries.shift();if(e.deferDeliveries!==!0&&!e.commandInbox.hasReadyAuthorization()&&e.bufferedDeliveries.length>0)return{delivery:takeBufferedTurnDelivery(e.bufferedDeliveries),kind:`delivery`};for(;;){let{result:t,source:r}=await e.commandInbox.nextWithSource();if(e.commandInbox.consumeNext(),r===`authorization`)return t.done?{closed:!0,kind:`authorization`,payloads:[]}:{closed:!1,kind:`authorization`,payloads:t.value.kind===`deliver`?t.value.payloads:[]};if(t.done)return{delivery:null,kind:`delivery`};if(t.value.kind===`session-timeout`)return{kind:`expired`};if(t.value.kind===`clear`||t.value.kind===`compact`||t.value.kind===`reset`)return{kind:t.value.kind};if(t.value.kind===`cancel`){if(t.value.taskId!==void 0){e.cancelledTaskIds.add(t.value.taskId);let n=e.bufferedDeliveries.filter(t=>!isCancelledTaskDelivery(t,e.cancelledTaskIds));e.bufferedDeliveries.splice(0,e.bufferedDeliveries.length,...n)}continue}if(t.value.kind===`runtime-action-result`)continue;let i=t.value.taskDeliveryId??t.value.caller?.taskId;if(i!==void 0&&isCancelledTaskDeliveryId(i,e.cancelledTaskIds))continue;if(i!==void 0){if(e.seenTaskDeliveries.has(i))continue;e.seenTaskDeliveries.add(i)}if(t.value.kind===`deliver`){if(e.deferDeliveries===!0){e.bufferedDeliveries.push(t.value);continue}return{delivery:t.value,kind:`delivery`}}let a=sendCommandToDelivery(t.value);if(e.deferDeliveries===!0){e.bufferedDeliveries.push(a);continue}return{delivery:a,kind:`delivery`}}}function isCancelledTaskDelivery(e,t){let n=e.taskDeliveryId??e.caller?.taskId;return n!==void 0&&isCancelledTaskDeliveryId(n,t)}function isCancelledTaskDeliveryId(e,t){return[...t].some(t=>e===t||e.startsWith(`${t}:`))}function takeBufferedTurnDelivery(t){let n=t.shift();if(n===void 0)throw Error(`Cannot take a turn delivery from an empty buffer.`);let r=[n],i=n.caller;for(;t.length>0;){let e=t[0];if(e===void 0||n.taskDeliveryId!==void 0||e.taskDeliveryId!==void 0||i!==void 0&&e.caller!==void 0)break;let a=t.shift();if(a===void 0)throw Error(`Buffered turn delivery disappeared while partitioning.`);r.push(a),i??=a.caller}return coalesceDeliveries(r)}export{nextTurnDelivery};
1
+ import{coalesceDeliveries}from"#harness/messages.js";import{routeDeliverToChildren}from"#execution/route-child-delivery.js";import{reportDroppedWirePayloadStep}from"#execution/report-dropped-wire-payload-step.js";import{SessionInboxWireError,sessionInboxWire}from"#execution/wire/session-inbox-wire.js";async function nextTurnDelivery(e){if(e.awaitAuthorizationCallbacks!==!0)return await awaitNextTurnDelivery(e);e.commandInbox.setAuthorizationWindow(!0);try{return await awaitNextTurnDelivery(e)}finally{e.commandInbox.setAuthorizationWindow(!1)}}async function awaitNextTurnDelivery(e){let n=e.cancelledTaskIds??new Set,r=e.seenTaskDeliveries??new Set;for(;;){let i=await waitForNextSessionAction({bufferedDeliveries:e.bufferedDeliveries,bufferedSessionControls:e.bufferedSessionControls,cancelledTaskIds:n,commandInbox:e.commandInbox,deferDeliveries:e.deferDeliveries,seenTaskDeliveries:r});if(i.kind===`authorization`)return i;if(i.kind!==`delivery`)return{kind:i.kind};let a=i.delivery;if(a===null)return{kind:`closed`};let o=await routeDeliverToChildren({delivery:a,parentWritable:e.driverWritable,serializedContext:e.stateCursor.serializedContext,sessionState:e.stateCursor.sessionState});if(e.stateCursor.adoptState(o),o.kind===`cancel-turn`)return{kind:`cancel-turn`};if(o.remainder!==void 0)return{delivery:o.remainder,kind:`turn`}}}async function waitForNextSessionAction(e){let t=e.bufferedSessionControls.shift();if(t!==void 0)return{kind:t};for(;e.bufferedDeliveries[0]!==void 0&&isCancelledTaskDelivery(e.bufferedDeliveries[0],e.cancelledTaskIds);)e.bufferedDeliveries.shift();if(e.deferDeliveries!==!0&&!e.commandInbox.hasReadyAuthorization()&&e.bufferedDeliveries.length>0)return{delivery:takeBufferedTurnDelivery(e.bufferedDeliveries),kind:`delivery`};for(;;){let{result:t,source:a}=await e.commandInbox.nextWithSource();if(e.commandInbox.consumeNext(),a===`authorization`)return t.done?{closed:!0,kind:`authorization`,payloads:[]}:{closed:!1,kind:`authorization`,payloads:t.value.kind===`deliver`?t.value.payloads:[]};if(t.done)return{delivery:null,kind:`delivery`};if(t.value.kind===`runtime-action-result`)continue;let o;try{o=sessionInboxWire.decode(t.value)}catch(e){if(!(e instanceof SessionInboxWireError))throw e;await reportDroppedWirePayloadStep({detail:e.message,family:`session-inbox`});continue}if(o.kind===`session-timeout`)return{kind:`expired`};if(o.kind===`clear`||o.kind===`compact`||o.kind===`reset`)return{kind:o.kind};if(o.kind===`cancel`){if(o.taskId!==void 0){e.cancelledTaskIds.add(o.taskId);let t=e.bufferedDeliveries.filter(t=>!isCancelledTaskDelivery(t,e.cancelledTaskIds));e.bufferedDeliveries.splice(0,e.bufferedDeliveries.length,...t)}continue}let s=o.taskDeliveryId??o.caller?.taskId;if(!(s!==void 0&&isCancelledTaskDeliveryId(s,e.cancelledTaskIds))){if(s!==void 0){if(e.seenTaskDeliveries.has(s))continue;e.seenTaskDeliveries.add(s)}if(e.deferDeliveries===!0){e.bufferedDeliveries.push(o);continue}return{delivery:o,kind:`delivery`}}}}function isCancelledTaskDelivery(e,t){let n=e.taskDeliveryId??e.caller?.taskId;return n!==void 0&&isCancelledTaskDeliveryId(n,t)}function isCancelledTaskDeliveryId(e,t){return[...t].some(t=>e===t||e.startsWith(`${t}:`))}function takeBufferedTurnDelivery(t){let n=t.shift();if(n===void 0)throw Error(`Cannot take a turn delivery from an empty buffer.`);let r=[n],i=n.caller;for(;t.length>0;){let e=t[0];if(e===void 0||n.taskDeliveryId!==void 0||e.taskDeliveryId!==void 0||i!==void 0&&e.caller!==void 0)break;let a=t.shift();if(a===void 0)throw Error(`Buffered turn delivery disappeared while partitioning.`);r.push(a),i??=a.caller}return coalesceDeliveries(r)}export{nextTurnDelivery};
@@ -1 +1 @@
1
- import{readDurableSession,replaceDurableSessionSnapshot}from"#execution/durable-session-store.js";import{resumeHook}from"#internal/workflow/runtime.js";import{createTaskInputRequestId,retireProxyInputRequests}from"#harness/proxy-input-requests.js";import{coalesceDeliverPayloads}from"#execution/deliver-payloads.js";import{routeDeliverPayload}from"#execution/subagent-hitl-proxy.js";import{sendTaskInboundPayload}from"#execution/tasks/parent/run-parent.js";import{findSessionTaskEntry}from"#tasks/session-index.js";async function routeProxiedDeliverStep(r){"use step";let l=await readDurableSession(r.sessionState),u=!(`delivery`in r),d=`delivery`in r?r.delivery:{auth:r.auth,kind:`deliver`,payloads:[r.payload]},f=new Map,p=new Map,m;for(let[e,t]of d.payloads.entries()){let n=routeDeliverPayload({allowRoute:(e,t)=>t.taskId===void 0||findSessionTaskEntry(l.state,t.taskId)!==void 0,payload:t,state:l.state});m??=n.parentAction,n.forSelf!==void 0&&f.set(e,n.forSelf);for(let[t,r]of n.forChildren.entries()){let i=r.taskId===void 0?r.childContinuationToken:[r.childContinuationToken,r.childResponseUrl??``,r.taskId].join(`\0`),a=p.get(i)??{childContinuationToken:r.childContinuationToken,childResponseUrl:r.childResponseUrl,metadata:[],payloads:[],retireRequestIds:[],sourcePayloadIndexes:[],taskId:r.taskId},o=a.payloads.length;if(a.payloads.push(r.payload),a.retireRequestIds.push(...r.retireRequestIds),a.sourcePayloadIndexes.push(e),n.forSelf===void 0&&t===0)for(let t of d.deliveryMetadata??[])t.payloadIndex===e&&a.metadata.push({...t,payloadIndex:o});p.set(i,a)}}let h=!1;for(let e of p.values()){let t=e.taskId;if(t!==void 0){let n=findSessionTaskEntry(l.state,t);if(n===void 0){mergeStrandedResponses(f,e,t);continue}if(await sendTaskInboundPayload({taskInboxToken:n.taskInboxToken,payload:{auth:d.auth,childContinuationToken:e.childContinuationToken,childResponseUrl:e.childResponseUrl,inputResponses:coalesceDeliverPayloads(e.payloads).inputResponses??[],kind:`input-response`,taskId:t}})===`unreachable`){mergeStrandedResponses(f,e,t);continue}l=retireProxyInputRequests(l,e.retireRequestIds),h=!0;continue}let r={...d,deliveryMetadata:e.metadata.length===0?void 0:e.metadata,payloads:e.payloads};await resumeHook(e.childContinuationToken,{...r,payload:coalesceDeliverPayloads(e.payloads)}),l=retireProxyInputRequests(l,e.retireRequestIds),h=!0}let g={serializedContext:r.serializedContext??{},sessionState:h?replaceDurableSessionSnapshot({session:l,state:r.sessionState}):r.sessionState};if(m!==void 0)return{...g,...m};let _=[...f].sort(([e],[t])=>e-t),v=_.flatMap(([e],t)=>(d.deliveryMetadata??[]).filter(t=>t.payloadIndex===e).map(e=>({...e,payloadIndex:t}))),y=_.length===0?void 0:u?coalesceDeliverPayloads(_.map(([,e])=>e)):{...d,deliveryMetadata:v.length===0?void 0:v,payloads:_.map(([,e])=>e)};return{...g,kind:`continue`,remainder:y}}function mergeStrandedResponses(e,t,n){for(let[i,a]of t.payloads.entries()){let o=t.sourcePayloadIndexes[i];if(o===void 0)continue;let s=(a.inputResponses??[]).map(e=>({...e,requestId:createTaskInputRequestId(n,e.requestId)}));if(s.length===0)continue;let c=e.get(o);e.set(o,{...c,inputResponses:[...c?.inputResponses??[],...s]})}}export{routeProxiedDeliverStep};
1
+ import{readDurableSession,replaceDurableSessionSnapshot}from"#execution/durable-session-store.js";import{createTaskInputRequestId,retireProxyInputRequests}from"#harness/proxy-input-requests.js";import{coalesceDeliverPayloads}from"#execution/deliver-payloads.js";import{routeDeliverPayload}from"#execution/subagent-hitl-proxy.js";import{sendTaskInboundPayload}from"#execution/tasks/parent/run-parent.js";import{resumeSessionInbox}from"#execution/wire/session-inbox-resume.js";import{findSessionTaskEntry}from"#tasks/session-index.js";async function routeProxiedDeliverStep(n){"use step";let l=await readDurableSession(n.sessionState),u=!(`delivery`in n),d=`delivery`in n?n.delivery:{auth:n.auth,kind:`deliver`,payloads:[n.payload]},f=new Map,p=new Map,m;for(let[e,t]of d.payloads.entries()){let n=routeDeliverPayload({allowRoute:(e,t)=>t.taskId===void 0||findSessionTaskEntry(l.state,t.taskId)!==void 0,payload:t,state:l.state});m??=n.parentAction,n.forSelf!==void 0&&f.set(e,n.forSelf);for(let[t,r]of n.forChildren.entries()){let i=r.taskId===void 0?r.childContinuationToken:[r.childContinuationToken,r.childResponseUrl??``,r.taskId].join(`\0`),a=p.get(i)??{childContinuationToken:r.childContinuationToken,childResponseUrl:r.childResponseUrl,metadata:[],payloads:[],retireRequestIds:[],sourcePayloadIndexes:[],taskId:r.taskId},o=a.payloads.length;if(a.payloads.push(r.payload),a.retireRequestIds.push(...r.retireRequestIds),a.sourcePayloadIndexes.push(e),n.forSelf===void 0&&t===0)for(let t of d.deliveryMetadata??[])t.payloadIndex===e&&a.metadata.push({...t,payloadIndex:o});p.set(i,a)}}let h=!1;for(let e of p.values()){let t=e.taskId;if(t!==void 0){let n=findSessionTaskEntry(l.state,t);if(n===void 0){mergeStrandedResponses(f,e,t);continue}if(await sendTaskInboundPayload({taskInboxToken:n.taskInboxToken,payload:{auth:d.auth,childContinuationToken:e.childContinuationToken,childResponseUrl:e.childResponseUrl,inputResponses:coalesceDeliverPayloads(e.payloads).inputResponses??[],kind:`input-response`,taskId:t}})===`unreachable`){mergeStrandedResponses(f,e,t);continue}l=retireProxyInputRequests(l,e.retireRequestIds),h=!0;continue}let n={...d,deliveryMetadata:e.metadata.length===0?void 0:e.metadata,payloads:e.payloads};await resumeSessionInbox(e.childContinuationToken,n),l=retireProxyInputRequests(l,e.retireRequestIds),h=!0}let g={serializedContext:n.serializedContext??{},sessionState:h?replaceDurableSessionSnapshot({session:l,state:n.sessionState}):n.sessionState};if(m!==void 0)return{...g,...m};let _=[...f].sort(([e],[t])=>e-t),v=_.flatMap(([e],t)=>(d.deliveryMetadata??[]).filter(t=>t.payloadIndex===e).map(e=>({...e,payloadIndex:t}))),y=_.length===0?void 0:u?coalesceDeliverPayloads(_.map(([,e])=>e)):{...d,deliveryMetadata:v.length===0?void 0:v,payloads:_.map(([,e])=>e)};return{...g,kind:`continue`,remainder:y}}function mergeStrandedResponses(e,t,r){for(let[i,a]of t.payloads.entries()){let o=t.sourcePayloadIndexes[i];if(o===void 0)continue;let s=(a.inputResponses??[]).map(e=>({...e,requestId:createTaskInputRequestId(r,e.requestId)}));if(s.length===0)continue;let c=e.get(o);e.set(o,{...c,inputResponses:[...c?.inputResponses??[],...s]})}}export{routeProxiedDeliverStep};
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Surfaces a durable payload dropped by a wire codec's decode.
3
+ *
4
+ * Workflow-context consumers cannot log directly — the logging module pulls
5
+ * Node builtins the workflow driver bundle must not contain — so the report
6
+ * crosses a step boundary. The recorded step also leaves a durable trace in
7
+ * the run's event log, which is the operator-visible half of the "drop
8
+ * loudly, never reinterpret" wire contract.
9
+ */
10
+ export declare function reportDroppedWirePayloadStep(input: {
11
+ readonly detail: string;
12
+ readonly family: string;
13
+ }): Promise<void>;
@@ -0,0 +1 @@
1
+ import{createLogger}from"#internal/logging.js";const log=createLogger(`execution.wire`);async function reportDroppedWirePayloadStep(e){"use step";log.error(`dropping undecodable wire payload`,{detail:e.detail,family:e.family})}export{reportDroppedWirePayloadStep};
@@ -1 +1 @@
1
- import{mkdir,readFile,writeFile}from"node:fs/promises";import{dirname}from"node:path";import{loadOptionalEnginePackage}from"#internal/application/optional-package-install.js";import{WORKSPACE_ROOT}from"#runtime/workspace/types.js";import{createFileBackedInternalSandboxSession,pathExists}from"#execution/sandbox/bindings/local-backend-utils.js";import{shellQuote}from"#execution/sandbox/shell-quote.js";import{buildSandboxSession}from"#execution/sandbox/session.js";import{adaptMultiplexedCommandToSandboxProcess}from"#execution/sandbox/multiplexed-command.js";let justBashModulePromise;async function loadJustBashModule(e){return justBashModulePromise??=loadOptionalEnginePackage({appRoot:e.appRoot,autoInstall:e.autoInstall,importModule:async()=>await import(`just-bash`),missingMessage:"The just-bash sandbox backend requires the `just-bash` package, which is not bundled with eve. Install it in your application (for example `pnpm add -D just-bash`), or use docker() / defaultSandbox() instead.",packageName:`just-bash`}).catch(e=>{throw justBashModulePromise=void 0,e}),await justBashModulePromise}async function createBashSandbox(t){let{ReadWriteFs:n,Sandbox:r}=await loadJustBashModule({appRoot:t.appRoot,autoInstall:t.autoInstall}),i=resolveLocalSandboxFilesystemRootPath(t.rootPath),a=resolveLocalSandboxMetadataPath(t.rootPath),o=await readLocalMetadata(a);await mkdir(i,{recursive:!0});let s=new n({allowSymlinks:!0,maxFileReadSize:2**53-1,root:i}),c=s;if(t.filesystem!==void 0)try{c=await t.filesystem({appRoot:t.appRoot,defaultFilesystem:s})}catch(e){throw Error(`Failed to create the custom just-bash filesystem.`,{cause:e})}await ensureLocalSandboxDirectories(c);let l=await r.create({cwd:WORKSPACE_ROOT,env:o?.env,fs:c,network:{dangerouslyAllowFullInternetAccess:!0}});return{async captureState(){return await writeLocalMetadata(a,{env:{...l.bashEnvInstance.getEnv()},version:1}),{rootPath:t.rootPath}},async dispose(){await l.stop()},async readFileBytes(e){let t;try{t=await c.readFileBuffer(e)}catch{return null}return Buffer.from(t)},async removePath(e){await c.rm(e.path,{force:e.force,recursive:e.recursive})},rootPath:t.rootPath,sessionKey:t.sessionKey,async spawn(e){if(e.abortSignal?.aborted)throw new DOMException(`The operation was aborted.`,`AbortError`);let t=e.workingDirectory===void 0?e.command:`( cd ${shellQuote(e.workingDirectory)} && ${e.command} )`;return adaptMultiplexedCommandToSandboxProcess({command:await l.runCommand({args:[t],cmd:`eval`,detached:!0,env:e.env,signal:e.abortSignal}),getOutput:e=>e.type})},async writeFiles(e){for(let t of e){let e=dirname(t.path);await c.mkdir(e,{recursive:!0}),await c.writeFile(t.path,t.content)}}}}async function justBashSetNetworkPolicyUnsupported(){throw Error(`setNetworkPolicy() is not supported on the just-bash sandbox backend. just-bash applies its network policy only at sandbox creation (no run-time update) and does not run git or other binaries. Use docker() for coarse egress control or vercel() / microsandbox() for credential brokering.`)}function createJustBashHandle(e,t){let n=buildSandboxSession(createFileBackedInternalSandboxSession({id:e.sessionKey,sandbox:e}),justBashSetNetworkPolicyUnsupported);return{session:n,useSessionFn:async()=>n,async captureState(){return{backendName:t,metadata:await e.captureState()??{},sessionKey:e.sessionKey}},async stop(){await e.dispose()},async shutdown(){await e.dispose()}}}function resolveLocalSandboxFilesystemRootPath(e){return`${e}/fs`}function resolveLocalSandboxMetadataPath(e){return`${e}/metadata.json`}async function ensureLocalSandboxDirectories(e){await e.mkdir(WORKSPACE_ROOT,{recursive:!0})}async function readLocalMetadata(e){if(!await pathExists(e))return null;let n=JSON.parse(await readFile(e,`utf8`));return n.version!==1||!isStringRecord(n.env)?null:{env:n.env,version:1}}async function writeLocalMetadata(t,r){await mkdir(dirname(t),{recursive:!0}),await writeFile(t,`${JSON.stringify(r,null,2)}\n`)}function isStringRecord(e){return typeof e==`object`&&!!e&&!Array.isArray(e)&&Object.values(e).every(e=>typeof e==`string`)}export{createBashSandbox,createJustBashHandle,justBashSetNetworkPolicyUnsupported};
1
+ import{mkdir,readFile,writeFile}from"node:fs/promises";import{dirname}from"node:path";import{loadOptionalEnginePackage}from"#internal/application/optional-package-install.js";import{WORKSPACE_ROOT}from"#runtime/workspace/types.js";import{createFileBackedInternalSandboxSession,pathExists}from"#execution/sandbox/bindings/local-backend-utils.js";import{shellQuote}from"#execution/sandbox/shell-quote.js";import{buildSandboxSession}from"#execution/sandbox/session.js";import{adaptMultiplexedCommandToSandboxProcess}from"#execution/sandbox/multiplexed-command.js";let justBashModulePromise;async function loadJustBashModule(e){return justBashModulePromise??=loadOptionalEnginePackage({appRoot:e.appRoot,autoInstall:e.autoInstall,importModule:async()=>await import(`just-bash`),missingMessage:"The just-bash sandbox backend requires the `just-bash` package, which is not bundled with eve. Install it in your application (for example `pnpm add -D just-bash`), or use docker() / defaultSandbox() instead.",packageName:`just-bash`}).catch(e=>{throw justBashModulePromise=void 0,e}),await justBashModulePromise}async function createBashSandbox(t){let n=await loadJustBashModule({appRoot:t.appRoot,autoInstall:t.autoInstall}),{ReadWriteFs:r,Sandbox:i}=n,a=resolveLocalSandboxFilesystemRootPath(t.rootPath),o=resolveLocalSandboxMetadataPath(t.rootPath),s=await readLocalMetadata(o);await mkdir(a,{recursive:!0});let c=new r({allowSymlinks:!0,maxFileReadSize:2**53-1,root:a}),l=c;if(t.filesystem!==void 0)try{l=await t.filesystem({appRoot:t.appRoot,defaultFilesystem:c,justBash:n})}catch(e){throw Error(`Failed to create the custom just-bash filesystem.`,{cause:e})}await ensureLocalSandboxDirectories(l);let u=await i.create({cwd:WORKSPACE_ROOT,env:s?.env,fs:l,network:{dangerouslyAllowFullInternetAccess:!0}});return{async captureState(){return await writeLocalMetadata(o,{env:{...u.bashEnvInstance.getEnv()},version:1}),{rootPath:t.rootPath}},async dispose(){await u.stop()},async readFileBytes(e){let t;try{t=await l.readFileBuffer(e)}catch{return null}return Buffer.from(t)},async removePath(e){await l.rm(e.path,{force:e.force,recursive:e.recursive})},rootPath:t.rootPath,sessionKey:t.sessionKey,async spawn(e){if(e.abortSignal?.aborted)throw new DOMException(`The operation was aborted.`,`AbortError`);let t=e.workingDirectory===void 0?e.command:`( cd ${shellQuote(e.workingDirectory)} && ${e.command} )`;return adaptMultiplexedCommandToSandboxProcess({command:await u.runCommand({args:[t],cmd:`eval`,detached:!0,env:e.env,signal:e.abortSignal}),getOutput:e=>e.type})},async writeFiles(e){for(let t of e){let e=dirname(t.path);await l.mkdir(e,{recursive:!0}),await l.writeFile(t.path,t.content)}}}}async function justBashSetNetworkPolicyUnsupported(){throw Error(`setNetworkPolicy() is not supported on the just-bash sandbox backend. just-bash applies its network policy only at sandbox creation (no run-time update) and does not run git or other binaries. Use docker() for coarse egress control or vercel() / microsandbox() for credential brokering.`)}function createJustBashHandle(e,t){let n=buildSandboxSession(createFileBackedInternalSandboxSession({id:e.sessionKey,sandbox:e}),justBashSetNetworkPolicyUnsupported);return{session:n,useSessionFn:async()=>n,async captureState(){return{backendName:t,metadata:await e.captureState()??{},sessionKey:e.sessionKey}},async stop(){await e.dispose()},async shutdown(){await e.dispose()}}}function resolveLocalSandboxFilesystemRootPath(e){return`${e}/fs`}function resolveLocalSandboxMetadataPath(e){return`${e}/metadata.json`}async function ensureLocalSandboxDirectories(e){await e.mkdir(WORKSPACE_ROOT,{recursive:!0})}async function readLocalMetadata(e){if(!await pathExists(e))return null;let n=JSON.parse(await readFile(e,`utf8`));return n.version!==1||!isStringRecord(n.env)?null:{env:n.env,version:1}}async function writeLocalMetadata(t,r){await mkdir(dirname(t),{recursive:!0}),await writeFile(t,`${JSON.stringify(r,null,2)}\n`)}function isStringRecord(e){return typeof e==`object`&&!!e&&!Array.isArray(e)&&Object.values(e).every(e=>typeof e==`string`)}export{createBashSandbox,createJustBashHandle,justBashSetNetworkPolicyUnsupported};
@@ -2,11 +2,9 @@ import type { DeliverHookPayload, RuntimeActionResultHookPayload, SessionCommand
2
2
  /**
3
3
  * Payloads accepted by a session driver's stable and channel aliases.
4
4
  *
5
- * `DeliverHookPayload` is the only delivery format producers persist. The
6
- * `send` member of `SessionCommand` stays accepted solely for payloads
7
- * persisted by eve 0.30.3–0.30.8, which wrote the command shape directly;
8
- * sessions are bounded by the 30-day default timeout, so the decode can be
9
- * dropped once runs created on those versions have aged out.
5
+ * This union is the hook's transport typing only; consumers interpret every
6
+ * payload through `sessionInboxWire.decode` in `execution/wire/session-inbox-wire.ts`,
7
+ * which owns the versioned wire schema and its legacy-shape fallbacks.
10
8
  */
11
9
  export type SessionInboxPayload = DeliverHookPayload | RuntimeActionResultHookPayload | SessionCommand | SessionTimeoutHookPayload;
12
10
  /** Which hook family produced an inbox read. */
@@ -1 +1 @@
1
- import{createHook}from"#compiled/@workflow/core/index.js";import{claimHookOwnership,disposeHook}from"#execution/hook-ownership.js";function createSessionCommandInbox(){let r,i,a,o=[],s=[],c=0,l=null,u,d,enqueue=e=>{s.push(e),s.sort((e,t)=>e.order-t.order),d?.(),d=void 0},arm=e=>{e.closed||e.pending||(e.pending=!0,e.resolved=void 0,(e.retired?Promise.resolve(e.hook).then(e=>({done:!1,value:e})):e.iterator.next()).then(t=>{let n={order:c++,result:t,state:e};e.resolved=n,e.enabled&&enqueue(n)},()=>{}))},enable=e=>{e.enabled=!0,e.resolved!==void 0&&enqueue(e.resolved)},createState=t=>{let n=createHook({token:t});return{closed:!1,enabled:!1,hook:n,iterator:n[Symbol.asyncIterator](),pending:!1,retired:!1}},states=()=>[r,i,a,...o].filter(e=>e!==void 0),nextRead=()=>{if(r===void 0)throw Error(`Cannot wait for session commands before claiming the stable inbox.`);if(l!==null)return l;let e=states();for(let t of e)arm(t);return e.every(e=>e.closed)?(u={order:c++,result:{done:!0,value:void 0},state:r},l=Promise.resolve(u.result),l):(l=(async()=>{for(;s.length===0;)await new Promise(e=>{d=e});let e=s.shift();return u=e,e.result})(),l)};return{async claimAuthorization(e){if(a!==void 0){if(a.hook.token===e)return;throw Error(`A session command inbox cannot change its authorization token.`)}let n=createState(e);await claimHookOwnership(n.hook),a=n},async claimStable(e){if(r!==void 0){if(r.hook.token===e)return;throw Error(`A session command inbox cannot change its stable token.`)}let n=createState(e);await claimHookOwnership(n.hook),enable(n),r=n},consumeNext(){if(u===void 0)throw Error(`Cannot consume a session command before it resolves.`);u.state.pending=!1,u.state.resolved=void 0,u.result.done&&(u.state.closed=!0),u=void 0,l=null},async dispose(){let e=[i,r,a].filter(e=>e!==void 0);i=void 0,r=void 0,a=void 0,await Promise.all(e.map(async e=>await disposeHook(e.hook)))},hasReadyAuthorization(){return a?.enabled!==!0||a.resolved===void 0?!1:u===void 0?s[0]?.state===a:u.state===a},next:nextRead,async nextWithSource(){return{result:await nextRead(),source:u!==void 0&&u.state===a?`authorization`:`session`}},setAuthorizationWindow(e){if(a===void 0){if(e)throw Error(`Cannot open the authorization window before claiming its hook.`);return}if(e){a.enabled||enable(a),u!==void 0&&u.state!==a&&a.resolved!==void 0&&a.resolved.order<u.order&&(enqueue(u),u=void 0,l=null),l!==null&&arm(a);return}a.enabled=!1;let t=s.findIndex(e=>e.state===a);t!==-1&&s.splice(t,1)},async rekeyContinuation(e){if(!e||i?.hook.token===e)return;let r=createState(e);if(i===void 0){await claimHookOwnership(r.hook),enable(r),i=r,l!==null&&arm(r);return}arm(r),await claimHookOwnership(r.hook),enable(r);let a=i;i=r,arm(a);try{await disposeHook(a.hook)}catch(e){i=void 0;try{await disposeHook(r.hook)}catch{}throw e}a.retired=!0,o.push(a)}}}export{createSessionCommandInbox};
1
+ import{createHook}from"#compiled/@workflow/core/index.js";import{claimHookOwnership,disposeHook}from"#execution/hook-ownership.js";import{SESSION_INBOX_WIRE_VERSION,SESSION_INBOX_WIRE_VERSION_METADATA_KEY}from"#execution/wire/session-inbox-contract.js";function createSessionCommandInbox(){let a,o,s,c=[],l=[],u=0,d=null,f,p,enqueue=e=>{l.push(e),l.sort((e,t)=>e.order-t.order),p?.(),p=void 0},arm=e=>{e.closed||e.pending||(e.pending=!0,e.resolved=void 0,(e.retired?Promise.resolve(e.hook).then(e=>({done:!1,value:e})):e.iterator.next()).then(t=>{let n={order:u++,result:t,state:e};e.resolved=n,e.enabled&&enqueue(n)},()=>{}))},enable=e=>{e.enabled=!0,e.resolved!==void 0&&enqueue(e.resolved)},createState=t=>{let n=createHook({metadata:{[SESSION_INBOX_WIRE_VERSION_METADATA_KEY]:SESSION_INBOX_WIRE_VERSION},token:t});return{closed:!1,enabled:!1,hook:n,iterator:n[Symbol.asyncIterator](),pending:!1,retired:!1}},states=()=>[a,o,s,...c].filter(e=>e!==void 0),nextRead=()=>{if(a===void 0)throw Error(`Cannot wait for session commands before claiming the stable inbox.`);if(d!==null)return d;let e=states();for(let t of e)arm(t);return e.every(e=>e.closed)?(f={order:u++,result:{done:!0,value:void 0},state:a},d=Promise.resolve(f.result),d):(d=(async()=>{for(;l.length===0;)await new Promise(e=>{p=e});let e=l.shift();return f=e,e.result})(),d)};return{async claimAuthorization(e){if(s!==void 0){if(s.hook.token===e)return;throw Error(`A session command inbox cannot change its authorization token.`)}let n=createState(e);await claimHookOwnership(n.hook),s=n},async claimStable(e){if(a!==void 0){if(a.hook.token===e)return;throw Error(`A session command inbox cannot change its stable token.`)}let n=createState(e);await claimHookOwnership(n.hook),enable(n),a=n},consumeNext(){if(f===void 0)throw Error(`Cannot consume a session command before it resolves.`);f.state.pending=!1,f.state.resolved=void 0,f.result.done&&(f.state.closed=!0),f=void 0,d=null},async dispose(){let e=[o,a,s].filter(e=>e!==void 0);o=void 0,a=void 0,s=void 0,await Promise.all(e.map(async e=>await disposeHook(e.hook)))},hasReadyAuthorization(){return s?.enabled!==!0||s.resolved===void 0?!1:f===void 0?l[0]?.state===s:f.state===s},next:nextRead,async nextWithSource(){return{result:await nextRead(),source:f!==void 0&&f.state===s?`authorization`:`session`}},setAuthorizationWindow(e){if(s===void 0){if(e)throw Error(`Cannot open the authorization window before claiming its hook.`);return}if(e){s.enabled||enable(s),f!==void 0&&f.state!==s&&s.resolved!==void 0&&s.resolved.order<f.order&&(enqueue(f),f=void 0,d=null),d!==null&&arm(s);return}s.enabled=!1;let t=l.findIndex(e=>e.state===s);t!==-1&&l.splice(t,1)},async rekeyContinuation(e){if(!e||o?.hook.token===e)return;let r=createState(e);if(o===void 0){await claimHookOwnership(r.hook),enable(r),o=r,d!==null&&arm(r);return}arm(r),await claimHookOwnership(r.hook),enable(r);let i=o;o=r,arm(i);try{await disposeHook(i.hook)}catch(e){o=void 0;try{await disposeHook(r.hook)}catch{}throw e}i.retired=!0,c.push(i)}}}export{createSessionCommandInbox};
@@ -1 +1 @@
1
- import{walkCauseChain}from"#shared/errors.js";import{sessionTimeoutWorkflowReference,startWorkflowPreferLatest}from"#execution/workflow-runtime.js";import{EntityConflictError,HookNotFoundError,RunExpiredError,WorkflowRunNotFoundError}from"#compiled/@workflow/errors/index.js";import{cancelRun,getWorld,resumeHook}from"#internal/workflow/runtime.js";async function startSessionTimeoutStep(e){"use step";return{runId:(await startWorkflowPreferLatest(sessionTimeoutWorkflowReference,[e])).runId}}async function signalSessionTimeoutStep(e){"use step";try{await resumeHook(e.token,{kind:`session-timeout`})}catch(e){if(!isInactiveTimeoutTarget(e))throw e}}async function cancelSessionTimeoutStep(e){"use step";try{await cancelRun(await getWorld(),e.runId,{cancelReason:`Session ended before its timeout`})}catch(e){if(!isInactiveTimeoutTarget(e))throw e}}function isInactiveTimeoutTarget(t){for(let n of walkCauseChain(t))if(HookNotFoundError.is(n)||WorkflowRunNotFoundError.is(n)||RunExpiredError.is(n)||EntityConflictError.is(n))return!0;return!1}export{cancelSessionTimeoutStep,signalSessionTimeoutStep,startSessionTimeoutStep};
1
+ import{walkCauseChain}from"#shared/errors.js";import{sessionTimeoutWorkflowReference,startWorkflowPreferLatest}from"#execution/workflow-runtime.js";import{EntityConflictError,HookNotFoundError,RunExpiredError,WorkflowRunNotFoundError}from"#compiled/@workflow/errors/index.js";import{cancelRun,getWorld}from"#internal/workflow/runtime.js";import{resumeSessionInbox}from"#execution/wire/session-inbox-resume.js";async function startSessionTimeoutStep(e){"use step";return{runId:(await startWorkflowPreferLatest(sessionTimeoutWorkflowReference,[e])).runId}}async function signalSessionTimeoutStep(e){"use step";try{await resumeSessionInbox(e.token,{kind:`session-timeout`})}catch(e){if(!isInactiveTimeoutTarget(e))throw e}}async function cancelSessionTimeoutStep(e){"use step";try{await cancelRun(await getWorld(),e.runId,{cancelReason:`Session ended before its timeout`})}catch(e){if(!isInactiveTimeoutTarget(e))throw e}}function isInactiveTimeoutTarget(t){for(let n of walkCauseChain(t))if(HookNotFoundError.is(n)||WorkflowRunNotFoundError.is(n)||RunExpiredError.is(n)||EntityConflictError.is(n))return!0;return!1}export{cancelSessionTimeoutStep,signalSessionTimeoutStep,startSessionTimeoutStep};
@@ -1 +1 @@
1
- import{createLogger}from"#internal/logging.js";import{resumeHook}from"#internal/workflow/runtime.js";import{getWritable}from"#compiled/@workflow/core/index.js";import{isTaskWorkflowTargetGone}from"#execution/tasks/workflow-target.js";import{TASK_VIEW_STREAM_NAMESPACE,isTerminalTaskStatus,taskAuthorizationRequestId}from"#tasks/types.js";const log=createLogger(`execution.tasks.run`);async function appendTaskViewStep(e){"use step";let t=getWritable({namespace:TASK_VIEW_STREAM_NAMESPACE}).getWriter();try{await t.write(e.view)}finally{t.releaseLock()}}async function wakeTaskAuthorizationParentStep(e){"use step";let n={callId:e.request.callId,childSessionId:e.request.childSessionId,event:e.request.event,kind:`subagent-authorization-event`,subagentName:e.request.subagentName},r=e.request.event.data,i={task:{authorizationEvents:[{hookPayload:n,taskId:e.taskId}]}};e.request.event.type===`authorization.required`&&(i.message=`Background task ${e.taskId} needs authorization.`);let a={kind:`send`,payload:i,taskDeliveryId:`${e.taskId}:authorization:${e.request.event.type}:${r.turnId}:${r.stepIndex}:${r.sequence}:${taskAuthorizationRequestId(e.request.event)}`};try{await resumeHook(e.token,a)}catch(e){if(isTaskWorkflowTargetGone(e))return;throw e}}async function wakeTaskParentStep(e){"use step";let n={message:formatTaskNotification(e.view)};isTerminalTaskStatus(e.view.status)&&(n.task={views:[e.view]});let r={kind:`send`,payload:n,taskDeliveryId:`${e.view.taskId}:ready:${e.view.status}`};try{await resumeHook(e.token,r)}catch(t){if(isTaskWorkflowTargetGone(t)){log.warn(`task wake target is gone; the parent session already ended`,{status:e.view.status,taskId:e.view.taskId});return}throw t}}async function wakeTaskUpdateParentStep(e){"use step";let n={kind:`send`,payload:{message:`Background task ${e.view.taskId} (${e.view.metadata.name}) update: ${e.update.message}`},taskDeliveryId:`${e.view.taskId}:update:${e.update.childTurnId}:${e.update.childStepIndex}:${e.update.callId}`};try{await resumeHook(e.token,n)}catch(e){if(isTaskWorkflowTargetGone(e))return;throw e}}async function wakeTaskInputRequestParentStep(e){"use step";let n={kind:`send`,payload:{task:{inputRequests:[{hookPayload:e.request,taskId:e.taskId}]}},taskDeliveryId:`${e.taskId}:input:${e.request.event.turnId}:${e.request.event.stepIndex}:${e.request.event.sequence}`};try{await resumeHook(e.token,n)}catch(e){if(isTaskWorkflowTargetGone(e))return;throw e}}async function deliverTaskInputResponsesStep(e){"use step";let n=new Set(e.requestIds),r={auth:e.answer.auth,kind:`send`,payload:{inputResponses:e.answer.inputResponses.filter(e=>n.has(e.requestId))},taskDeliveryId:`${e.answer.taskId}:${[...e.requestIds].sort().join(`,`)}`};try{if(e.answer.childResponseUrl!==void 0){let t=await fetch(e.answer.childResponseUrl,{body:JSON.stringify({inputResponses:r.payload.inputResponses}),headers:{"content-type":`application/json`},method:`POST`,redirect:`error`});if(t.status===404)return`unreachable`;if(!t.ok)throw Error(`Remote task input delivery failed with HTTP ${t.status}.`)}else await resumeHook(e.answer.childContinuationToken,r);return`delivered`}catch(t){if(isTaskWorkflowTargetGone(t))return log.warn(`task input answer target is gone; the child turn already ended`,{taskId:e.answer.taskId}),`unreachable`;throw t}}function formatTaskNotification(e){let t=`Background task ${e.taskId} (${e.metadata.name})`;return e.status===`input_required`?`${t} needs input. Use task_peek to inspect the outstanding requests.`:`${t} is ${e.status}. Use task_peek to read its output.`}export{appendTaskViewStep,deliverTaskInputResponsesStep,wakeTaskAuthorizationParentStep,wakeTaskInputRequestParentStep,wakeTaskParentStep,wakeTaskUpdateParentStep};
1
+ import{createLogger}from"#internal/logging.js";import{resumeSessionInbox}from"#execution/wire/session-inbox-resume.js";import{getWritable}from"#compiled/@workflow/core/index.js";import{isTaskWorkflowTargetGone}from"#execution/tasks/workflow-target.js";import{TASK_VIEW_STREAM_NAMESPACE,isTerminalTaskStatus,taskAuthorizationRequestId}from"#tasks/types.js";const log=createLogger(`execution.tasks.run`);async function appendTaskViewStep(e){"use step";let t=getWritable({namespace:TASK_VIEW_STREAM_NAMESPACE}).getWriter();try{await t.write(e.view)}finally{t.releaseLock()}}async function wakeTaskAuthorizationParentStep(e){"use step";let n={callId:e.request.callId,childSessionId:e.request.childSessionId,event:e.request.event,kind:`subagent-authorization-event`,subagentName:e.request.subagentName},r=e.request.event.data,i={task:{authorizationEvents:[{hookPayload:n,taskId:e.taskId}]}};e.request.event.type===`authorization.required`&&(i.message=`Background task ${e.taskId} needs authorization.`);let a={kind:`send`,payload:i,taskDeliveryId:`${e.taskId}:authorization:${e.request.event.type}:${r.turnId}:${r.stepIndex}:${r.sequence}:${taskAuthorizationRequestId(e.request.event)}`};try{await resumeSessionInbox(e.token,a)}catch(e){if(isTaskWorkflowTargetGone(e))return;throw e}}async function wakeTaskParentStep(e){"use step";let n={message:formatTaskNotification(e.view)};isTerminalTaskStatus(e.view.status)&&(n.task={views:[e.view]});let r={kind:`send`,payload:n,taskDeliveryId:`${e.view.taskId}:ready:${e.view.status}`};try{await resumeSessionInbox(e.token,r)}catch(t){if(isTaskWorkflowTargetGone(t)){log.warn(`task wake target is gone; the parent session already ended`,{status:e.view.status,taskId:e.view.taskId});return}throw t}}async function wakeTaskUpdateParentStep(e){"use step";let n={kind:`send`,payload:{message:`Background task ${e.view.taskId} (${e.view.metadata.name}) update: ${e.update.message}`},taskDeliveryId:`${e.view.taskId}:update:${e.update.childTurnId}:${e.update.childStepIndex}:${e.update.callId}`};try{await resumeSessionInbox(e.token,n)}catch(e){if(isTaskWorkflowTargetGone(e))return;throw e}}async function wakeTaskInputRequestParentStep(e){"use step";let n={kind:`send`,payload:{task:{inputRequests:[{hookPayload:e.request,taskId:e.taskId}]}},taskDeliveryId:`${e.taskId}:input:${e.request.event.turnId}:${e.request.event.stepIndex}:${e.request.event.sequence}`};try{await resumeSessionInbox(e.token,n)}catch(e){if(isTaskWorkflowTargetGone(e))return;throw e}}async function deliverTaskInputResponsesStep(e){"use step";let n=new Set(e.requestIds),r={auth:e.answer.auth,kind:`send`,payload:{inputResponses:e.answer.inputResponses.filter(e=>n.has(e.requestId))},taskDeliveryId:`${e.answer.taskId}:${[...e.requestIds].sort().join(`,`)}`};try{if(e.answer.childResponseUrl!==void 0){let t=await fetch(e.answer.childResponseUrl,{body:JSON.stringify({inputResponses:r.payload.inputResponses}),headers:{"content-type":`application/json`},method:`POST`,redirect:`error`});if(t.status===404)return`unreachable`;if(!t.ok)throw Error(`Remote task input delivery failed with HTTP ${t.status}.`)}else await resumeSessionInbox(e.answer.childContinuationToken,r);return`delivered`}catch(t){if(isTaskWorkflowTargetGone(t))return log.warn(`task input answer target is gone; the child turn already ended`,{taskId:e.answer.taskId}),`unreachable`;throw t}}function formatTaskNotification(e){let t=`Background task ${e.taskId} (${e.metadata.name})`;return e.status===`input_required`?`${t} needs input. Use task_peek to inspect the outstanding requests.`:`${t} is ${e.status}. Use task_peek to read its output.`}export{appendTaskViewStep,deliverTaskInputResponsesStep,wakeTaskAuthorizationParentStep,wakeTaskInputRequestParentStep,wakeTaskParentStep,wakeTaskUpdateParentStep};
@@ -1 +1 @@
1
- import{sendCommandToDelivery}from"#execution/session-command-wire.js";import{createHook}from"#compiled/@workflow/core/index.js";import{closeHookIterator,disposeHook}from"#execution/hook-ownership.js";import{turnCancellationHookToken}from"#execution/turn-cancellation-token.js";import{forwardTurnCancellationStep}from"#execution/forward-turn-cancellation-step.js";import{forwardTurnDeliveryStep}from"#execution/forward-turn-delivery-step.js";import{rebuildSerializableError}from"#execution/workflow-errors.js";var TurnControlReceiver=class{bufferedDeliveries;bufferedSessionControls;commandInbox;control;controlIterator;expectedTurnId;cancelledTaskIds;seenTaskDeliveries;pendingControl=null;constructor(e){this.bufferedDeliveries=e.bufferedDeliveries,this.bufferedSessionControls=e.bufferedSessionControls,this.cancelledTaskIds=e.cancelledTaskIds??new Set,this.commandInbox=e.commandInbox,this.seenTaskDeliveries=e.seenTaskDeliveries??new Set,this.control=createHook({token:e.token}),this.controlIterator=this.control[Symbol.asyncIterator](),this.expectedTurnId=e.expectedTurnId}get token(){return this.control.token}async dispose(){await closeHookIterator(this.controlIterator),await disposeHook(this.control)}async waitForAction(){for(;;){let e=await this.nextControlOrCommand();if(e.kind===`command`){let t=await this.handleSessionCommand(e.command);if(t!==void 0)return t;continue}let t=e.payload,n=this.readTerminalControl(t);if(n!==void 0)return n;if(t.kind===`turn-delivery-request`){let e=await this.serviceDeliveryRequest(t);if(e!==void 0)return e}}}async handleSessionCommand(t){if(t.kind===`deliver`){if(!this.acceptTaskDelivery(t))return;await this.bufferDelivery(t);return}if(t.kind===`send`){if(!this.acceptTaskDelivery(t))return;await this.bufferDelivery(sendCommandToDelivery(t));return}if(t.kind===`clear`||t.kind===`compact`){this.bufferedSessionControls.push(t.kind);return}if(t.kind===`session-timeout`){this.bufferedSessionControls.push(`expired`);return}if(t.kind!==`runtime-action-result`){if(t.kind===`cancel`){t.taskId!==void 0&&this.discardTaskDeliveries(t.taskId);let e=t.taskId!==void 0&&t.turnId!==void 0&&t.turnId!==this.expectedTurnId?void 0:t.turnId;await forwardTurnCancellationStep({payload:e===void 0?{}:{turnId:e},token:turnCancellationHookToken(this.control.token)});return}if(t.kind===`reset`){await forwardTurnCancellationStep({payload:{},token:turnCancellationHookToken(this.control.token)}),this.bufferedSessionControls.push(`reset`);return}return unsupportedSessionCommand(t)}}async bufferDelivery(e){this.bufferedDeliveries.push(e),!(e.turnPolicy!==`steer`||!deliveryHasMessage(e))&&await forwardTurnCancellationStep({payload:{},token:turnCancellationHookToken(this.control.token)})}bufferTurnDeliveries(e){e.bufferedDeliveries!==void 0&&this.bufferedDeliveries.unshift(...e.bufferedDeliveries.filter(e=>!this.shouldDiscard(e)))}consumeControl(){this.pendingControl=null}getControlPromise(){return this.pendingControl??=this.controlIterator.next(),this.pendingControl}async nextControlOrCommand(){let e=await Promise.race([this.getControlPromise().then(e=>({kind:`control`,value:e})),this.commandInbox.next().then(e=>({kind:`command`,value:e}))]);if(e.kind===`command`){if(e.value.done)throw Error(`Session command inbox closed before the active turn settled.`);return this.commandInbox.consumeNext(),{command:e.value.value,kind:`command`}}if(this.consumeControl(),e.value.done)throw Error(`Turn control hook closed before delivering a result.`);let t=e.value.value;if(t.kind===`turn-error`)throw rebuildSerializableError(t.error);return t.kind===`turn-continuation-token`?(await this.commandInbox.rekeyContinuation(t.continuationToken),await this.nextControlOrCommand()):{kind:`control`,payload:t}}readTerminalControl(e){if(e.kind===`turn-error`)throw rebuildSerializableError(e.error);if(e.kind===`turn-result`)return this.bufferTurnDeliveries(e),e.action}async serviceDeliveryRequest(t){await this.commandInbox.rekeyContinuation(t.continuationToken);let n=this.takeInputResponseDelivery();for(;n===void 0;){let r=await Promise.race([this.getControlPromise().then(e=>({kind:`control`,value:e})),this.commandInbox.next().then(e=>({kind:`command`,value:e}))]);if(r.kind===`control`){if(this.consumeControl(),r.value.done)throw Error(`Turn control hook closed during a delivery request.`);if(r.value.value.kind===`turn-continuation-token`){await this.commandInbox.rekeyContinuation(r.value.value.continuationToken);continue}let e=this.readTerminalControl(r.value.value);if(e!==void 0)return e;if(r.value.value.kind===`turn-delivery-cancelled`&&r.value.value.requestId===t.requestId)return;continue}if(r.value.done)throw Error(`Session command inbox closed during a turn delivery request.`);if(this.commandInbox.consumeNext(),r.value.value.kind===`deliver`){if(!this.acceptTaskDelivery(r.value.value))continue;deliveryHasMessage(r.value.value)?await this.bufferDelivery(r.value.value):n=r.value.value;continue}if(r.value.value.kind===`send`){if(!this.acceptTaskDelivery(r.value.value))continue;let t=sendCommandToDelivery(r.value.value);deliveryHasMessage(t)?await this.bufferDelivery(t):n=t;continue}let i=await this.handleSessionCommand(r.value.value);if(i!==void 0)return i}try{await forwardTurnDeliveryStep({inboxToken:t.inboxToken,payload:{delivery:n,kind:`driver-delivery`,requestId:t.requestId}})}catch(e){if(!(e instanceof Error&&e.name===`HookNotFoundError`))throw e}return await this.awaitForwardedDelivery(t.requestId,n)}takeInputResponseDelivery(){let e=this.bufferedDeliveries.findIndex(e=>!deliveryHasMessage(e));if(e!==-1)return this.bufferedDeliveries.splice(e,1)[0]}async awaitForwardedDelivery(e,t){for(;;){let n=await this.nextControlOrCommand();if(n.kind===`command`){let e=await this.handleSessionCommand(n.command);if(e!==void 0)return this.shouldDiscard(t)||this.bufferedDeliveries.unshift(t),e;continue}let r=n.payload;if(r.kind===`turn-delivery-accepted`){if(r.requestId===e)return;continue}if(r.kind===`turn-delivery-cancelled`&&r.requestId===e){this.shouldDiscard(t)||this.bufferedDeliveries.unshift(t);return}r.kind===`turn-result`&&(this.shouldDiscard(t)||this.bufferedDeliveries.unshift(t));let i=this.readTerminalControl(r);if(i!==void 0)return i}}acceptTaskDelivery(e){let t=e.taskDeliveryId??e.caller?.taskId;return t===void 0?!0:this.originatesFromCancelledTask(t)||this.seenTaskDeliveries.has(t)?!1:(this.seenTaskDeliveries.add(t),!0)}discardTaskDeliveries(e){this.cancelledTaskIds.add(e);let t=this.bufferedDeliveries.filter(e=>!this.shouldDiscard(e));this.bufferedDeliveries.splice(0,this.bufferedDeliveries.length,...t)}originatesFromCancelledTask(e){return[...this.cancelledTaskIds].some(t=>deliveryOriginatesFromTask(e,t))}shouldDiscard(e){let t=e.taskDeliveryId??e.caller?.taskId;return t!==void 0&&this.originatesFromCancelledTask(t)}};function deliveryOriginatesFromTask(e,t){return e===t||e.startsWith(`${t}:`)}function deliveryHasMessage(e){return e.payloads.some(e=>e.message!==void 0)}function unsupportedSessionCommand(e){throw Error(`Unsupported session command: ${JSON.stringify(e)}`)}export{TurnControlReceiver};
1
+ import{reportDroppedWirePayloadStep}from"#execution/report-dropped-wire-payload-step.js";import{SessionInboxWireError,sessionInboxWire}from"#execution/wire/session-inbox-wire.js";import{createHook}from"#compiled/@workflow/core/index.js";import{closeHookIterator,disposeHook}from"#execution/hook-ownership.js";import{turnCancellationHookToken}from"#execution/turn-cancellation-token.js";import{forwardTurnCancellationStep}from"#execution/forward-turn-cancellation-step.js";import{forwardTurnDeliveryStep}from"#execution/forward-turn-delivery-step.js";import{rebuildSerializableError}from"#execution/workflow-errors.js";var TurnControlReceiver=class{bufferedDeliveries;bufferedSessionControls;commandInbox;control;controlIterator;expectedTurnId;cancelledTaskIds;seenTaskDeliveries;pendingControl=null;constructor(e){this.bufferedDeliveries=e.bufferedDeliveries,this.bufferedSessionControls=e.bufferedSessionControls,this.cancelledTaskIds=e.cancelledTaskIds??new Set,this.commandInbox=e.commandInbox,this.seenTaskDeliveries=e.seenTaskDeliveries??new Set,this.control=createHook({token:e.token}),this.controlIterator=this.control[Symbol.asyncIterator](),this.expectedTurnId=e.expectedTurnId}get token(){return this.control.token}async dispose(){await closeHookIterator(this.controlIterator),await disposeHook(this.control)}async waitForAction(){for(;;){let e=await this.nextControlOrCommand();if(e.kind===`command`){let t=await this.handleSessionCommand(e.command);if(t!==void 0)return t;continue}let t=e.payload,n=this.readTerminalControl(t);if(n!==void 0)return n;if(t.kind===`turn-delivery-request`){let e=await this.serviceDeliveryRequest(t);if(e!==void 0)return e}}}async handleSessionCommand(e){if(e.kind===`deliver`){if(!this.acceptTaskDelivery(e))return;await this.bufferDelivery(e);return}if(e.kind===`clear`||e.kind===`compact`){this.bufferedSessionControls.push(e.kind);return}if(e.kind===`session-timeout`){this.bufferedSessionControls.push(`expired`);return}if(e.kind===`cancel`){e.taskId!==void 0&&this.discardTaskDeliveries(e.taskId);let t=e.taskId!==void 0&&e.turnId!==void 0&&e.turnId!==this.expectedTurnId?void 0:e.turnId;await forwardTurnCancellationStep({payload:t===void 0?{}:{turnId:t},token:turnCancellationHookToken(this.control.token)});return}if(e.kind===`reset`){await forwardTurnCancellationStep({payload:{},token:turnCancellationHookToken(this.control.token)}),this.bufferedSessionControls.push(`reset`);return}return unsupportedSessionCommand(e)}async bufferDelivery(e){this.bufferedDeliveries.push(e),!(e.turnPolicy!==`steer`||!deliveryHasMessage(e))&&await forwardTurnCancellationStep({payload:{},token:turnCancellationHookToken(this.control.token)})}bufferTurnDeliveries(e){e.bufferedDeliveries!==void 0&&this.bufferedDeliveries.unshift(...e.bufferedDeliveries.filter(e=>!this.shouldDiscard(e)))}consumeControl(){this.pendingControl=null}getControlPromise(){return this.pendingControl??=this.controlIterator.next(),this.pendingControl}async nextControlOrCommand(){let r=await Promise.race([this.getControlPromise().then(e=>({kind:`control`,value:e})),this.commandInbox.next().then(e=>({kind:`command`,value:e}))]);if(r.kind===`command`){if(r.value.done)throw Error(`Session command inbox closed before the active turn settled.`);if(this.commandInbox.consumeNext(),r.value.value.kind===`runtime-action-result`)return await this.nextControlOrCommand();try{return{command:sessionInboxWire.decode(r.value.value),kind:`command`}}catch(n){if(!(n instanceof SessionInboxWireError))throw n;return await reportDroppedWirePayloadStep({detail:n.message,family:`session-inbox`}),await this.nextControlOrCommand()}}if(this.consumeControl(),r.value.done)throw Error(`Turn control hook closed before delivering a result.`);let i=r.value.value;if(i.kind===`turn-error`)throw rebuildSerializableError(i.error);return i.kind===`turn-continuation-token`?(await this.commandInbox.rekeyContinuation(i.continuationToken),await this.nextControlOrCommand()):{kind:`control`,payload:i}}readTerminalControl(e){if(e.kind===`turn-error`)throw rebuildSerializableError(e.error);if(e.kind===`turn-result`)return this.bufferTurnDeliveries(e),e.action}async serviceDeliveryRequest(r){await this.commandInbox.rekeyContinuation(r.continuationToken);let i=this.takeInputResponseDelivery();for(;i===void 0;){let a=await Promise.race([this.getControlPromise().then(e=>({kind:`control`,value:e})),this.commandInbox.next().then(e=>({kind:`command`,value:e}))]);if(a.kind===`control`){if(this.consumeControl(),a.value.done)throw Error(`Turn control hook closed during a delivery request.`);if(a.value.value.kind===`turn-continuation-token`){await this.commandInbox.rekeyContinuation(a.value.value.continuationToken);continue}let e=this.readTerminalControl(a.value.value);if(e!==void 0)return e;if(a.value.value.kind===`turn-delivery-cancelled`&&a.value.value.requestId===r.requestId)return;continue}if(a.value.done)throw Error(`Session command inbox closed during a turn delivery request.`);if(this.commandInbox.consumeNext(),a.value.value.kind===`runtime-action-result`)continue;let o;try{o=sessionInboxWire.decode(a.value.value)}catch(n){if(!(n instanceof SessionInboxWireError))throw n;await reportDroppedWirePayloadStep({detail:n.message,family:`session-inbox`});continue}if(o.kind===`deliver`){if(!this.acceptTaskDelivery(o))continue;deliveryHasMessage(o)?await this.bufferDelivery(o):i=o;continue}let s=await this.handleSessionCommand(o);if(s!==void 0)return s}try{await forwardTurnDeliveryStep({inboxToken:r.inboxToken,payload:{delivery:i,kind:`driver-delivery`,requestId:r.requestId}})}catch(e){if(!(e instanceof Error&&e.name===`HookNotFoundError`))throw e}return await this.awaitForwardedDelivery(r.requestId,i)}takeInputResponseDelivery(){let e=this.bufferedDeliveries.findIndex(e=>!deliveryHasMessage(e));if(e!==-1)return this.bufferedDeliveries.splice(e,1)[0]}async awaitForwardedDelivery(e,t){for(;;){let n=await this.nextControlOrCommand();if(n.kind===`command`){let e=await this.handleSessionCommand(n.command);if(e!==void 0)return this.shouldDiscard(t)||this.bufferedDeliveries.unshift(t),e;continue}let r=n.payload;if(r.kind===`turn-delivery-accepted`){if(r.requestId===e)return;continue}if(r.kind===`turn-delivery-cancelled`&&r.requestId===e){this.shouldDiscard(t)||this.bufferedDeliveries.unshift(t);return}r.kind===`turn-result`&&(this.shouldDiscard(t)||this.bufferedDeliveries.unshift(t));let i=this.readTerminalControl(r);if(i!==void 0)return i}}acceptTaskDelivery(e){let t=e.taskDeliveryId??e.caller?.taskId;return t===void 0?!0:this.originatesFromCancelledTask(t)||this.seenTaskDeliveries.has(t)?!1:(this.seenTaskDeliveries.add(t),!0)}discardTaskDeliveries(e){this.cancelledTaskIds.add(e);let t=this.bufferedDeliveries.filter(e=>!this.shouldDiscard(e));this.bufferedDeliveries.splice(0,this.bufferedDeliveries.length,...t)}originatesFromCancelledTask(e){return[...this.cancelledTaskIds].some(t=>deliveryOriginatesFromTask(e,t))}shouldDiscard(e){let t=e.taskDeliveryId??e.caller?.taskId;return t!==void 0&&this.originatesFromCancelledTask(t)}};function deliveryOriginatesFromTask(e,t){return e===t||e.startsWith(`${t}:`)}function deliveryHasMessage(e){return e.payloads.some(e=>e.message!==void 0)}function unsupportedSessionCommand(e){throw Error(`Unsupported session command: ${JSON.stringify(e)}`)}export{TurnControlReceiver};
@@ -0,0 +1,24 @@
1
+ /** Every explicit session-inbox wire version still supported by producers. */
2
+ export declare const SESSION_INBOX_WIRE_VERSIONS: readonly [1];
3
+ export type SessionInboxWireVersion = (typeof SESSION_INBOX_WIRE_VERSIONS)[number];
4
+ /** Current persisted session-inbox wire version. */
5
+ export declare const SESSION_INBOX_WIRE_VERSION: 1;
6
+ /** Hook metadata field advertising the consumer's inbox wire capability. */
7
+ export declare const SESSION_INBOX_WIRE_VERSION_METADATA_KEY = "sessionInboxWireVersion";
8
+ /**
9
+ * The consumer wire selected before a producer persists a payload.
10
+ *
11
+ * Version 0 had two incompatible unversioned shapes, so its historical
12
+ * variants remain explicit rather than pretending they were one protocol.
13
+ */
14
+ export type SessionInboxWireTarget = {
15
+ readonly variant: "deliver" | "send";
16
+ readonly version: 0;
17
+ } | {
18
+ readonly version: SessionInboxWireVersion;
19
+ };
20
+ export declare function isSessionInboxWireVersion(value: unknown): value is SessionInboxWireVersion;
21
+ /** Raised when a session inbox value violates its versioned wire contract. */
22
+ export declare class SessionInboxWireError extends Error {
23
+ constructor(message: string);
24
+ }
@@ -0,0 +1 @@
1
+ const SESSION_INBOX_WIRE_VERSIONS=[1],SESSION_INBOX_WIRE_VERSION=SESSION_INBOX_WIRE_VERSIONS[SESSION_INBOX_WIRE_VERSIONS.length-1],SESSION_INBOX_WIRE_VERSION_METADATA_KEY=`sessionInboxWireVersion`;function isSessionInboxWireVersion(t){return SESSION_INBOX_WIRE_VERSIONS.some(e=>e===t)}var SessionInboxWireError=class extends Error{constructor(e){super(e),this.name=`SessionInboxWireError`}};export{SESSION_INBOX_WIRE_VERSION,SESSION_INBOX_WIRE_VERSIONS,SESSION_INBOX_WIRE_VERSION_METADATA_KEY,SessionInboxWireError,isSessionInboxWireVersion};
@@ -0,0 +1,23 @@
1
+ import type { DeliverHookPayload, SessionCommand, SessionTimeoutHookPayload } from "#channel/types.js";
2
+ import { type SessionInboxWireV1 } from "#execution/wire/session-inbox-wire.v1.js";
3
+ import { type SessionInboxWireTarget, type SessionInboxWireVersion } from "#execution/wire/session-inbox-contract.js";
4
+ type SessionInboxCommand = DeliverHookPayload | SessionCommand | SessionTimeoutHookPayload;
5
+ /** Current wire type consumed after migration. */
6
+ export type SessionInboxWire = SessionInboxWireV1;
7
+ type LegacySessionInboxWireTarget = Extract<SessionInboxWireTarget, {
8
+ readonly version: 0;
9
+ }>;
10
+ /** Encodes a command for the selected session-inbox consumer. */
11
+ declare function encode(command: SessionInboxCommand, target: {
12
+ readonly version: 1;
13
+ }): SessionInboxWireV1;
14
+ declare function encode(command: SessionInboxCommand, target: {
15
+ readonly version: SessionInboxWireVersion;
16
+ }): unknown;
17
+ declare function encode(command: SessionInboxCommand, target: LegacySessionInboxWireTarget): Record<string, unknown>;
18
+ declare function encode(command: SessionInboxCommand, target: SessionInboxWireTarget): SessionInboxWireV1 | Record<string, unknown>;
19
+ /** Server/step-safe producer facade. */
20
+ export declare const sessionInboxWire: {
21
+ readonly encode: typeof encode;
22
+ };
23
+ export {};
@@ -0,0 +1 @@
1
+ import{SessionInboxWireError,isSessionInboxWireVersion}from"#execution/wire/session-inbox-contract.js";import{encodeSessionCommandV1}from"#execution/wire/session-inbox-wire.v1.js";import{encodeSessionCommandV0}from"#execution/wire/session-inbox-wire.v0.js";const versionedEncoders={1:encodeSessionCommandV1};function encode(e,t){if(t.version===0)return encodeSessionCommandV0(encodeSessionCommandV1(e),t.variant);if(isSessionInboxWireVersion(t.version))return versionedEncoders[t.version](e);throw new SessionInboxWireError(`Cannot encode session inbox payload for unknown wire version ${JSON.stringify(t.version)}.`)}const sessionInboxWire={encode};export{sessionInboxWire};
@@ -0,0 +1,10 @@
1
+ import type { DeliverHookPayload, SessionCommand, SessionTimeoutHookPayload } from "#channel/types.js";
2
+ import { type SessionInboxWireTarget } from "#execution/wire/session-inbox-contract.js";
3
+ import { getHookByToken, resumeHook } from "#internal/workflow/runtime.js";
4
+ type ResumedSessionInboxHook = Awaited<ReturnType<typeof resumeHook>>;
5
+ /** Resolves the consumer contract, encodes for it, and resumes that exact hook. */
6
+ export declare function resumeSessionInbox(token: string, command: DeliverHookPayload | SessionCommand | SessionTimeoutHookPayload): Promise<ResumedSessionInboxHook>;
7
+ type SessionInboxHook = Awaited<ReturnType<typeof getHookByToken>>;
8
+ /** Selects the encoder understood by a persisted hook's consumer deployment. */
9
+ export declare function resolveSessionInboxWireTarget(hook: SessionInboxHook): Promise<SessionInboxWireTarget>;
10
+ export {};
@@ -0,0 +1 @@
1
+ import{sessionCommandHookToken}from"#execution/session-command-token.js";import{isObject}from"#shared/guards.js";import{HookNotFoundError}from"#compiled/@workflow/errors/index.js";import{getHookByToken,resumeHook}from"#internal/workflow/runtime.js";import{SESSION_INBOX_WIRE_VERSION_METADATA_KEY,SessionInboxWireError,isSessionInboxWireVersion}from"#execution/wire/session-inbox-contract.js";import{sessionInboxWire}from"#execution/wire/session-inbox-encoder.js";async function resumeSessionInbox(e,t){let n=await getHookByToken(e),i=await resolveSessionInboxWireTarget(n);return await resumeHook(n,sessionInboxWire.encode(t,i))}async function resolveSessionInboxWireTarget(r){let a=isObject(r.metadata)?r.metadata:void 0;if(a!==void 0&&SESSION_INBOX_WIRE_VERSION_METADATA_KEY in a){let e=a[SESSION_INBOX_WIRE_VERSION_METADATA_KEY];if(isSessionInboxWireVersion(e))return{version:e};throw new SessionInboxWireError(`Session inbox target declares unsupported wire version ${JSON.stringify(e)}.`)}let o=sessionCommandHookToken(r.runId);if(r.token===o)return{variant:`send`,version:0};try{let e=await getHookByToken(o);if(e.runId!==r.runId)throw new SessionInboxWireError(`Stable session inbox ${JSON.stringify(o)} belongs to run ${JSON.stringify(e.runId)}, expected ${JSON.stringify(r.runId)}.`);return{variant:`send`,version:0}}catch(e){if(HookNotFoundError.is(e))return{variant:`deliver`,version:0};throw e}}export{resolveSessionInboxWireTarget,resumeSessionInbox};
@@ -0,0 +1,29 @@
1
+ import type { DeliverHookPayload, SessionCommand, SessionTimeoutHookPayload } from "#channel/types.js";
2
+ /**
3
+ * The session inbox wire family: every payload persisted to a session's
4
+ * durable inbox hooks crosses through `sessionInboxWire.encode` /
5
+ * `sessionInboxWire.decode`.
6
+ *
7
+ * Historic migrations live in `session-inbox-wire.vN.ts` modules; the
8
+ * current schema and encoder live in the current version module. This file
9
+ * remains the dependency-free decoder facade reached by the workflow body.
10
+ *
11
+ * See research/session-inbox-wire-schema.md and issue #1765.
12
+ */
13
+ /** A persisted inbox payload normalized for consumption; `send` never survives decode. */
14
+ export type DecodedSessionInbox = DeliverHookPayload | SessionTimeoutHookPayload | Extract<SessionCommand, {
15
+ readonly kind: "cancel" | "clear" | "compact" | "reset";
16
+ }>;
17
+ export { SessionInboxWireError } from "#execution/wire/session-inbox-contract.js";
18
+ /**
19
+ * Decodes a persisted inbox payload or throws {@link SessionInboxWireError}.
20
+ *
21
+ * Unknown newer versions and shape mismatches both throw: a lost delivery
22
+ * with an operator-visible signal is the designed failure; a reinterpreted
23
+ * delivery is the bug this module exists to prevent.
24
+ */
25
+ declare function decode(value: unknown): DecodedSessionInbox;
26
+ /** Workflow-safe consumer facade. */
27
+ export declare const sessionInboxWire: {
28
+ readonly decode: typeof decode;
29
+ };
@@ -0,0 +1 @@
1
+ import{SESSION_INBOX_WIRE_VERSION,SessionInboxWireError,SessionInboxWireError as SessionInboxWireError$1}from"#execution/wire/session-inbox-contract.js";import{sessionInboxWireV0Migration}from"#execution/wire/session-inbox-wire.v0.js";import{runMigrationChain}from"#execution/durable-session-migrations/chain.js";const WIRE_LABEL=`session inbox payload`,sessionInboxMigrations=[sessionInboxWireV0Migration];function decode(t){let n;try{n=runMigrationChain({initialVersion:0,label:WIRE_LABEL,migrations:sessionInboxMigrations,targetVersion:SESSION_INBOX_WIRE_VERSION,value:t})}catch(e){throw new SessionInboxWireError$1(e instanceof Error?e.message:String(e))}let r=n;if(r.version!==SESSION_INBOX_WIRE_VERSION)throw new SessionInboxWireError$1(`${WIRE_LABEL} declares version ${JSON.stringify(r.version)}, expected ${SESSION_INBOX_WIRE_VERSION}.`);return normalizeWire(r)}const sessionInboxWire={decode};function normalizeWire(e){switch(e.kind){case`deliver`:return{auth:e.auth,caller:e.caller,deliveryMetadata:e.deliveryMetadata,kind:`deliver`,payloads:e.payloads,requestId:e.requestId,taskDeliveryId:e.taskDeliveryId,turnPolicy:e.turnPolicy};case`session-timeout`:return{kind:`session-timeout`};case`clear`:return{kind:`clear`};case`compact`:return{kind:`compact`};case`reset`:return{kind:`reset`,reason:e.reason};case`cancel`:return{kind:`cancel`,taskId:e.taskId,turnId:e.turnId};default:throw new SessionInboxWireError$1(`${WIRE_LABEL} has an unrecognized kind ${JSON.stringify(e.kind)}.`)}}export{SessionInboxWireError,sessionInboxWire};
@@ -0,0 +1,5 @@
1
+ import type { VersionMigration } from "#execution/durable-session-migrations/chain.js";
2
+ import type { SessionInboxWireV1 } from "#execution/wire/session-inbox-wire.v1.js";
3
+ export declare const sessionInboxWireV0Migration: VersionMigration;
4
+ /** Encodes the two incompatible shapes from the unversioned wire era. */
5
+ export declare function encodeSessionCommandV0(wire: SessionInboxWireV1, variant: "deliver" | "send"): Omit<SessionInboxWireV1, "version"> | Record<string, unknown>;
@@ -0,0 +1 @@
1
+ import{isObject}from"#shared/guards.js";function migrateSessionInboxWireV0(t){let n=t;if(n.kind===`send`)return migrateLegacySend(n);if(n.kind===`deliver`&&!(Array.isArray(n.payloads)&&n.payloads.every(isObject)))throw Error(`legacy deliver payload has no object-array payloads field.`);return{...n,version:1}}function migrateLegacySend(t){if(!isObject(t.payload))throw Error(`legacy send command has no object payload field.`);if(t.delivery!==void 0&&!isObject(t.delivery))throw Error(`legacy send command has a non-object delivery field.`);return{auth:t.auth,caller:t.caller,deliveryMetadata:t.delivery===void 0?void 0:[{...t.delivery,payloadIndex:0}],kind:`deliver`,payload:t.payload,payloads:[t.payload],requestId:t.requestId,taskDeliveryId:t.taskDeliveryId,turnPolicy:t.turnPolicy,version:1}}const sessionInboxWireV0Migration={from:0,migrate:migrateSessionInboxWireV0,to:1};function encodeSessionCommandV0(e,t){if(e.kind!==`deliver`){let{version:t,...n}=e;return n}if(t===`deliver`){let{payload:t,version:n,...r}=e;return r}let n=e.deliveryMetadata?.find(e=>e.payloadIndex===0),r;if(n!==void 0){let{payloadIndex:e,...t}=n;r=t}return{auth:e.auth,caller:e.caller,delivery:r,kind:`send`,payload:e.payload,requestId:e.requestId,taskDeliveryId:e.taskDeliveryId,turnPolicy:e.turnPolicy}}export{encodeSessionCommandV0,sessionInboxWireV0Migration};