eve 0.32.0 → 0.33.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (178) hide show
  1. package/CHANGELOG.md +13 -1
  2. package/README.md +8 -4
  3. package/dist/src/channel/channel-address.d.ts +4 -1
  4. package/dist/src/channel/channel-address.js +1 -1
  5. package/dist/src/channel/channel-operations.d.ts +3 -1
  6. package/dist/src/channel/compiled-channel.d.ts +2 -1
  7. package/dist/src/channel/cross-channel-receive.d.ts +5 -2
  8. package/dist/src/channel/cross-channel-receive.js +1 -1
  9. package/dist/src/channel/session.d.ts +6 -2
  10. package/dist/src/channel/session.js +1 -1
  11. package/dist/src/channel/types.d.ts +6 -0
  12. package/dist/src/channel/types.js +1 -1
  13. package/dist/src/chunks/{use-eve-agent-CX87G1vU.js → use-eve-agent-3oBnxzhV.js} +27 -17
  14. package/dist/src/chunks/{use-eve-agent-DwyRde1N.js → use-eve-agent-B-Hky2f4.js} +27 -17
  15. package/dist/src/cli/commands/agent-prompt/collect-intent.md +3 -0
  16. package/dist/src/cli/commands/agent-prompt/scaffold.md +4 -2
  17. package/dist/src/cli/commands/info.js +1 -1
  18. package/dist/src/cli/commands/init-repl.d.ts +1 -1
  19. package/dist/src/cli/commands/init-repl.js +1 -1
  20. package/dist/src/cli/commands/init.d.ts +7 -0
  21. package/dist/src/cli/commands/init.js +1 -1
  22. package/dist/src/cli/commands/integration-connect.d.ts +3 -3
  23. package/dist/src/cli/commands/integration-connect.js +1 -1
  24. package/dist/src/cli/commands/integration-setup.js +1 -1
  25. package/dist/src/cli/commands/set.d.ts +20 -0
  26. package/dist/src/cli/commands/set.js +1 -0
  27. package/dist/src/cli/dev/tui/runner.js +1 -1
  28. package/dist/src/cli/dev/tui/setup-issues.js +1 -1
  29. package/dist/src/cli/option-parsers.d.ts +3 -0
  30. package/dist/src/cli/option-parsers.js +1 -1
  31. package/dist/src/cli/run.js +1 -1
  32. package/dist/src/client/agent-info-schema.d.ts +28 -5
  33. package/dist/src/client/agent-info-schema.js +1 -1
  34. package/dist/src/client/session.js +1 -1
  35. package/dist/src/client/types.d.ts +3 -0
  36. package/dist/src/compiler/extension-compatibility.d.ts +19 -9
  37. package/dist/src/compiler/extension-compatibility.js +1 -1
  38. package/dist/src/compiler/manifest.d.ts +119 -19
  39. package/dist/src/compiler/manifest.js +1 -1
  40. package/dist/src/compiler/model-catalog.d.ts +2 -30
  41. package/dist/src/compiler/model-catalog.js +1 -1
  42. package/dist/src/compiler/module-map.d.ts +2 -2
  43. package/dist/src/compiler/module-map.js +2 -2
  44. package/dist/src/compiler/normalize-agent-config.js +1 -1
  45. package/dist/src/compiler/normalize-instructions.js +1 -1
  46. package/dist/src/compiler/normalize-manifest.js +2 -2
  47. package/dist/src/compiler/normalize-skill.js +1 -1
  48. package/dist/src/compiler/normalize-subagent.d.ts +5 -1
  49. package/dist/src/compiler/normalize-subagent.js +1 -1
  50. package/dist/src/compiler/remote-agent-node.d.ts +4 -1
  51. package/dist/src/compiler/workspace-resources.js +1 -1
  52. package/dist/src/context/dynamic-model-lifecycle.d.ts +7 -2
  53. package/dist/src/context/dynamic-model-lifecycle.js +1 -1
  54. package/dist/src/context/dynamic-subagent-lifecycle.js +1 -1
  55. package/dist/src/context/hook-lifecycle.js +1 -1
  56. package/dist/src/context/keys.d.ts +8 -0
  57. package/dist/src/context/keys.js +1 -1
  58. package/dist/src/evals/session.js +1 -1
  59. package/dist/src/execution/dispatch-runtime-actions-step.js +1 -1
  60. package/dist/src/execution/effective-agent-config.js +1 -1
  61. package/dist/src/execution/node-step.js +1 -1
  62. package/dist/src/execution/session-command-wire.js +1 -1
  63. package/dist/src/execution/session.d.ts +2 -0
  64. package/dist/src/execution/session.js +2 -2
  65. package/dist/src/execution/settle-cancelled-turn-step.js +1 -1
  66. package/dist/src/execution/turn-control-receiver.d.ts +2 -0
  67. package/dist/src/execution/turn-control-receiver.js +1 -1
  68. package/dist/src/execution/workflow-steps.js +1 -1
  69. package/dist/src/harness/emission.d.ts +1 -1
  70. package/dist/src/harness/emission.js +1 -1
  71. package/dist/src/harness/step-hooks.d.ts +1 -1
  72. package/dist/src/harness/step-hooks.js +1 -1
  73. package/dist/src/harness/tool-loop.d.ts +1 -1
  74. package/dist/src/harness/tool-loop.js +2 -2
  75. package/dist/src/harness/types.d.ts +11 -5
  76. package/dist/src/harness/types.js +1 -1
  77. package/dist/src/internal/application/package.js +1 -1
  78. package/dist/src/internal/authored-definition/core.js +1 -1
  79. package/dist/src/internal/authored-definition/schema-backed.js +1 -1
  80. package/dist/src/internal/authored-module-loader.js +1 -1
  81. package/dist/src/internal/authored-module-map-loader.js +1 -1
  82. package/dist/src/internal/model-catalog.d.ts +46 -0
  83. package/dist/src/internal/model-catalog.js +1 -0
  84. package/dist/src/internal/nitro/host/build-vercel-agent-summary.js +1 -1
  85. package/dist/src/internal/nitro/host/create-application-nitro.js +1 -1
  86. package/dist/src/internal/nitro/host/dev-host-fingerprint.js +1 -1
  87. package/dist/src/internal/nitro/routes/agent-info/build-agent-info-response-from-manifest.js +1 -1
  88. package/dist/src/internal/nitro/routes/agent-info/build-agent-info-response.d.ts +20 -10
  89. package/dist/src/internal/nitro/routes/agent-info/build-agent-info-response.js +1 -1
  90. package/dist/src/internal/nitro/routes/channel-dispatch.js +1 -1
  91. package/dist/src/internal/nitro/routes/info.js +1 -1
  92. package/dist/src/internal/vercel-agent-summary.d.ts +12 -3
  93. package/dist/src/internal/vercel-agent-summary.js +1 -1
  94. package/dist/src/protocol/message.d.ts +2 -2
  95. package/dist/src/protocol/message.js +1 -1
  96. package/dist/src/public/channels/chat-sdk/chatSdkChannel.d.ts +5 -5
  97. package/dist/src/public/channels/chat-sdk/chatSdkChannel.js +2 -2
  98. package/dist/src/public/channels/discord/discordChannel.d.ts +3 -1
  99. package/dist/src/public/channels/discord/discordChannel.js +1 -1
  100. package/dist/src/public/channels/eve.d.ts +3 -1
  101. package/dist/src/public/channels/eve.js +1 -1
  102. package/dist/src/public/channels/github/githubChannel.d.ts +3 -1
  103. package/dist/src/public/channels/github/githubChannel.js +1 -1
  104. package/dist/src/public/channels/index.d.ts +1 -1
  105. package/dist/src/public/channels/linear/linearChannel.d.ts +3 -1
  106. package/dist/src/public/channels/linear/linearChannel.js +1 -1
  107. package/dist/src/public/channels/photon/photonIMessageChannel.d.ts +3 -1
  108. package/dist/src/public/channels/photon/photonIMessageChannel.js +1 -1
  109. package/dist/src/public/channels/slack/slackChannel.d.ts +3 -1
  110. package/dist/src/public/channels/slack/slackChannel.js +1 -1
  111. package/dist/src/public/channels/teams/teamsChannel.d.ts +3 -1
  112. package/dist/src/public/channels/teams/teamsChannel.js +1 -1
  113. package/dist/src/public/channels/telegram/telegramChannel.d.ts +3 -1
  114. package/dist/src/public/channels/telegram/telegramChannel.js +1 -1
  115. package/dist/src/public/channels/twilio/twilioChannel.d.ts +3 -1
  116. package/dist/src/public/channels/twilio/twilioChannel.js +1 -1
  117. package/dist/src/public/definitions/agent.d.ts +5 -7
  118. package/dist/src/public/definitions/agent.js +1 -1
  119. package/dist/src/public/definitions/channel.d.ts +3 -1
  120. package/dist/src/public/definitions/channel.js +1 -1
  121. package/dist/src/public/definitions/tool.d.ts +1 -5
  122. package/dist/src/public/definitions/tool.js +1 -1
  123. package/dist/src/public/index.d.ts +1 -1
  124. package/dist/src/runtime/agent/bootstrap.d.ts +19 -6
  125. package/dist/src/runtime/agent/bootstrap.js +1 -1
  126. package/dist/src/runtime/agent/model-catalog.d.ts +10 -0
  127. package/dist/src/runtime/agent/model-catalog.js +1 -0
  128. package/dist/src/runtime/agent/resolve-model.d.ts +8 -4
  129. package/dist/src/runtime/agent/resolve-model.js +1 -1
  130. package/dist/src/runtime/framework-channels/index.js +1 -1
  131. package/dist/src/runtime/resolve-agent-graph.js +1 -1
  132. package/dist/src/runtime/resolve-agent.d.ts +2 -2
  133. package/dist/src/runtime/resolve-agent.js +1 -1
  134. package/dist/src/runtime/resolve-channel.js +1 -1
  135. package/dist/src/runtime/resolve-dynamic-subagent.d.ts +2 -5
  136. package/dist/src/runtime/subagents/dynamic-agent-config.d.ts +8 -7
  137. package/dist/src/runtime/subagents/dynamic-agent-config.js +1 -1
  138. package/dist/src/runtime/types.d.ts +11 -4
  139. package/dist/src/setup/flows/deploy.d.ts +5 -3
  140. package/dist/src/setup/flows/deploy.js +1 -1
  141. package/dist/src/setup/flows/ensure-vercel-project.d.ts +5 -1
  142. package/dist/src/setup/flows/ensure-vercel-project.js +1 -1
  143. package/dist/src/setup/flows/model-source-change.d.ts +1 -0
  144. package/dist/src/setup/flows/model-source-change.js +1 -1
  145. package/dist/src/setup/integrations/discord/setup.js +1 -1
  146. package/dist/src/setup/integrations/github/setup.js +1 -1
  147. package/dist/src/setup/integrations/linear/setup.js +1 -1
  148. package/dist/src/setup/integrations/photon/setup-flow.js +1 -1
  149. package/dist/src/setup/integrations/slack/setup.js +1 -1
  150. package/dist/src/setup/scaffold/create/add-to-project.d.ts +2 -0
  151. package/dist/src/setup/scaffold/create/add-to-project.js +1 -1
  152. package/dist/src/setup/scaffold/create/project.d.ts +3 -1
  153. package/dist/src/setup/scaffold/create/project.js +4 -4
  154. package/dist/src/shared/agent-definition.d.ts +23 -23
  155. package/dist/src/shared/agent-definition.js +1 -1
  156. package/dist/src/shared/channel-definition.d.ts +3 -1
  157. package/dist/src/shared/dynamic-tool-definition.d.ts +4 -10
  158. package/dist/src/shared/dynamic-tool-definition.js +1 -1
  159. package/dist/src/svelte/index.js +1 -1
  160. package/dist/src/svelte/use-eve-agent.js +1 -1
  161. package/dist/src/vue/index.js +1 -1
  162. package/dist/src/vue/use-eve-agent.js +1 -1
  163. package/docs/agent-config.md +30 -19
  164. package/docs/channels/chat-sdk.mdx +5 -5
  165. package/docs/channels/custom.mdx +20 -0
  166. package/docs/channels/discord.mdx +1 -0
  167. package/docs/channels/eve.mdx +2 -0
  168. package/docs/channels/github.mdx +1 -1
  169. package/docs/channels/linear.mdx +1 -1
  170. package/docs/channels/overview.mdx +19 -0
  171. package/docs/channels/photon.mdx +5 -2
  172. package/docs/channels/slack.mdx +5 -11
  173. package/docs/concepts/execution-model-and-durability.mdx +5 -8
  174. package/docs/concepts/sessions-runs-and-streaming.md +2 -2
  175. package/docs/guides/dynamic-capabilities.md +24 -20
  176. package/docs/installation.mdx +7 -1
  177. package/docs/reference/cli.md +33 -8
  178. package/package.json +1 -1
@@ -1 +1 @@
1
- import{markEventHandled}from"./utils.js";import{createLogger,logError}from"#internal/logging.js";import{POST,defineChannel}from"#public/definitions/channel.js";import{mergeUploadPolicy}from"#public/channels/upload-policy.js";import{buildSlackBinding,buildSlackWorkspaceHandle,slackContinuationToken}from"#public/channels/slack/api.js";import{buildSlackAuthContext,slackUserIdFromAuthContext}from"#public/channels/slack/auth.js";import{defaultEvents,defaultInputRequestedHandler,defaultOnAppMention,defaultOnDirectMessage}from"#public/channels/slack/defaults.js";import{loadThreadContextMessages}from"#public/channels/slack/thread.js";import{parseSlackWebhookBody}from"#compiled/@chat-adapter/slack/webhook.js";import{bindSlackSessionOperations}from"#public/channels/slack/session-operations.js";import{buildSlackTurnMessage,collectInboundFileParts,createSlackFetchFile}from"#public/channels/slack/attachments.js";import{parseMessageEvent,parseSlackEventEnvelope,slackEventBotUserId,slackMessageFromWebhookPayload}from"#public/channels/slack/inbound.js";import{formatSlackInboundMessage,formatSlackThreadContext}from"#public/channels/slack/model-context.js";import{SLACK_CHANNEL_DEFAULT_ROUTE}from"#public/channels/slack/constants.js";import{handleInteractionPost}from"#public/channels/slack/interactions.js";import{verifySlackRequest as verifySlackRequest$1}from"#public/channels/slack/verify.js";const log=createLogger(`slack.channel`);function rebuildSlackContext(e,t,n){let{thread:r,slack:i}=buildSlackBinding({botToken:n?.botToken,channelId:e.channelId??``,threadTs:e.threadTs??``,teamId:e.teamId??void 0,onThreadTsChanged(n){e.threadTs=n,e.channelId&&t.continuation?.rekey(slackContinuationToken(e.channelId,n))}});return{thread:r,slack:i,state:e}}function slackChannel(e={}){let t=mergeUploadPolicy(e.uploadPolicy),n=createSlackFetchFile({botToken:e.credentials?.botToken}),o=e.events?.[`authorization.required`],s=e.events?.[`turn.started`]??defaultEvents[`turn.started`],c={...defaultEvents,...e.events,async"turn.started"(e,t,n){let r=slackUserIdFromAuthContext(n.session.auth.current);r!==void 0&&(t.state.triggeringUserId=r),await s(e,t,n)},"input.requested":e.events?.[`input.requested`]??defaultInputRequestedHandler(),"authorization.required":o===void 0?defaultEvents[`authorization.required`]:constrainAuthorizationRequired(o)},l=new Set;return defineChannel({kindHint:`slack`,state:{channelId:null,threadTs:null,teamId:null,triggeringUserId:null,pendingToolCallMessage:null,lastReasoningTypingAtMs:null,lastReasoningTypingStatus:null,pendingAuthMessageTs:{}},fetchFile:n,metadata(e){return{channelId:e.channelId,teamId:e.teamId,threadTs:e.threadTs,triggeringUserId:e.triggeringUserId??null}},context(t,n){return rebuildSlackContext(t,n,e.credentials)},routes:[POST(e.route??SLACK_CHANNEL_DEFAULT_ROUTE,async(n,r)=>{let{waitUntil:i}=r,{from:a,resolveSession:o}=r,s=await verifyInbound(n,e.credentials);return s===null?new Response(`unauthorized`,{status:401}):shouldDropSlackHttpTimeoutRetry(n.headers)?new Response(`ok`):(n.headers.get(`content-type`)??``).includes(`application/x-www-form-urlencoded`)?handleInteractionPost(s,{from:a,resolveSession:o,waitUntil:i},{config:e}):handleEventPost({body:s,from:a,resolveSession:o,waitUntil:i,config:e,uploadPolicy:t,handledEvents:l,headers:n.headers})})],receive(t,{from:n}){return receiveOnSlack(t,{from:n,credentials:e.credentials})},events:c})}async function receiveOnSlack(e,t){let n=e.target,r=n.channelId;if(!r||typeof r!=`string`)throw Error(`slackChannel().receive requires target.channelId.`);let i=typeof n.threadTs==`string`?n.threadTs:``,a=n.initialMessage;if(a&&i.length>0)throw Error("slackChannel().receive: `threadTs` and `initialMessage` are mutually exclusive.");let s=i;if(a){let{thread:e}=buildSlackBinding({botToken:t.credentials?.botToken,channelId:r,threadTs:``,teamId:t.teamId}),n={card:a.card};a.fallbackText!==void 0&&(n.fallbackText=a.fallbackText),s=(await e.post(n)).id}let l=s||crypto.randomUUID();return t.from(slackContinuationToken(r,l)).send(e.message,{auth:e.auth,state:{channelId:r,threadTs:s||null,teamId:t.teamId??null,triggeringUserId:t.triggeringUserId??null}})}function constrainAuthorizationRequired(e){return(t,n,r)=>e(t,{postEphemeral:(e,t)=>n.thread.postEphemeral(e,t),postDirectMessage:(e,t)=>n.thread.postDirectMessage(e,t),state:n.state},r)}function shouldDropSlackHttpTimeoutRetry(e){return Number(e.get(`x-slack-retry-num`)??`0`)>=1&&e.get(`x-slack-retry-reason`)===`http_timeout`}async function handleEventPost(t){let{config:n}=t,r,i;try{r=parseSlackWebhookBody(t.body,{headers:t.headers}),i=parseSlackEventEnvelope(t.body)}catch(e){return log.warn(`inbound webhook body is not valid JSON`,{error:e}),new Response(`ok`)}if(r.kind===`url_verification`)return new Response(r.challenge,{status:200,headers:{"content-type":`text/plain`}});if(i===null)return new Response(`ok`);let a=typeof i.api_app_id==`string`?i.api_app_id:void 0,o=slackEventBotUserId(i),dispatch=null,s=null;if(r.kind===`app_mention`||r.kind===`direct_message`){let e=r.kind,i=slackMessageFromWebhookPayload(r);if(i!==null&&!isSelfAuthoredSlackMessage({appId:a,botUserId:o},i)){let dispatchMessageWith=r=>()=>dispatchSlackMessage({appId:a,botUserId:o,from:t.from,resolveSession:t.resolveSession,credentials:n.credentials,handler:r,kind:e,message:i,threadContext:n.threadContext,uploadPolicy:t.uploadPolicy}),r=(e===`app_mention`?n.onAppMention:n.onDirectMessage)??n.onMessage;r===void 0?s=dispatchMessageWith(e===`app_mention`?defaultOnAppMention:defaultOnDirectMessage):dispatch=()=>dispatchSlackMessage({appId:a,botUserId:o,from:t.from,resolveSession:t.resolveSession,credentials:n.credentials,handler:r,kind:e,message:i,threadContext:n.threadContext,uploadPolicy:t.uploadPolicy})}}if(dispatch===null&&n.onMessage!==void 0){let e=parseMessageEvent(i);e!==null&&!isSelfAuthoredSlackMessage({appId:a,botUserId:o},e)&&(o===void 0||!e.text.includes(`<@${o}`))&&(dispatch=()=>dispatchSlackMessage({appId:a,botUserId:o,from:t.from,resolveSession:t.resolveSession,credentials:n.credentials,handler:n.onMessage,kind:`channel_message`,message:e,threadContext:n.threadContext,uploadPolicy:t.uploadPolicy}))}let c=n.onEvent;if(dispatch===null&&c!==void 0&&(dispatch=()=>dispatchSlackEvent({from:t.from,resolveSession:t.resolveSession,credentials:n.credentials,envelope:i,handler:c})),dispatch??=s,dispatch===null)return new Response(`ok`);let l=i.event_id;if(l){if(t.handledEvents.has(l))return log.warn(`received a duplicate event`,{event_id:l,event_time:i.event_time,retry_num:r.retry?.num??`(null)`,retry_reason:r.retry?.reason??`(null)`}),new Response(`ok`);markEventHandled(l,t.handledEvents)}return t.waitUntil(dispatch()),new Response(`ok`)}function isSelfAuthoredSlackMessage(e,t){return e.botUserId!==void 0&&t.author?.userId===e.botUserId||e.appId!==void 0&&t.raw.app_id===e.appId}async function dispatchSlackMessage(e){let t=slackContinuationToken(e.message.channelId,e.message.threadTs),{thread:r,slack:i}=buildSlackBinding({appId:e.appId,botToken:e.credentials?.botToken,botUserId:e.botUserId,channelId:e.message.channelId,threadTs:e.message.threadTs,teamId:e.message.teamId}),a=e.message.author,s=bindSlackSessionOperations({address:t,defaultAuth:a===void 0?null:buildSlackAuthContext({channelId:e.message.channelId,fullName:a.fullName,isBot:a.isBot,teamId:e.message.teamId,threadTs:e.message.threadTs,userId:a.userId,userName:a.userName}),from:e.from,resolveSession:e.resolveSession,state:{channelId:e.message.channelId,teamId:e.message.teamId??null,threadTs:e.message.threadTs,triggeringUserId:a?.userId??null}}),u={...s,isBotMentioned:()=>e.kind===`app_mention`||e.botUserId!==void 0&&e.message.text.includes(`<@${e.botUserId}`),isSubscribed:async()=>await s.resolveSession()!==void 0,slack:i,thread:r},d;try{d=await e.handler(u,e.message)}catch(t){logError(log,`${e.kind} handler failed`,t,{channelId:e.message.channelId});return}d!=null&&await deliverSlackMessage({credentials:e.credentials,kind:e.kind,message:e.message,result:d,sessionOperations:s,thread:r,threadContext:e.threadContext,uploadPolicy:e.uploadPolicy})}async function dispatchSlackEvent(e){let t=e.envelope.event.team_id,r=typeof t==`string`?t:typeof e.envelope.team_id==`string`?e.envelope.team_id:void 0,i=[],sourceFor=t=>e.from(slackContinuationToken(t.channelId,t.threadTs)),a={cancel:({target:e,turnId:t})=>sourceFor(e).cancel({turnId:t}),clear:({target:e})=>sourceFor(e).clear(),compact:({target:e})=>sourceFor(e).compact(),envelope:e.envelope,reset:({reason:e,target:t})=>sourceFor(t).reset({reason:e}),resolveSession:({target:t})=>e.resolveSession(slackContinuationToken(t.channelId,t.threadTs)),respond:(e,{auth:t,target:n})=>sourceFor(n).respond(e,{auth:t}),send:(t,{auth:n,target:i})=>receiveOnSlack({auth:n,message:t,target:i},{from:e.from,credentials:e.credentials,teamId:r,...typeof e.envelope.event.user==`string`?{triggeringUserId:e.envelope.event.user}:{}}),slack:buildSlackWorkspaceHandle({botToken:e.credentials?.botToken,teamId:r}),waitUntil(e){i.push(e)}};try{await e.handler(a,e.envelope.event)}catch(t){logError(log,`event handler failed`,t,{eventId:e.envelope.event_id,eventType:e.envelope.event.type})}await Promise.allSettled(i)}async function verifyInbound(e,t){try{return await verifySlackRequest$1(e,{signingSecret:t?.signingSecret??(t?.webhookVerifier?void 0:process.env.SLACK_SIGNING_SECRET),webhookVerifier:t?.webhookVerifier})}catch(e){return log.warn(`slack inbound verification failed`,{error:e}),null}}async function deliverSlackMessage(e){let{message:t,thread:r}=e;try{let n=formatSlackThreadContext(e.threadContext===void 0?[]:await loadThreadContextMessages(r,t,e.threadContext)),i=await collectInboundFileParts({mention:t,thread:r,policy:e.uploadPolicy}),a=formatSlackInboundMessage({channelId:t.channelId,fullName:t.author?.fullName,teamId:t.teamId,threadTs:t.threadTs,userId:t.author?.userId??``,userName:t.author?.userName},t),o=buildSlackTurnMessage(n===void 0?a:`${n}\n\n${a}`,i),s=e.result.context??[],c=s.length===0?{auth:e.result.auth,title:t.markdown}:{auth:e.result.auth,context:s,title:t.markdown};await e.sessionOperations.send(o,c)}catch(r){logError(log,`${e.kind} delivery failed`,r,{channelId:t.channelId})}}export{constrainAuthorizationRequired,slackChannel};
1
+ import{markEventHandled}from"./utils.js";import{createLogger,logError}from"#internal/logging.js";import{POST,defineChannel}from"#public/definitions/channel.js";import{mergeUploadPolicy}from"#public/channels/upload-policy.js";import{buildSlackBinding,buildSlackWorkspaceHandle,slackContinuationToken}from"#public/channels/slack/api.js";import{buildSlackAuthContext,slackUserIdFromAuthContext}from"#public/channels/slack/auth.js";import{defaultEvents,defaultInputRequestedHandler,defaultOnAppMention,defaultOnDirectMessage}from"#public/channels/slack/defaults.js";import{loadThreadContextMessages}from"#public/channels/slack/thread.js";import{parseSlackWebhookBody}from"#compiled/@chat-adapter/slack/webhook.js";import{bindSlackSessionOperations}from"#public/channels/slack/session-operations.js";import{buildSlackTurnMessage,collectInboundFileParts,createSlackFetchFile}from"#public/channels/slack/attachments.js";import{parseMessageEvent,parseSlackEventEnvelope,slackEventBotUserId,slackMessageFromWebhookPayload}from"#public/channels/slack/inbound.js";import{formatSlackInboundMessage,formatSlackThreadContext}from"#public/channels/slack/model-context.js";import{SLACK_CHANNEL_DEFAULT_ROUTE}from"#public/channels/slack/constants.js";import{handleInteractionPost}from"#public/channels/slack/interactions.js";import{verifySlackRequest as verifySlackRequest$1}from"#public/channels/slack/verify.js";const log=createLogger(`slack.channel`);function rebuildSlackContext(e,t,n){let{thread:r,slack:i}=buildSlackBinding({botToken:n?.botToken,channelId:e.channelId??``,threadTs:e.threadTs??``,teamId:e.teamId??void 0,onThreadTsChanged(n){e.threadTs=n,e.channelId&&t.continuation?.rekey(slackContinuationToken(e.channelId,n))}});return{thread:r,slack:i,state:e}}function slackChannel(e={}){let t=mergeUploadPolicy(e.uploadPolicy),n=createSlackFetchFile({botToken:e.credentials?.botToken}),o=e.events?.[`authorization.required`],s=e.events?.[`turn.started`]??defaultEvents[`turn.started`],c={...defaultEvents,...e.events,async"turn.started"(e,t,n){let r=slackUserIdFromAuthContext(n.session.auth.current);r!==void 0&&(t.state.triggeringUserId=r),await s(e,t,n)},"input.requested":e.events?.[`input.requested`]??defaultInputRequestedHandler(),"authorization.required":o===void 0?defaultEvents[`authorization.required`]:constrainAuthorizationRequired(o)},l=new Set;return defineChannel({kindHint:`slack`,turnPolicy:e.turnPolicy,state:{channelId:null,threadTs:null,teamId:null,triggeringUserId:null,pendingToolCallMessage:null,lastReasoningTypingAtMs:null,lastReasoningTypingStatus:null,pendingAuthMessageTs:{}},fetchFile:n,metadata(e){return{channelId:e.channelId,teamId:e.teamId,threadTs:e.threadTs,triggeringUserId:e.triggeringUserId??null}},context(t,n){return rebuildSlackContext(t,n,e.credentials)},routes:[POST(e.route??SLACK_CHANNEL_DEFAULT_ROUTE,async(n,r)=>{let{waitUntil:i}=r,{from:a,resolveSession:o}=r,s=await verifyInbound(n,e.credentials);return s===null?new Response(`unauthorized`,{status:401}):shouldDropSlackHttpTimeoutRetry(n.headers)?new Response(`ok`):(n.headers.get(`content-type`)??``).includes(`application/x-www-form-urlencoded`)?handleInteractionPost(s,{from:a,resolveSession:o,waitUntil:i},{config:e}):handleEventPost({body:s,from:a,resolveSession:o,waitUntil:i,config:e,uploadPolicy:t,handledEvents:l,headers:n.headers})})],receive(t,{from:n}){return receiveOnSlack(t,{from:n,credentials:e.credentials})},events:c})}async function receiveOnSlack(e,t){let n=e.target,r=n.channelId;if(!r||typeof r!=`string`)throw Error(`slackChannel().receive requires target.channelId.`);let i=typeof n.threadTs==`string`?n.threadTs:``,a=n.initialMessage;if(a&&i.length>0)throw Error("slackChannel().receive: `threadTs` and `initialMessage` are mutually exclusive.");let s=i;if(a){let{thread:e}=buildSlackBinding({botToken:t.credentials?.botToken,channelId:r,threadTs:``,teamId:t.teamId}),n={card:a.card};a.fallbackText!==void 0&&(n.fallbackText=a.fallbackText),s=(await e.post(n)).id}let l=s||crypto.randomUUID();return t.from(slackContinuationToken(r,l)).send(e.message,{auth:e.auth,state:{channelId:r,threadTs:s||null,teamId:t.teamId??null,triggeringUserId:t.triggeringUserId??null}})}function constrainAuthorizationRequired(e){return(t,n,r)=>e(t,{postEphemeral:(e,t)=>n.thread.postEphemeral(e,t),postDirectMessage:(e,t)=>n.thread.postDirectMessage(e,t),state:n.state},r)}function shouldDropSlackHttpTimeoutRetry(e){return Number(e.get(`x-slack-retry-num`)??`0`)>=1&&e.get(`x-slack-retry-reason`)===`http_timeout`}async function handleEventPost(t){let{config:n}=t,r,i;try{r=parseSlackWebhookBody(t.body,{headers:t.headers}),i=parseSlackEventEnvelope(t.body)}catch(e){return log.warn(`inbound webhook body is not valid JSON`,{error:e}),new Response(`ok`)}if(r.kind===`url_verification`)return new Response(r.challenge,{status:200,headers:{"content-type":`text/plain`}});if(i===null)return new Response(`ok`);let a=typeof i.api_app_id==`string`?i.api_app_id:void 0,o=slackEventBotUserId(i),dispatch=null,s=null;if(r.kind===`app_mention`||r.kind===`direct_message`){let e=r.kind,i=slackMessageFromWebhookPayload(r);if(i!==null&&!isSelfAuthoredSlackMessage({appId:a,botUserId:o},i)){let dispatchMessageWith=r=>()=>dispatchSlackMessage({appId:a,botUserId:o,from:t.from,resolveSession:t.resolveSession,credentials:n.credentials,handler:r,kind:e,message:i,threadContext:n.threadContext,uploadPolicy:t.uploadPolicy}),r=(e===`app_mention`?n.onAppMention:n.onDirectMessage)??n.onMessage;r===void 0?s=dispatchMessageWith(e===`app_mention`?defaultOnAppMention:defaultOnDirectMessage):dispatch=()=>dispatchSlackMessage({appId:a,botUserId:o,from:t.from,resolveSession:t.resolveSession,credentials:n.credentials,handler:r,kind:e,message:i,threadContext:n.threadContext,uploadPolicy:t.uploadPolicy})}}if(dispatch===null&&n.onMessage!==void 0){let e=parseMessageEvent(i);e!==null&&!isSelfAuthoredSlackMessage({appId:a,botUserId:o},e)&&(o===void 0||!e.text.includes(`<@${o}`))&&(dispatch=()=>dispatchSlackMessage({appId:a,botUserId:o,from:t.from,resolveSession:t.resolveSession,credentials:n.credentials,handler:n.onMessage,kind:`channel_message`,message:e,threadContext:n.threadContext,uploadPolicy:t.uploadPolicy}))}let c=n.onEvent;if(dispatch===null&&c!==void 0&&(dispatch=()=>dispatchSlackEvent({from:t.from,resolveSession:t.resolveSession,credentials:n.credentials,envelope:i,handler:c})),dispatch??=s,dispatch===null)return new Response(`ok`);let l=i.event_id;if(l){if(t.handledEvents.has(l))return log.warn(`received a duplicate event`,{event_id:l,event_time:i.event_time,retry_num:r.retry?.num??`(null)`,retry_reason:r.retry?.reason??`(null)`}),new Response(`ok`);markEventHandled(l,t.handledEvents)}return t.waitUntil(dispatch()),new Response(`ok`)}function isSelfAuthoredSlackMessage(e,t){return e.botUserId!==void 0&&t.author?.userId===e.botUserId||e.appId!==void 0&&t.raw.app_id===e.appId}async function dispatchSlackMessage(e){let t=slackContinuationToken(e.message.channelId,e.message.threadTs),{thread:r,slack:i}=buildSlackBinding({appId:e.appId,botToken:e.credentials?.botToken,botUserId:e.botUserId,channelId:e.message.channelId,threadTs:e.message.threadTs,teamId:e.message.teamId}),a=e.message.author,s=bindSlackSessionOperations({address:t,defaultAuth:a===void 0?null:buildSlackAuthContext({channelId:e.message.channelId,fullName:a.fullName,isBot:a.isBot,teamId:e.message.teamId,threadTs:e.message.threadTs,userId:a.userId,userName:a.userName}),from:e.from,resolveSession:e.resolveSession,state:{channelId:e.message.channelId,teamId:e.message.teamId??null,threadTs:e.message.threadTs,triggeringUserId:a?.userId??null}}),u={...s,isBotMentioned:()=>e.kind===`app_mention`||e.botUserId!==void 0&&e.message.text.includes(`<@${e.botUserId}`),isSubscribed:async()=>await s.resolveSession()!==void 0,slack:i,thread:r},d;try{d=await e.handler(u,e.message)}catch(t){logError(log,`${e.kind} handler failed`,t,{channelId:e.message.channelId});return}d!=null&&await deliverSlackMessage({credentials:e.credentials,kind:e.kind,message:e.message,result:d,sessionOperations:s,thread:r,threadContext:e.threadContext,uploadPolicy:e.uploadPolicy})}async function dispatchSlackEvent(e){let t=e.envelope.event.team_id,r=typeof t==`string`?t:typeof e.envelope.team_id==`string`?e.envelope.team_id:void 0,i=[],sourceFor=t=>e.from(slackContinuationToken(t.channelId,t.threadTs)),a={cancel:({target:e,turnId:t})=>sourceFor(e).cancel({turnId:t}),clear:({target:e})=>sourceFor(e).clear(),compact:({target:e})=>sourceFor(e).compact(),envelope:e.envelope,reset:({reason:e,target:t})=>sourceFor(t).reset({reason:e}),resolveSession:({target:t})=>e.resolveSession(slackContinuationToken(t.channelId,t.threadTs)),respond:(e,{auth:t,target:n})=>sourceFor(n).respond(e,{auth:t}),send:(t,{auth:n,target:i})=>receiveOnSlack({auth:n,message:t,target:i},{from:e.from,credentials:e.credentials,teamId:r,...typeof e.envelope.event.user==`string`?{triggeringUserId:e.envelope.event.user}:{}}),slack:buildSlackWorkspaceHandle({botToken:e.credentials?.botToken,teamId:r}),waitUntil(e){i.push(e)}};try{await e.handler(a,e.envelope.event)}catch(t){logError(log,`event handler failed`,t,{eventId:e.envelope.event_id,eventType:e.envelope.event.type})}await Promise.allSettled(i)}async function verifyInbound(e,t){try{return await verifySlackRequest$1(e,{signingSecret:t?.signingSecret??(t?.webhookVerifier?void 0:process.env.SLACK_SIGNING_SECRET),webhookVerifier:t?.webhookVerifier})}catch(e){return log.warn(`slack inbound verification failed`,{error:e}),null}}async function deliverSlackMessage(e){let{message:t,thread:r}=e;try{let n=formatSlackThreadContext(e.threadContext===void 0?[]:await loadThreadContextMessages(r,t,e.threadContext)),i=await collectInboundFileParts({mention:t,thread:r,policy:e.uploadPolicy}),a=formatSlackInboundMessage({channelId:t.channelId,fullName:t.author?.fullName,teamId:t.teamId,threadTs:t.threadTs,userId:t.author?.userId??``,userName:t.author?.userName},t),o=buildSlackTurnMessage(n===void 0?a:`${n}\n\n${a}`,i),s=e.result.context??[],c=s.length===0?{auth:e.result.auth,title:t.markdown}:{auth:e.result.auth,context:s,title:t.markdown};await e.sessionOperations.send(o,c)}catch(r){logError(log,`${e.kind} delivery failed`,r,{channelId:t.channelId})}}export{constrainAuthorizationRequired,slackChannel};
@@ -1,5 +1,5 @@
1
1
  import type { TeamsInstrumentationMetadata } from "#public/channels/teams/index.js";
2
- import type { SessionAuthContext } from "#channel/types.js";
2
+ import type { SessionAuthContext, TurnPolicy } from "#channel/types.js";
3
3
  import type { SessionContext } from "#public/definitions/callback-context.js";
4
4
  import type { ChannelContinuationOps } from "#public/definitions/channel.js";
5
5
  import type { UnstampedMessageStreamEvent } from "#protocol/message.js";
@@ -126,6 +126,8 @@ export interface TeamsChannelConfig {
126
126
  readonly files?: TeamsFilesConfig;
127
127
  /** Override the default webhook route path (`/eve/v1/teams`). */
128
128
  readonly route?: string;
129
+ /** Policy for accepted messages that arrive while a turn is active. */
130
+ readonly turnPolicy?: TurnPolicy;
129
131
  /** Inbound message hook. Defaults to user-scoped auth and mention-gated dispatch outside personal chats. */
130
132
  onMessage?(ctx: TeamsInboundMessageContext, message: TeamsMessageActivity): TeamsInboundResultOrPromise;
131
133
  /** Authorizes HITL card submissions. Defaults to the submitting Teams user. */
@@ -1 +1 @@
1
- import{createLogger,logError}from"#internal/logging.js";import{readNonEmptyString}from"#shared/guards.js";import{parseJsonObject}from"#shared/json.js";import{POST,defineChannel}from"#public/definitions/channel.js";import{callTeamsConnectorApi,normalizeTeamsContinuationAddress,normalizeTeamsPostInput,replyToTeamsActivity,sendTeamsActivity,teamsContinuationToken,triggerTeamsTypingIndicator,updateTeamsActivity}from"#public/channels/teams/api.js";import{deriveTeamsInputResponses,isTeamsInputResponseActivity,readTeamsInputReplyToActivityId,teamsInvokeResponse}from"#public/channels/teams/hitl.js";import{formatTeamsContextBlock,parseTeamsActivity,teamsThreadRootActivityId}from"#public/channels/teams/inbound.js";import{buildTeamsTurnMessage,collectTeamsFileParts,createTeamsFetchFile,normalizeTeamsFilesPolicy}from"#public/channels/teams/attachments.js";import{defaultEvents,defaultOnMessage,defaultTeamsAuth,teamsMentionUser}from"#public/channels/teams/defaults.js";import{verifyTeamsRequest}from"#public/channels/teams/verify.js";const log=createLogger(`teams.channel`);function teamsChannel(e={}){let t=normalizeTeamsFilesPolicy(e.files),o=e.onMessage??defaultOnMessage,s=e.onInputResponse??(e.onMessage===void 0?defaultOnInputResponse:rejectInput),c={...defaultEvents,...e.events};return defineChannel({kindHint:`teams`,state:initialTeamsState(),fetchFile:createTeamsFetchFile(t),metadata:e=>({channelId:e.channelId,conversationType:e.conversationType,teamId:e.teamId}),context(t,n){return rebuildTeamsContext(t,n,e)},routes:[POST(e.route??`/eve/v1/teams`,async(n,{from:i,resolveSession:a,waitUntil:c})=>{let l=await verifyInbound(n,e.credentials);if(l===null)return new Response(`unauthorized`,{status:401});let u;try{u=parseJsonObject(JSON.parse(l))}catch(e){return log.warn(`inbound Teams body is not valid JSON`,{error:e}),teamsOk()}let d=parseTeamsActivity(u);return d===null?teamsOk():d.type===`message`?(c(isTeamsInputResponseActivity(d)?dispatchInputResponses({activity:d,config:e,from:i,onInputResponse:s}):dispatchMessage({activity:d,config:e,filesPolicy:t,onMessage:o,from:i,resolveSession:a})),teamsOk()):d.type===`invoke`?handleInvoke({activity:d,config:e,onInputResponse:s,waitUntil:c,from:i}):teamsOk()})],async receive(t,{from:r}){let i=t.target,a=readNonEmptyString(i.serviceUrl),o=readNonEmptyString(i.conversationId);if(!a||!o)throw Error(`teamsChannel().receive requires target.serviceUrl and target.conversationId.`);let s=readNonEmptyString(i.conversationType)??null,c=readNonEmptyString(i.replyToActivityId)??null,l=i.initialMessage;if(l!==void 0&&c!==null)throw Error("teamsChannel().receive: `replyToActivityId` and `initialMessage` are mutually exclusive.");let u={...initialTeamsState(),channelId:readNonEmptyString(i.channelId)??null,conversationId:o,conversationType:s,replyToActivityId:c,serviceUrl:a,teamId:readNonEmptyString(i.teamId)??null,tenantId:readNonEmptyString(i.tenantId)??null};if(l!==void 0){let t=await buildTeamsBinding({config:e,state:u}).thread.post(l);s!==`personal`&&t.id&&(c=t.id,u.replyToActivityId=t.id)}return r(teamsContinuationToken({conversationId:o,replyToActivityId:c,tenantId:u.tenantId})).send(t.message,{auth:t.auth,state:u})},events:c})}function rebuildTeamsContext(e,t,n){return{...buildTeamsBinding({config:n,session:t,state:e}),adaptiveCardVersion:n.adaptiveCardVersion??`1.5`,state:e}}function buildTeamsBinding(e){let n=buildTeamsHandle(e);return{teams:n,thread:{mentionUser:teamsMentionUser,post(e){return n.sendActivity(e)},async startTyping(){try{await n.startTyping()}catch(e){logError(log,`Teams typing indicator failed — swallowed`,e)}},update(e,t){return n.updateActivity(e,t)}}}}function buildTeamsHandle(e){let t=e.state,n=e.config.api,r=e.config.credentials;function requireAddress(){let e=t.conversationId??``,n=t.serviceUrl??``;if(!e||!n)throw Error(`teamsChannel: missing serviceUrl or conversationId for outbound message.`);return{conversationId:e,serviceUrl:n}}function anchor(n){if(!n.id||t.replyToActivityId||t.conversationType===`personal`)return;t.replyToActivityId=n.id;let r=t.conversationId;r&&e.session?.continuation?.rekey(teamsContinuationToken({conversationId:r,replyToActivityId:n.id,tenantId:t.tenantId}))}async function send(e){let i=requireAddress(),a=buildOutboundActivity(t,e),o=t.replyToActivityId===null?await sendTeamsActivity({...n,body:a,credentials:r,conversationId:i.conversationId,serviceUrl:i.serviceUrl}):await replyToTeamsActivity({...n,body:a,credentials:r,activityId:t.replyToActivityId,conversationId:i.conversationId,serviceUrl:i.serviceUrl});return anchor(o),o}return{channelId:t.channelId??void 0,conversationId:t.conversationId??``,conversationType:t.conversationType??void 0,replyToActivityId:t.replyToActivityId??void 0,serviceUrl:t.serviceUrl??``,teamId:t.teamId??void 0,tenantId:t.tenantId??void 0,request(e,t,i){let a=requireAddress();return callTeamsConnectorApi({...n,body:t,credentials:r,method:i?.method,path:e,serviceUrl:a.serviceUrl})},sendActivity:send,replyToActivity(e){let i=requireAddress(),a=t.replyToActivityId??``;if(!a)throw Error(`teamsChannel: missing reply activity id.`);return replyToTeamsActivity({...n,body:buildOutboundActivity(t,e),credentials:r,activityId:a,conversationId:i.conversationId,serviceUrl:i.serviceUrl})},updateActivity(e,i){let a=requireAddress();return updateTeamsActivity({...n,body:buildOutboundActivity(t,i),credentials:r,activityId:e,conversationId:a.conversationId,serviceUrl:a.serviceUrl})},async startTyping(){let e=requireAddress();await triggerTeamsTypingIndicator({...n,credentials:r,conversationId:e.conversationId,serviceUrl:e.serviceUrl})}}}async function verifyInbound(e,t){try{return await verifyTeamsRequest(e,{appId:t?.webhookVerifier?void 0:t?.appId,webhookVerifier:t?.webhookVerifier})}catch(e){return log.warn(`teams inbound verification failed`,{error:e}),null}}async function dispatchMessage(e){let t=stateFromActivity(e.activity),n=buildTeamsBinding({config:e.config,state:t}),r=stateToken(t),i={...n,isSubscribed:async()=>await e.resolveSession(r)!==void 0},a;try{a=await e.onMessage(i,e.activity)}catch(e){log.error(`Teams message handler failed`,{error:e});return}if(a==null)return;let o=collectTeamsFileParts(e.activity.attachments,e.filesPolicy),s=buildTeamsTurnMessage(e.activity.text,o),c={activityId:e.activity.id,channelId:e.activity.teamsChannelId,conversationId:e.activity.conversation.id,conversationType:e.activity.conversationType,scope:e.activity.scope,teamId:e.activity.teamId,tenantId:e.activity.tenantId,userId:e.activity.from.id,userName:e.activity.from.name},l=a.context??[];try{await e.from(r).send(s,{auth:a.auth,context:[formatTeamsContextBlock(c),...l],state:t})}catch(e){log.error(`Teams message delivery failed`,{error:e})}}async function handleInvoke(e){if(isTeamsInputResponseActivity(e.activity))return e.waitUntil(dispatchInputResponses({activity:e.activity,config:e.config,onInputResponse:e.onInputResponse,from:e.from})),Response.json(teamsInvokeResponse());if(e.config.onInvoke===void 0)return teamsOk();let t=buildTeamsBinding({config:e.config,state:stateFromActivity(e.activity)}),n=await e.config.onInvoke(t,e.activity);return n instanceof Response?n:n&&typeof n==`object`?Response.json(n):teamsOk()}async function dispatchInputResponses(e){let t=deriveTeamsInputResponses(e.activity);if(t.length===0)return;let n=stateFromActivity(e.activity),r=buildTeamsBinding({config:e.config,state:n}),i;try{i=await e.onInputResponse(r,e.activity)}catch(e){log.error(`Teams input response authorization failed`,{error:e});return}if(i!==null)try{await e.from(resolveInputContinuationToken(e.activity,n)).respond(t,{auth:i.auth})}catch(e){log.error(`Teams input response delivery failed`,{error:e})}}function stateFromActivity(e){let t=normalizeTeamsContinuationAddress({conversationId:e.conversation.id,replyToActivityId:teamsThreadRootActivityId(e)});return{bot:e.recipient,channelId:e.teamsChannelId??null,conversationId:e.conversation.id,conversationType:e.conversationType??e.scope,pendingAuthActivityId:null,replyToActivityId:t.replyToActivityId,serviceUrl:e.serviceUrl,teamId:e.teamId??null,tenantId:e.tenantId??null,triggeringUser:e.from}}function resolveInputContinuationToken(e,t){let n=readTeamsInputReplyToActivityId(e);return n===null?stateToken(t):teamsContinuationToken({conversationId:e.conversation.id,replyToActivityId:n,tenantId:e.tenantId})}function defaultOnInputResponse(e,t){return{auth:defaultTeamsAuth(t)}}function rejectInput(){return null}function initialTeamsState(){return{bot:null,channelId:null,conversationId:null,conversationType:null,pendingAuthActivityId:null,replyToActivityId:null,serviceUrl:null,teamId:null,tenantId:null,triggeringUser:null}}function stateToken(e){let t=e.conversationId??``;if(!t)throw Error(`teamsChannel: missing conversation id.`);return teamsContinuationToken({conversationId:t,replyToActivityId:e.replyToActivityId,tenantId:e.tenantId})}function buildOutboundActivity(e,t){if(typeof t!=`string`&&`type`in t&&t.type===`typing`)return t;let n=normalizeTeamsPostInput(t),r=mergeChannelData(e,n.channelData);return{...n,channelData:r,conversation:e.conversationId?{id:e.conversationId}:void 0,from:e.bot??void 0,replyToId:e.replyToActivityId??void 0,type:`message`}}function mergeChannelData(e,t){let n={...t};return e.tenantId&&(n.tenant={id:e.tenantId}),e.teamId&&(n.team={id:e.teamId}),e.channelId&&(n.channel={id:e.channelId}),Object.keys(n).length>0?parseJsonObject(n):void 0}function teamsOk(){return new Response(`ok`,{status:200})}export{teamsChannel};
1
+ import{createLogger,logError}from"#internal/logging.js";import{readNonEmptyString}from"#shared/guards.js";import{parseJsonObject}from"#shared/json.js";import{POST,defineChannel}from"#public/definitions/channel.js";import{callTeamsConnectorApi,normalizeTeamsContinuationAddress,normalizeTeamsPostInput,replyToTeamsActivity,sendTeamsActivity,teamsContinuationToken,triggerTeamsTypingIndicator,updateTeamsActivity}from"#public/channels/teams/api.js";import{deriveTeamsInputResponses,isTeamsInputResponseActivity,readTeamsInputReplyToActivityId,teamsInvokeResponse}from"#public/channels/teams/hitl.js";import{formatTeamsContextBlock,parseTeamsActivity,teamsThreadRootActivityId}from"#public/channels/teams/inbound.js";import{buildTeamsTurnMessage,collectTeamsFileParts,createTeamsFetchFile,normalizeTeamsFilesPolicy}from"#public/channels/teams/attachments.js";import{defaultEvents,defaultOnMessage,defaultTeamsAuth,teamsMentionUser}from"#public/channels/teams/defaults.js";import{verifyTeamsRequest}from"#public/channels/teams/verify.js";const log=createLogger(`teams.channel`);function teamsChannel(e={}){let t=normalizeTeamsFilesPolicy(e.files),o=e.onMessage??defaultOnMessage,s=e.onInputResponse??(e.onMessage===void 0?defaultOnInputResponse:rejectInput),c={...defaultEvents,...e.events};return defineChannel({kindHint:`teams`,turnPolicy:e.turnPolicy,state:initialTeamsState(),fetchFile:createTeamsFetchFile(t),metadata:e=>({channelId:e.channelId,conversationType:e.conversationType,teamId:e.teamId}),context(t,n){return rebuildTeamsContext(t,n,e)},routes:[POST(e.route??`/eve/v1/teams`,async(n,{from:i,resolveSession:a,waitUntil:c})=>{let l=await verifyInbound(n,e.credentials);if(l===null)return new Response(`unauthorized`,{status:401});let u;try{u=parseJsonObject(JSON.parse(l))}catch(e){return log.warn(`inbound Teams body is not valid JSON`,{error:e}),teamsOk()}let d=parseTeamsActivity(u);return d===null?teamsOk():d.type===`message`?(c(isTeamsInputResponseActivity(d)?dispatchInputResponses({activity:d,config:e,from:i,onInputResponse:s}):dispatchMessage({activity:d,config:e,filesPolicy:t,onMessage:o,from:i,resolveSession:a})),teamsOk()):d.type===`invoke`?handleInvoke({activity:d,config:e,onInputResponse:s,waitUntil:c,from:i}):teamsOk()})],async receive(t,{from:r}){let i=t.target,a=readNonEmptyString(i.serviceUrl),o=readNonEmptyString(i.conversationId);if(!a||!o)throw Error(`teamsChannel().receive requires target.serviceUrl and target.conversationId.`);let s=readNonEmptyString(i.conversationType)??null,c=readNonEmptyString(i.replyToActivityId)??null,l=i.initialMessage;if(l!==void 0&&c!==null)throw Error("teamsChannel().receive: `replyToActivityId` and `initialMessage` are mutually exclusive.");let u={...initialTeamsState(),channelId:readNonEmptyString(i.channelId)??null,conversationId:o,conversationType:s,replyToActivityId:c,serviceUrl:a,teamId:readNonEmptyString(i.teamId)??null,tenantId:readNonEmptyString(i.tenantId)??null};if(l!==void 0){let t=await buildTeamsBinding({config:e,state:u}).thread.post(l);s!==`personal`&&t.id&&(c=t.id,u.replyToActivityId=t.id)}return r(teamsContinuationToken({conversationId:o,replyToActivityId:c,tenantId:u.tenantId})).send(t.message,{auth:t.auth,state:u})},events:c})}function rebuildTeamsContext(e,t,n){return{...buildTeamsBinding({config:n,session:t,state:e}),adaptiveCardVersion:n.adaptiveCardVersion??`1.5`,state:e}}function buildTeamsBinding(e){let n=buildTeamsHandle(e);return{teams:n,thread:{mentionUser:teamsMentionUser,post(e){return n.sendActivity(e)},async startTyping(){try{await n.startTyping()}catch(e){logError(log,`Teams typing indicator failed — swallowed`,e)}},update(e,t){return n.updateActivity(e,t)}}}}function buildTeamsHandle(e){let t=e.state,n=e.config.api,r=e.config.credentials;function requireAddress(){let e=t.conversationId??``,n=t.serviceUrl??``;if(!e||!n)throw Error(`teamsChannel: missing serviceUrl or conversationId for outbound message.`);return{conversationId:e,serviceUrl:n}}function anchor(n){if(!n.id||t.replyToActivityId||t.conversationType===`personal`)return;t.replyToActivityId=n.id;let r=t.conversationId;r&&e.session?.continuation?.rekey(teamsContinuationToken({conversationId:r,replyToActivityId:n.id,tenantId:t.tenantId}))}async function send(e){let i=requireAddress(),a=buildOutboundActivity(t,e),o=t.replyToActivityId===null?await sendTeamsActivity({...n,body:a,credentials:r,conversationId:i.conversationId,serviceUrl:i.serviceUrl}):await replyToTeamsActivity({...n,body:a,credentials:r,activityId:t.replyToActivityId,conversationId:i.conversationId,serviceUrl:i.serviceUrl});return anchor(o),o}return{channelId:t.channelId??void 0,conversationId:t.conversationId??``,conversationType:t.conversationType??void 0,replyToActivityId:t.replyToActivityId??void 0,serviceUrl:t.serviceUrl??``,teamId:t.teamId??void 0,tenantId:t.tenantId??void 0,request(e,t,i){let a=requireAddress();return callTeamsConnectorApi({...n,body:t,credentials:r,method:i?.method,path:e,serviceUrl:a.serviceUrl})},sendActivity:send,replyToActivity(e){let i=requireAddress(),a=t.replyToActivityId??``;if(!a)throw Error(`teamsChannel: missing reply activity id.`);return replyToTeamsActivity({...n,body:buildOutboundActivity(t,e),credentials:r,activityId:a,conversationId:i.conversationId,serviceUrl:i.serviceUrl})},updateActivity(e,i){let a=requireAddress();return updateTeamsActivity({...n,body:buildOutboundActivity(t,i),credentials:r,activityId:e,conversationId:a.conversationId,serviceUrl:a.serviceUrl})},async startTyping(){let e=requireAddress();await triggerTeamsTypingIndicator({...n,credentials:r,conversationId:e.conversationId,serviceUrl:e.serviceUrl})}}}async function verifyInbound(e,t){try{return await verifyTeamsRequest(e,{appId:t?.webhookVerifier?void 0:t?.appId,webhookVerifier:t?.webhookVerifier})}catch(e){return log.warn(`teams inbound verification failed`,{error:e}),null}}async function dispatchMessage(e){let t=stateFromActivity(e.activity),n=buildTeamsBinding({config:e.config,state:t}),r=stateToken(t),i={...n,isSubscribed:async()=>await e.resolveSession(r)!==void 0},a;try{a=await e.onMessage(i,e.activity)}catch(e){log.error(`Teams message handler failed`,{error:e});return}if(a==null)return;let o=collectTeamsFileParts(e.activity.attachments,e.filesPolicy),s=buildTeamsTurnMessage(e.activity.text,o),c={activityId:e.activity.id,channelId:e.activity.teamsChannelId,conversationId:e.activity.conversation.id,conversationType:e.activity.conversationType,scope:e.activity.scope,teamId:e.activity.teamId,tenantId:e.activity.tenantId,userId:e.activity.from.id,userName:e.activity.from.name},l=a.context??[];try{await e.from(r).send(s,{auth:a.auth,context:[formatTeamsContextBlock(c),...l],state:t})}catch(e){log.error(`Teams message delivery failed`,{error:e})}}async function handleInvoke(e){if(isTeamsInputResponseActivity(e.activity))return e.waitUntil(dispatchInputResponses({activity:e.activity,config:e.config,onInputResponse:e.onInputResponse,from:e.from})),Response.json(teamsInvokeResponse());if(e.config.onInvoke===void 0)return teamsOk();let t=buildTeamsBinding({config:e.config,state:stateFromActivity(e.activity)}),n=await e.config.onInvoke(t,e.activity);return n instanceof Response?n:n&&typeof n==`object`?Response.json(n):teamsOk()}async function dispatchInputResponses(e){let t=deriveTeamsInputResponses(e.activity);if(t.length===0)return;let n=stateFromActivity(e.activity),r=buildTeamsBinding({config:e.config,state:n}),i;try{i=await e.onInputResponse(r,e.activity)}catch(e){log.error(`Teams input response authorization failed`,{error:e});return}if(i!==null)try{await e.from(resolveInputContinuationToken(e.activity,n)).respond(t,{auth:i.auth})}catch(e){log.error(`Teams input response delivery failed`,{error:e})}}function stateFromActivity(e){let t=normalizeTeamsContinuationAddress({conversationId:e.conversation.id,replyToActivityId:teamsThreadRootActivityId(e)});return{bot:e.recipient,channelId:e.teamsChannelId??null,conversationId:e.conversation.id,conversationType:e.conversationType??e.scope,pendingAuthActivityId:null,replyToActivityId:t.replyToActivityId,serviceUrl:e.serviceUrl,teamId:e.teamId??null,tenantId:e.tenantId??null,triggeringUser:e.from}}function resolveInputContinuationToken(e,t){let n=readTeamsInputReplyToActivityId(e);return n===null?stateToken(t):teamsContinuationToken({conversationId:e.conversation.id,replyToActivityId:n,tenantId:e.tenantId})}function defaultOnInputResponse(e,t){return{auth:defaultTeamsAuth(t)}}function rejectInput(){return null}function initialTeamsState(){return{bot:null,channelId:null,conversationId:null,conversationType:null,pendingAuthActivityId:null,replyToActivityId:null,serviceUrl:null,teamId:null,tenantId:null,triggeringUser:null}}function stateToken(e){let t=e.conversationId??``;if(!t)throw Error(`teamsChannel: missing conversation id.`);return teamsContinuationToken({conversationId:t,replyToActivityId:e.replyToActivityId,tenantId:e.tenantId})}function buildOutboundActivity(e,t){if(typeof t!=`string`&&`type`in t&&t.type===`typing`)return t;let n=normalizeTeamsPostInput(t),r=mergeChannelData(e,n.channelData);return{...n,channelData:r,conversation:e.conversationId?{id:e.conversationId}:void 0,from:e.bot??void 0,replyToId:e.replyToActivityId??void 0,type:`message`}}function mergeChannelData(e,t){let n={...t};return e.tenantId&&(n.tenant={id:e.tenantId}),e.teamId&&(n.team={id:e.teamId}),e.channelId&&(n.channel={id:e.channelId}),Object.keys(n).length>0?parseJsonObject(n):void 0}function teamsOk(){return new Response(`ok`,{status:200})}export{teamsChannel};
@@ -1,5 +1,5 @@
1
1
  import type { TelegramInstrumentationMetadata } from "#public/channels/telegram/index.js";
2
- import type { SessionAuthContext } from "#channel/types.js";
2
+ import type { SessionAuthContext, TurnPolicy } from "#channel/types.js";
3
3
  import type { SessionContext } from "#public/definitions/callback-context.js";
4
4
  import type { ChannelContinuationOps } from "#public/definitions/channel.js";
5
5
  import type { UnstampedMessageStreamEvent } from "#protocol/message.js";
@@ -97,6 +97,8 @@ export interface TelegramChannelConfig {
97
97
  readonly onMessage?: (ctx: TelegramContext, message: TelegramMessage) => TelegramInboundResultOrPromise;
98
98
  /** Override the default webhook route path (`/eve/v1/telegram`). */
99
99
  readonly route?: string;
100
+ /** Policy for accepted messages that arrive while a turn is active. */
101
+ readonly turnPolicy?: TurnPolicy;
100
102
  /** Inbound upload policy for Telegram photos and documents. */
101
103
  readonly uploadPolicy?: UploadPolicyInput;
102
104
  }
@@ -1 +1 @@
1
- import{createLogger,logError}from"#internal/logging.js";import{isCompiledChannel}from"#channel/compiled-channel.js";import{defaultDeliverResult}from"#channel/adapter.js";import{parseJsonObject}from"#shared/json.js";import{POST,defineChannel}from"#public/definitions/channel.js";import{mergeUploadPolicy}from"#public/channels/upload-policy.js";import{formatTelegramContextBlock,parseTelegramUpdate}from"#public/channels/telegram/inbound.js";import{answerTelegramCallbackQuery,callTelegramApi,editTelegramMessageReplyMarkup,sendTelegramChatAction,sendTelegramMessage,splitTelegramMessageText,telegramContinuationToken}from"#public/channels/telegram/api.js";import{TELEGRAM_HITL_CALLBACK_PREFIX,isTelegramSyntheticResponse,resolveTelegramInputResponses,telegramCallbackInputResponse,telegramReplyInputResponse}from"#public/channels/telegram/hitl.js";import{buildTelegramTurnMessage,collectTelegramFileParts,createTelegramFetchFile}from"#public/channels/telegram/attachments.js";import{defaultEvents,defaultOnMessage}from"#public/channels/telegram/defaults.js";import{verifyTelegramRequest}from"#public/channels/telegram/verify.js";const log=createLogger(`telegram.channel`);function telegramChannel(e={}){let t=mergeUploadPolicy(e.uploadPolicy),n=e.onMessage??defaultOnMessage,r={...defaultEvents,...e.events},c=defineChannel({kindHint:`telegram`,state:initialTelegramState(e.botUsername),metadata:e=>({chatId:e.chatId,chatType:e.chatType,triggeringUserId:e.triggeringUserId??null}),fetchFile:createTelegramFetchFile({api:e.api,credentials:e.credentials,policy:t}),context(t,n){return rebuildTelegramContext(t,n,e)},routes:[POST(e.route??`/eve/v1/telegram`,async(r,{from:a,waitUntil:o})=>{let s=await verifyInbound(r,e.credentials);if(s===null)return new Response(`unauthorized`,{status:401});let c;try{c=parseJsonObject(JSON.parse(s))}catch(e){return log.warn(`inbound Telegram body is not valid JSON`,{error:e}),new Response(`ok`)}let u=parseTelegramUpdate(c);return u===null?new Response(`ok`):u.kind===`message`?(o(dispatchMessage({config:e,message:u.message,onMessage:n,uploadPolicy:t,from:a})),new Response(`ok`)):(o(dispatchCallbackQuery({config:e,query:u.callbackQuery,from:a})),new Response(`ok`))})],async receive(t,{from:n}){let r=t.target,i=readChatId(r.chatId);if(i===void 0)throw Error(`telegramChannel().receive requires target.chatId.`);let a=typeof r.messageThreadId==`number`?r.messageThreadId:void 0,o=readOptionalString(r.conversationId),s=r.initialMessage;if(s!==void 0&&o!==void 0)throw Error("telegramChannel().receive: `conversationId` and `initialMessage` are mutually exclusive.");let c={...initialTelegramState(e.botUsername),chatId:i,conversationId:o??null,messageThreadId:a??null};return s!==void 0&&await buildTelegramHandle({config:e,state:c}).sendMessage(s),n(continuationTokenFromState(c)).send(t.message,{auth:t.auth,state:c})},events:r});return attachTelegramDeliver(c),c}function rebuildTelegramContext(e,t,n){return{state:e,telegram:buildTelegramHandle({config:n,session:t,state:e})}}function buildTelegramHandle(e){let n=e.config.api,r=e.state,i=e.config.credentials;function anchor(t){let n=r.chatType??t.chatType??null;r.chatType===null&&t.chatType!==void 0&&(r.chatType=t.chatType),!(!t.id||!shouldAnchorTelegramConversation(n))&&(r.conversationId=t.id,r.chatId&&e.session?.continuation?.rekey(telegramContinuationToken({chatId:r.chatId,conversationId:t.id,messageThreadId:r.messageThreadId??void 0})))}async function sendOne(e){let t=r.chatId??``;if(!t)throw Error(`telegramChannel: missing chat id for outbound message.`);let a=await sendTelegramMessage({apiBaseUrl:n?.apiBaseUrl,body:{...e,message_thread_id:e.message_thread_id??r.messageThreadId??void 0},credentials:i,fetch:n?.fetch,fileBaseUrl:n?.fileBaseUrl,chatId:t});return anchor(a),a}return{botUsername:r.botUsername??e.config.botUsername,chatId:r.chatId??``,chatType:r.chatType??void 0,conversationId:r.conversationId??void 0,messageThreadId:r.messageThreadId??void 0,answerCallbackQuery(e){return answerTelegramCallbackQuery({apiBaseUrl:n?.apiBaseUrl,callbackQueryId:e.callbackQueryId,credentials:i,fetch:n?.fetch,showAlert:e.showAlert,text:e.text})},editMessageReplyMarkup(e){let t=r.chatId??``;if(!t)throw Error(`telegramChannel: missing chat id for reply-markup edit.`);return editTelegramMessageReplyMarkup({apiBaseUrl:n?.apiBaseUrl,chatId:t,credentials:i,fetch:n?.fetch,messageId:e.messageId,replyMarkup:e.replyMarkup})},post(e){return postTelegramMessage(e,sendOne)},request(e,t){return callTelegramApi({apiBaseUrl:n?.apiBaseUrl,body:t,botToken:i?.botToken,fetch:n?.fetch,method:e})},sendMessage(e){return postTelegramMessage(e,sendOne)},async startTyping(e=`typing`){let a=r.chatId??``;if(a)try{await sendTelegramChatAction({action:e,apiBaseUrl:n?.apiBaseUrl,chatId:a,credentials:i,fetch:n?.fetch,messageThreadId:r.messageThreadId??void 0})}catch(e){logError(log,`Telegram typing indicator failed — swallowed`,e,{chatId:a})}}}}function shouldAnchorTelegramConversation(e){return e===`group`||e===`supergroup`}async function postTelegramMessage(e,t){let n=typeof e==`string`?{text:e}:e,r=splitTelegramMessageText(n.text),i;for(let[e,a]of r.entries()){let r=await t(e===0?{...n,text:a}:{text:a});i===void 0&&(i=r)}return i??{id:``,raw:null}}async function verifyInbound(e,t){try{return await verifyTelegramRequest(e,{secretToken:t?.webhookVerifier?void 0:t?.webhookSecretToken,webhookVerifier:t?.webhookVerifier})}catch(e){return log.warn(`telegram inbound verification failed`,{error:e}),null}}async function dispatchMessage(e){if(e.message.from?.isBot===!0)return;let t=stateFromMessage(e.message,e.config),n={telegram:buildTelegramHandle({config:e.config,state:t})},r;try{r=await e.onMessage(n,e.message)}catch(e){log.error(`message handler failed`,{error:e});return}if(r==null)return;let i=collectTelegramFileParts(e.message.attachments,e.uploadPolicy),a=buildTelegramTurnMessage(e.message,i),o=formatTelegramContextBlock({botUsername:e.config.botUsername,chatId:e.message.chat.id,chatTitle:e.message.chat.title,chatType:e.message.chat.type,messageId:e.message.messageId,messageThreadId:e.message.messageThreadId,userId:e.message.from?.id,username:e.message.from?.username}),s=r.context??[],l=e.message.text||e.message.caption,u=e.message.replyToMessage?.from?.isBot===!0&&l.trim().length>0?[telegramReplyInputResponse({messageId:e.message.replyToMessage.messageId,text:l})]:void 0;try{let n=e.from(continuationTokenFromState(t));u===void 0?await n.send(a,{auth:r.auth,context:[o,...s],state:t}):await n.respond(u,{auth:r.auth,context:[o,...s]})}catch(e){log.error(`message delivery failed`,{error:e})}}async function dispatchCallbackQuery(e){let t=stateFromCallbackQuery(e.query,e.config),n={telegram:buildTelegramHandle({config:e.config,state:t})};if(e.query.data?.startsWith(TELEGRAM_HITL_CALLBACK_PREFIX)===!0){try{await n.telegram.answerCallbackQuery({callbackQueryId:e.query.id,text:`Answer received.`})}catch(e){log.warn(`Telegram callback-query acknowledgement failed`,{error:e})}if(!e.query.message||!t.chatId)return;try{await e.from(continuationTokenFromState(t)).respond([telegramCallbackInputResponse(e.query.data)],{auth:null})}catch(e){log.error(`callback query delivery failed`,{error:e})}return}if(e.config.onCallbackQuery!==void 0){try{await e.config.onCallbackQuery(n,e.query)}catch(e){log.error(`custom callback-query handler failed`,{error:e})}return}try{await n.telegram.answerCallbackQuery({callbackQueryId:e.query.id,text:`Unsupported action.`})}catch(e){log.warn(`Telegram unsupported callback-query acknowledgement failed`,{error:e})}}function attachTelegramDeliver(e){if(!isCompiledChannel(e))return;let t=e.adapter;t.deliver=(e,t)=>{let n=e.inputResponses??[];if(n.some(isTelegramSyntheticResponse)){let r=resolveTelegramInputResponses(t.state,n);return r.length>0?{inputResponses:r,context:e.context}:e.message===void 0?void 0:{message:e.message,context:e.context}}return defaultDeliverResult(e)}}function stateFromMessage(e,t){let n=e.chat.type===`private`;return{...initialTelegramState(t.botUsername),chatId:e.chat.id,chatType:e.chat.type,conversationId:n?null:conversationIdForMessage(e),messageThreadId:e.messageThreadId??null,triggeringUserId:e.from?.id??null}}function stateFromCallbackQuery(e,t){let n=e.message;if(!n)return{...initialTelegramState(t.botUsername),triggeringUserId:e.from.id};let r=n.chat.type===`private`;return{...initialTelegramState(t.botUsername),chatId:n.chat.id,chatType:n.chat.type,conversationId:r?null:n.messageId,messageThreadId:n.messageThreadId??null,triggeringUserId:e.from.id}}function conversationIdForMessage(e){return e.replyToMessage?.from?.isBot===!0?e.replyToMessage.messageId:e.messageId}function continuationTokenFromState(e){return telegramContinuationToken({chatId:e.chatId??``,conversationId:e.chatType===`private`?void 0:e.conversationId??void 0,messageThreadId:e.messageThreadId??void 0})}function initialTelegramState(e){return{botUsername:e??null,chatId:null,chatType:null,conversationId:null,hitlCallbacks:{},messageThreadId:null,nextHitlCallbackId:0,pendingFreeformReplies:{},triggeringUserId:null}}function readChatId(e){if(typeof e==`string`&&e.length>0)return e;if(typeof e==`number`&&Number.isFinite(e))return String(e)}function readOptionalString(e){if(typeof e==`string`&&e.length>0)return e;if(typeof e==`number`&&Number.isFinite(e))return String(e)}export{telegramChannel};
1
+ import{createLogger,logError}from"#internal/logging.js";import{isCompiledChannel}from"#channel/compiled-channel.js";import{defaultDeliverResult}from"#channel/adapter.js";import{parseJsonObject}from"#shared/json.js";import{POST,defineChannel}from"#public/definitions/channel.js";import{mergeUploadPolicy}from"#public/channels/upload-policy.js";import{formatTelegramContextBlock,parseTelegramUpdate}from"#public/channels/telegram/inbound.js";import{answerTelegramCallbackQuery,callTelegramApi,editTelegramMessageReplyMarkup,sendTelegramChatAction,sendTelegramMessage,splitTelegramMessageText,telegramContinuationToken}from"#public/channels/telegram/api.js";import{TELEGRAM_HITL_CALLBACK_PREFIX,isTelegramSyntheticResponse,resolveTelegramInputResponses,telegramCallbackInputResponse,telegramReplyInputResponse}from"#public/channels/telegram/hitl.js";import{buildTelegramTurnMessage,collectTelegramFileParts,createTelegramFetchFile}from"#public/channels/telegram/attachments.js";import{defaultEvents,defaultOnMessage}from"#public/channels/telegram/defaults.js";import{verifyTelegramRequest}from"#public/channels/telegram/verify.js";const log=createLogger(`telegram.channel`);function telegramChannel(e={}){let t=mergeUploadPolicy(e.uploadPolicy),n=e.onMessage??defaultOnMessage,r={...defaultEvents,...e.events},c=defineChannel({kindHint:`telegram`,turnPolicy:e.turnPolicy,state:initialTelegramState(e.botUsername),metadata:e=>({chatId:e.chatId,chatType:e.chatType,triggeringUserId:e.triggeringUserId??null}),fetchFile:createTelegramFetchFile({api:e.api,credentials:e.credentials,policy:t}),context(t,n){return rebuildTelegramContext(t,n,e)},routes:[POST(e.route??`/eve/v1/telegram`,async(r,{from:a,waitUntil:o})=>{let s=await verifyInbound(r,e.credentials);if(s===null)return new Response(`unauthorized`,{status:401});let c;try{c=parseJsonObject(JSON.parse(s))}catch(e){return log.warn(`inbound Telegram body is not valid JSON`,{error:e}),new Response(`ok`)}let u=parseTelegramUpdate(c);return u===null?new Response(`ok`):u.kind===`message`?(o(dispatchMessage({config:e,message:u.message,onMessage:n,uploadPolicy:t,from:a})),new Response(`ok`)):(o(dispatchCallbackQuery({config:e,query:u.callbackQuery,from:a})),new Response(`ok`))})],async receive(t,{from:n}){let r=t.target,i=readChatId(r.chatId);if(i===void 0)throw Error(`telegramChannel().receive requires target.chatId.`);let a=typeof r.messageThreadId==`number`?r.messageThreadId:void 0,o=readOptionalString(r.conversationId),s=r.initialMessage;if(s!==void 0&&o!==void 0)throw Error("telegramChannel().receive: `conversationId` and `initialMessage` are mutually exclusive.");let c={...initialTelegramState(e.botUsername),chatId:i,conversationId:o??null,messageThreadId:a??null};return s!==void 0&&await buildTelegramHandle({config:e,state:c}).sendMessage(s),n(continuationTokenFromState(c)).send(t.message,{auth:t.auth,state:c})},events:r});return attachTelegramDeliver(c),c}function rebuildTelegramContext(e,t,n){return{state:e,telegram:buildTelegramHandle({config:n,session:t,state:e})}}function buildTelegramHandle(e){let n=e.config.api,r=e.state,i=e.config.credentials;function anchor(t){let n=r.chatType??t.chatType??null;r.chatType===null&&t.chatType!==void 0&&(r.chatType=t.chatType),!(!t.id||!shouldAnchorTelegramConversation(n))&&(r.conversationId=t.id,r.chatId&&e.session?.continuation?.rekey(telegramContinuationToken({chatId:r.chatId,conversationId:t.id,messageThreadId:r.messageThreadId??void 0})))}async function sendOne(e){let t=r.chatId??``;if(!t)throw Error(`telegramChannel: missing chat id for outbound message.`);let a=await sendTelegramMessage({apiBaseUrl:n?.apiBaseUrl,body:{...e,message_thread_id:e.message_thread_id??r.messageThreadId??void 0},credentials:i,fetch:n?.fetch,fileBaseUrl:n?.fileBaseUrl,chatId:t});return anchor(a),a}return{botUsername:r.botUsername??e.config.botUsername,chatId:r.chatId??``,chatType:r.chatType??void 0,conversationId:r.conversationId??void 0,messageThreadId:r.messageThreadId??void 0,answerCallbackQuery(e){return answerTelegramCallbackQuery({apiBaseUrl:n?.apiBaseUrl,callbackQueryId:e.callbackQueryId,credentials:i,fetch:n?.fetch,showAlert:e.showAlert,text:e.text})},editMessageReplyMarkup(e){let t=r.chatId??``;if(!t)throw Error(`telegramChannel: missing chat id for reply-markup edit.`);return editTelegramMessageReplyMarkup({apiBaseUrl:n?.apiBaseUrl,chatId:t,credentials:i,fetch:n?.fetch,messageId:e.messageId,replyMarkup:e.replyMarkup})},post(e){return postTelegramMessage(e,sendOne)},request(e,t){return callTelegramApi({apiBaseUrl:n?.apiBaseUrl,body:t,botToken:i?.botToken,fetch:n?.fetch,method:e})},sendMessage(e){return postTelegramMessage(e,sendOne)},async startTyping(e=`typing`){let a=r.chatId??``;if(a)try{await sendTelegramChatAction({action:e,apiBaseUrl:n?.apiBaseUrl,chatId:a,credentials:i,fetch:n?.fetch,messageThreadId:r.messageThreadId??void 0})}catch(e){logError(log,`Telegram typing indicator failed — swallowed`,e,{chatId:a})}}}}function shouldAnchorTelegramConversation(e){return e===`group`||e===`supergroup`}async function postTelegramMessage(e,t){let n=typeof e==`string`?{text:e}:e,r=splitTelegramMessageText(n.text),i;for(let[e,a]of r.entries()){let r=await t(e===0?{...n,text:a}:{text:a});i===void 0&&(i=r)}return i??{id:``,raw:null}}async function verifyInbound(e,t){try{return await verifyTelegramRequest(e,{secretToken:t?.webhookVerifier?void 0:t?.webhookSecretToken,webhookVerifier:t?.webhookVerifier})}catch(e){return log.warn(`telegram inbound verification failed`,{error:e}),null}}async function dispatchMessage(e){if(e.message.from?.isBot===!0)return;let t=stateFromMessage(e.message,e.config),n={telegram:buildTelegramHandle({config:e.config,state:t})},r;try{r=await e.onMessage(n,e.message)}catch(e){log.error(`message handler failed`,{error:e});return}if(r==null)return;let i=collectTelegramFileParts(e.message.attachments,e.uploadPolicy),a=buildTelegramTurnMessage(e.message,i),o=formatTelegramContextBlock({botUsername:e.config.botUsername,chatId:e.message.chat.id,chatTitle:e.message.chat.title,chatType:e.message.chat.type,messageId:e.message.messageId,messageThreadId:e.message.messageThreadId,userId:e.message.from?.id,username:e.message.from?.username}),s=r.context??[],l=e.message.text||e.message.caption,u=e.message.replyToMessage?.from?.isBot===!0&&l.trim().length>0?[telegramReplyInputResponse({messageId:e.message.replyToMessage.messageId,text:l})]:void 0;try{let n=e.from(continuationTokenFromState(t));u===void 0?await n.send(a,{auth:r.auth,context:[o,...s],state:t}):await n.respond(u,{auth:r.auth,context:[o,...s]})}catch(e){log.error(`message delivery failed`,{error:e})}}async function dispatchCallbackQuery(e){let t=stateFromCallbackQuery(e.query,e.config),n={telegram:buildTelegramHandle({config:e.config,state:t})};if(e.query.data?.startsWith(TELEGRAM_HITL_CALLBACK_PREFIX)===!0){try{await n.telegram.answerCallbackQuery({callbackQueryId:e.query.id,text:`Answer received.`})}catch(e){log.warn(`Telegram callback-query acknowledgement failed`,{error:e})}if(!e.query.message||!t.chatId)return;try{await e.from(continuationTokenFromState(t)).respond([telegramCallbackInputResponse(e.query.data)],{auth:null})}catch(e){log.error(`callback query delivery failed`,{error:e})}return}if(e.config.onCallbackQuery!==void 0){try{await e.config.onCallbackQuery(n,e.query)}catch(e){log.error(`custom callback-query handler failed`,{error:e})}return}try{await n.telegram.answerCallbackQuery({callbackQueryId:e.query.id,text:`Unsupported action.`})}catch(e){log.warn(`Telegram unsupported callback-query acknowledgement failed`,{error:e})}}function attachTelegramDeliver(e){if(!isCompiledChannel(e))return;let t=e.adapter;t.deliver=(e,t)=>{let n=e.inputResponses??[];if(n.some(isTelegramSyntheticResponse)){let r=resolveTelegramInputResponses(t.state,n);return r.length>0?{inputResponses:r,context:e.context}:e.message===void 0?void 0:{message:e.message,context:e.context}}return defaultDeliverResult(e)}}function stateFromMessage(e,t){let n=e.chat.type===`private`;return{...initialTelegramState(t.botUsername),chatId:e.chat.id,chatType:e.chat.type,conversationId:n?null:conversationIdForMessage(e),messageThreadId:e.messageThreadId??null,triggeringUserId:e.from?.id??null}}function stateFromCallbackQuery(e,t){let n=e.message;if(!n)return{...initialTelegramState(t.botUsername),triggeringUserId:e.from.id};let r=n.chat.type===`private`;return{...initialTelegramState(t.botUsername),chatId:n.chat.id,chatType:n.chat.type,conversationId:r?null:n.messageId,messageThreadId:n.messageThreadId??null,triggeringUserId:e.from.id}}function conversationIdForMessage(e){return e.replyToMessage?.from?.isBot===!0?e.replyToMessage.messageId:e.messageId}function continuationTokenFromState(e){return telegramContinuationToken({chatId:e.chatId??``,conversationId:e.chatType===`private`?void 0:e.conversationId??void 0,messageThreadId:e.messageThreadId??void 0})}function initialTelegramState(e){return{botUsername:e??null,chatId:null,chatType:null,conversationId:null,hitlCallbacks:{},messageThreadId:null,nextHitlCallbackId:0,pendingFreeformReplies:{},triggeringUserId:null}}function readChatId(e){if(typeof e==`string`&&e.length>0)return e;if(typeof e==`number`&&Number.isFinite(e))return String(e)}function readOptionalString(e){if(typeof e==`string`&&e.length>0)return e;if(typeof e==`number`&&Number.isFinite(e))return String(e)}export{telegramChannel};
@@ -1,4 +1,4 @@
1
- import type { SessionAuthContext } from "#channel/types.js";
1
+ import type { SessionAuthContext, TurnPolicy } from "#channel/types.js";
2
2
  import type { SessionContext } from "#public/definitions/callback-context.js";
3
3
  import type { ChannelContinuationOps } from "#public/definitions/channel.js";
4
4
  import type { UnstampedMessageStreamEvent } from "#protocol/message.js";
@@ -140,6 +140,8 @@ export interface TwilioChannelConfig {
140
140
  * mounts `/messages`, `/voice`, and `/voice/transcription` below it.
141
141
  */
142
142
  readonly route?: string;
143
+ /** Policy for accepted messages that arrive while a turn is active. */
144
+ readonly turnPolicy?: TurnPolicy;
143
145
  /**
144
146
  * Public URL Twilio used for signing. Set this when proxies or local
145
147
  * tunnels make `request.url` differ from the configured webhook URL.
@@ -1 +1 @@
1
- import{createLogger}from"#internal/logging.js";import{readNonEmptyString}from"#shared/guards.js";import{GET,POST,defineChannel}from"#public/definitions/channel.js";import"#public/channels/twilio/verify.js";import{callTwilioApi,sendTwilioMessage,twilioContinuationToken,updateTwilioCall}from"#public/channels/twilio/api.js";import{emptyTwilioResponse,gatherSpeechTwilioResponse,sayTwilioResponse}from"#public/channels/twilio/twiml.js";import{defaultEvents,defaultOnText,defaultOnVoice,defaultOnVoiceTranscription}from"#public/channels/twilio/defaults.js";import{formatTwilioContextBlock,parseTwilioTextMessage,parseTwilioVoiceCall,parseTwilioVoiceTranscription}from"#public/channels/twilio/inbound.js";import{buildTwilioActionUrl,buildTwilioRoutes,verifyTwilioInbound}from"#public/channels/twilio/routing.js";const log=createLogger(`twilio.channel`);function twilioChannel(e){assertAllowFromConfigured(e);let a=buildTwilioRoutes(e.route??`/eve/v1/twilio`),o=e.onText??defaultOnText,c=e.onVoice??defaultOnVoice,l=e.onVoiceTranscription??defaultOnVoiceTranscription,u={...defaultEvents,...e.events},d=handleTwilioMessages({config:e,onText:o}),f=handleTwilioVoice({config:e,onVoice:c,routes:a}),p=handleTwilioTranscription({config:e,onVoiceTranscription:l,routes:a});return defineChannel({kindHint:`twilio`,state:{from:null,to:null,lastCallSid:null,lastMessageSid:null},metadata(e){return{from:e.from,lastCallSid:e.lastCallSid??null,lastMessageSid:e.lastMessageSid??null,to:e.to}},context(t,n){return rebuildTwilioContext(t,n,e)},routes:[GET(a.messages,d),POST(a.messages,d),GET(a.voice,f),POST(a.voice,f),GET(a.transcription,p),POST(a.transcription,p)],async receive(n,{from:r}){let i=readNonEmptyString(n.target.phoneNumber);if(!i)throw Error(`twilioChannel().receive requires target.phoneNumber.`);let a=readNonEmptyString(n.target.from)??e.messaging?.from??null;return r(twilioContinuationToken(i,a??void 0)).send(n.message,{auth:n.auth,state:{from:i,lastCallSid:null,lastMessageSid:null,to:a}})},events:u})}function handleTwilioMessages(e){return async(t,{from:n,waitUntil:r})=>{let i=await verifyTwilioInbound(t,e.config);if(i===null)return new Response(`unauthorized`,{status:401});let a=parseTwilioTextMessage(i.params);return a?await isAllowed(a.from,e.config.allowFrom)?(r(dispatchText({config:e.config,message:a,onText:e.onText,from:n})),emptyTwilioResponse()):new Response(`forbidden`,{status:403}):emptyTwilioResponse()}}function handleTwilioVoice(e){return async t=>{let n=await verifyTwilioInbound(t,e.config);if(n===null)return new Response(`unauthorized`,{status:401});let r=parseTwilioVoiceCall(n.params);if(!r)return sayTwilioResponse(`Missing caller information.`);if(!await isAllowed(r.from,e.config.allowFrom))return new Response(`forbidden`,{status:403});let i=await acceptVoiceCall({call:r,config:e.config,onVoice:e.onVoice});if(i===null)return new Response(`forbidden`,{status:403});let a=i??{};return gatherSpeechTwilioResponse({actionUrl:await buildTwilioActionUrl(t,e.config,e.routes.transcription),hints:a.hints??e.config.voice?.hints,language:a.language??e.config.voice?.language,profanityFilter:a.profanityFilter??e.config.voice?.profanityFilter,prompt:a.prompt??e.config.voice?.prompt??`Please say your message after the tone.`,speechModel:a.speechModel??e.config.voice?.speechModel,speechTimeout:a.speechTimeout??e.config.voice?.speechTimeout??`auto`,timeoutSeconds:a.timeoutSeconds??e.config.voice?.timeoutSeconds,voice:a.voice??e.config.voice?.voice})}}function handleTwilioTranscription(e){return async(t,{from:n,waitUntil:r})=>{let i=await verifyTwilioInbound(t,e.config);if(i===null)return new Response(`unauthorized`,{status:401});let a=parseTwilioVoiceTranscription(i.params);return a?await isAllowed(a.from,e.config.allowFrom)?(r(dispatchVoiceTranscription({config:e.config,onVoiceTranscription:e.onVoiceTranscription,from:n,transcription:a})),sayTwilioResponse(e.config.voice?.acknowledgement??`Thanks. I'll follow up by text.`)):new Response(`forbidden`,{status:403}):gatherSpeechTwilioResponse({actionUrl:await buildTwilioActionUrl(t,e.config,e.routes.transcription),language:e.config.voice?.language,prompt:e.config.voice?.prompt??`Please say your message after the tone.`,speechTimeout:e.config.voice?.speechTimeout??`auto`,timeoutSeconds:e.config.voice?.timeoutSeconds})}}function rebuildTwilioContext(e,t,n){return{state:e,twilio:buildTwilioHandle({callSid:e.lastCallSid??void 0,config:n,from:e.from??``,to:e.to??void 0})}}function buildTwilioHandle(e){let t=e.config.api,n=e.config.credentials,r=e.config.messaging?.from??e.to,i=e.config.messaging?.messagingServiceSid,s=e.config.messaging?.statusCallbackUrl;return{callSid:e.callSid,from:e.from,to:e.to,request(e,r){return callTwilioApi({apiBaseUrl:t?.apiBaseUrl,body:r,credentials:n,fetch:t?.fetch,path:e})},sendMessage(a,c){return sendTwilioMessage({apiBaseUrl:t?.apiBaseUrl,body:a,credentials:n,fetch:t?.fetch,from:c?.from??r,messagingServiceSid:c?.messagingServiceSid??i,statusCallbackUrl:c?.statusCallbackUrl??s,to:c?.to??e.from})},updateCall(e,r){return updateTwilioCall({apiBaseUrl:t?.apiBaseUrl,callSid:e,credentials:n,fetch:t?.fetch,twiml:r})}}}function assertAllowFromConfigured(e){if(e?.allowFrom===void 0)throw Error(`twilioChannel requires allowFrom. Use allowFrom: "*" to allow all numbers.`)}async function dispatchText(e){let{message:t}=e,n={twilio:buildTwilioHandle({callSid:void 0,config:e.config,from:t.from,to:t.to})},r;try{r=await e.onText(n,t)}catch(e){log.error(`text handler failed`,{error:e});return}if(r==null)return;let i=formatTwilioContextBlock({channel:`text`,from:t.from,messageSid:t.messageSid,to:t.to});try{await e.from(twilioContinuationToken(t.from,t.to)).send(t.body,{auth:r.auth,context:[i],state:{from:t.from,lastCallSid:null,lastMessageSid:t.messageSid??null,to:t.to??null}})}catch(e){log.error(`text delivery failed`,{error:e})}}async function acceptVoiceCall(e){let{call:t}=e,n={twilio:buildTwilioHandle({callSid:t.callSid,config:e.config,from:t.from,to:t.to})};try{return await e.onVoice(n,t)}catch(e){return log.error(`voice handler failed`,{error:e}),null}}async function dispatchVoiceTranscription(e){let{transcription:t}=e,n={twilio:buildTwilioHandle({callSid:t.callSid,config:e.config,from:t.from,to:t.to})},r;try{r=await e.onVoiceTranscription(n,t)}catch(e){log.error(`voice transcription handler failed`,{error:e});return}if(r==null)return;let i=formatTwilioContextBlock({callSid:t.callSid,channel:`voice`,from:t.from,to:t.to});try{await e.from(twilioContinuationToken(t.from,t.to)).send(t.text,{auth:r.auth,context:[i],state:{from:t.from,lastCallSid:t.callSid??null,lastMessageSid:null,to:t.to??null}})}catch(e){log.error(`voice transcription delivery failed`,{error:e})}}async function isAllowed(e,t){let n=typeof t==`function`?await t():t;return n===`*`?!0:typeof n==`string`?n===e:n.includes(e)}export{twilioChannel};
1
+ import{createLogger}from"#internal/logging.js";import{readNonEmptyString}from"#shared/guards.js";import{GET,POST,defineChannel}from"#public/definitions/channel.js";import"#public/channels/twilio/verify.js";import{callTwilioApi,sendTwilioMessage,twilioContinuationToken,updateTwilioCall}from"#public/channels/twilio/api.js";import{emptyTwilioResponse,gatherSpeechTwilioResponse,sayTwilioResponse}from"#public/channels/twilio/twiml.js";import{defaultEvents,defaultOnText,defaultOnVoice,defaultOnVoiceTranscription}from"#public/channels/twilio/defaults.js";import{formatTwilioContextBlock,parseTwilioTextMessage,parseTwilioVoiceCall,parseTwilioVoiceTranscription}from"#public/channels/twilio/inbound.js";import{buildTwilioActionUrl,buildTwilioRoutes,verifyTwilioInbound}from"#public/channels/twilio/routing.js";const log=createLogger(`twilio.channel`);function twilioChannel(e){assertAllowFromConfigured(e);let a=buildTwilioRoutes(e.route??`/eve/v1/twilio`),o=e.onText??defaultOnText,c=e.onVoice??defaultOnVoice,l=e.onVoiceTranscription??defaultOnVoiceTranscription,u={...defaultEvents,...e.events},d=handleTwilioMessages({config:e,onText:o}),f=handleTwilioVoice({config:e,onVoice:c,routes:a}),p=handleTwilioTranscription({config:e,onVoiceTranscription:l,routes:a});return defineChannel({kindHint:`twilio`,turnPolicy:e.turnPolicy,state:{from:null,to:null,lastCallSid:null,lastMessageSid:null},metadata(e){return{from:e.from,lastCallSid:e.lastCallSid??null,lastMessageSid:e.lastMessageSid??null,to:e.to}},context(t,n){return rebuildTwilioContext(t,n,e)},routes:[GET(a.messages,d),POST(a.messages,d),GET(a.voice,f),POST(a.voice,f),GET(a.transcription,p),POST(a.transcription,p)],async receive(n,{from:r}){let i=readNonEmptyString(n.target.phoneNumber);if(!i)throw Error(`twilioChannel().receive requires target.phoneNumber.`);let a=readNonEmptyString(n.target.from)??e.messaging?.from??null;return r(twilioContinuationToken(i,a??void 0)).send(n.message,{auth:n.auth,state:{from:i,lastCallSid:null,lastMessageSid:null,to:a}})},events:u})}function handleTwilioMessages(e){return async(t,{from:n,waitUntil:r})=>{let i=await verifyTwilioInbound(t,e.config);if(i===null)return new Response(`unauthorized`,{status:401});let a=parseTwilioTextMessage(i.params);return a?await isAllowed(a.from,e.config.allowFrom)?(r(dispatchText({config:e.config,message:a,onText:e.onText,from:n})),emptyTwilioResponse()):new Response(`forbidden`,{status:403}):emptyTwilioResponse()}}function handleTwilioVoice(e){return async t=>{let n=await verifyTwilioInbound(t,e.config);if(n===null)return new Response(`unauthorized`,{status:401});let r=parseTwilioVoiceCall(n.params);if(!r)return sayTwilioResponse(`Missing caller information.`);if(!await isAllowed(r.from,e.config.allowFrom))return new Response(`forbidden`,{status:403});let i=await acceptVoiceCall({call:r,config:e.config,onVoice:e.onVoice});if(i===null)return new Response(`forbidden`,{status:403});let a=i??{};return gatherSpeechTwilioResponse({actionUrl:await buildTwilioActionUrl(t,e.config,e.routes.transcription),hints:a.hints??e.config.voice?.hints,language:a.language??e.config.voice?.language,profanityFilter:a.profanityFilter??e.config.voice?.profanityFilter,prompt:a.prompt??e.config.voice?.prompt??`Please say your message after the tone.`,speechModel:a.speechModel??e.config.voice?.speechModel,speechTimeout:a.speechTimeout??e.config.voice?.speechTimeout??`auto`,timeoutSeconds:a.timeoutSeconds??e.config.voice?.timeoutSeconds,voice:a.voice??e.config.voice?.voice})}}function handleTwilioTranscription(e){return async(t,{from:n,waitUntil:r})=>{let i=await verifyTwilioInbound(t,e.config);if(i===null)return new Response(`unauthorized`,{status:401});let a=parseTwilioVoiceTranscription(i.params);return a?await isAllowed(a.from,e.config.allowFrom)?(r(dispatchVoiceTranscription({config:e.config,onVoiceTranscription:e.onVoiceTranscription,from:n,transcription:a})),sayTwilioResponse(e.config.voice?.acknowledgement??`Thanks. I'll follow up by text.`)):new Response(`forbidden`,{status:403}):gatherSpeechTwilioResponse({actionUrl:await buildTwilioActionUrl(t,e.config,e.routes.transcription),language:e.config.voice?.language,prompt:e.config.voice?.prompt??`Please say your message after the tone.`,speechTimeout:e.config.voice?.speechTimeout??`auto`,timeoutSeconds:e.config.voice?.timeoutSeconds})}}function rebuildTwilioContext(e,t,n){return{state:e,twilio:buildTwilioHandle({callSid:e.lastCallSid??void 0,config:n,from:e.from??``,to:e.to??void 0})}}function buildTwilioHandle(e){let t=e.config.api,n=e.config.credentials,r=e.config.messaging?.from??e.to,i=e.config.messaging?.messagingServiceSid,s=e.config.messaging?.statusCallbackUrl;return{callSid:e.callSid,from:e.from,to:e.to,request(e,r){return callTwilioApi({apiBaseUrl:t?.apiBaseUrl,body:r,credentials:n,fetch:t?.fetch,path:e})},sendMessage(a,c){return sendTwilioMessage({apiBaseUrl:t?.apiBaseUrl,body:a,credentials:n,fetch:t?.fetch,from:c?.from??r,messagingServiceSid:c?.messagingServiceSid??i,statusCallbackUrl:c?.statusCallbackUrl??s,to:c?.to??e.from})},updateCall(e,r){return updateTwilioCall({apiBaseUrl:t?.apiBaseUrl,callSid:e,credentials:n,fetch:t?.fetch,twiml:r})}}}function assertAllowFromConfigured(e){if(e?.allowFrom===void 0)throw Error(`twilioChannel requires allowFrom. Use allowFrom: "*" to allow all numbers.`)}async function dispatchText(e){let{message:t}=e,n={twilio:buildTwilioHandle({callSid:void 0,config:e.config,from:t.from,to:t.to})},r;try{r=await e.onText(n,t)}catch(e){log.error(`text handler failed`,{error:e});return}if(r==null)return;let i=formatTwilioContextBlock({channel:`text`,from:t.from,messageSid:t.messageSid,to:t.to});try{await e.from(twilioContinuationToken(t.from,t.to)).send(t.body,{auth:r.auth,context:[i],state:{from:t.from,lastCallSid:null,lastMessageSid:t.messageSid??null,to:t.to??null}})}catch(e){log.error(`text delivery failed`,{error:e})}}async function acceptVoiceCall(e){let{call:t}=e,n={twilio:buildTwilioHandle({callSid:t.callSid,config:e.config,from:t.from,to:t.to})};try{return await e.onVoice(n,t)}catch(e){return log.error(`voice handler failed`,{error:e}),null}}async function dispatchVoiceTranscription(e){let{transcription:t}=e,n={twilio:buildTwilioHandle({callSid:t.callSid,config:e.config,from:t.from,to:t.to})},r;try{r=await e.onVoiceTranscription(n,t)}catch(e){log.error(`voice transcription handler failed`,{error:e});return}if(r==null)return;let i=formatTwilioContextBlock({callSid:t.callSid,channel:`voice`,from:t.from,to:t.to});try{await e.from(twilioContinuationToken(t.from,t.to)).send(t.text,{auth:r.auth,context:[i],state:{from:t.from,lastCallSid:t.callSid??null,lastMessageSid:null,to:t.to??null}})}catch(e){log.error(`voice transcription delivery failed`,{error:e})}}async function isAllowed(e,t){let n=typeof t==`function`?await t():t;return n===`*`?!0:typeof n==`string`?n===e:n.includes(e)}export{twilioChannel};
@@ -1,7 +1,7 @@
1
- import type { AgentBuildDefinition, PublicAgentDefinition } from "#shared/agent-definition.js";
1
+ import type { AgentBuildDefinition, PublicAgentDefinition, PublicAgentStaticModelDefinition } from "#shared/agent-definition.js";
2
2
  import type { ExactDefinition } from "#public/definitions/exact.js";
3
3
  import type { RemoteAgentDefinition } from "#public/definitions/remote-agent.js";
4
- import type { DynamicEvents, DynamicEventsWithFallback, DynamicSentinel } from "#shared/dynamic-tool-definition.js";
4
+ import type { DynamicEvents, DynamicSentinel } from "#shared/dynamic-tool-definition.js";
5
5
  declare const DEFINED_AGENT: unique symbol;
6
6
  export type { AgentModelResolveContext, AgentModelOptionsDefinition, AgentModelResolver, AgentReasoningDefinition, AgentBuildDefinition, PublicAgentDynamicModelDefinition as AgentDynamicModelDefinition, PublicAgentDynamicModelResult as AgentDynamicModelResult, AgentExperimentalDefinition, AgentLimitsDefinition, PublicAgentModelSelectionDefinition as AgentModelSelectionDefinition, AgentWorkflowDefinition, AgentWorkflowWorldDefinition, PublicAgentModelDefinition as AgentModelDefinition, PublicAgentStaticModelDefinition as AgentStaticModelDefinition, PublicAgentCompactionDefinition as AgentCompactionDefinition, } from "#shared/agent-definition.js";
7
7
  /**
@@ -23,7 +23,9 @@ export type DefinedAgent<TAgent extends AgentDefinition = AgentDefinition> = TAg
23
23
  * Agent configuration returned by a dynamic subagent resolver. The description
24
24
  * tells the parent agent when to delegate.
25
25
  */
26
- export type DynamicLocalSubagentDefinition = AgentDefinition & {
26
+ export type DynamicLocalSubagentDefinition = Extract<AgentDefinition, {
27
+ readonly model: PublicAgentStaticModelDefinition;
28
+ }> & {
27
29
  readonly description: string;
28
30
  };
29
31
  /** Definition a dynamic subagent resolver may select at runtime. */
@@ -34,10 +36,6 @@ type DynamicSubagentDescriptionConstraint<TEvents extends DynamicEvents> = Exclu
34
36
  readonly "Dynamic subagent definitions require a description": never;
35
37
  };
36
38
  interface DefineDynamicAgent {
37
- <const TEvents extends DynamicEventsWithFallback, TFallback = unknown>(definition: {
38
- readonly fallback: TFallback;
39
- readonly events: TEvents;
40
- } & DynamicSubagentDescriptionConstraint<TEvents>): DynamicSentinel<Exclude<DynamicEventResult<TEvents>, undefined>, TFallback>;
41
39
  <const TEvents extends DynamicEvents>(definition: {
42
40
  readonly build?: AgentBuildDefinition;
43
41
  readonly events: TEvents;
@@ -1 +1 @@
1
- import{defineDynamic as defineDynamic$1}from"#public/definitions/tool.js";const defineDynamic=(t=>{let n=Object.hasOwn(t,`fallback`)?defineDynamic$1({events:t.events,fallback:t.fallback}):defineDynamic$1({events:t.events});return t.build===void 0?n:{...n,build:t.build}});function defineAgent(e){return e}export{defineAgent,defineDynamic};
1
+ import{defineDynamic as defineDynamic$1}from"#public/definitions/tool.js";const defineDynamic=(t=>{let n=defineDynamic$1({events:t.events});return t.build===void 0?n:{...n,build:t.build}});function defineAgent(e){return e}export{defineAgent,defineDynamic};
@@ -3,11 +3,12 @@ import { type ChannelCorsOptions } from "#channel/cors.js";
3
3
  import type { ChannelFrom, ChannelReceiveContext, ChannelResolveSession, ChannelRespondOptions, ChannelSendOptions, ChannelSource } from "#channel/channel-operations.js";
4
4
  import type { RouteDefinition } from "#channel/routes.js";
5
5
  import type { Session } from "#channel/session.js";
6
+ import type { TurnPolicy } from "#channel/types.js";
6
7
  import type { UnstampedMessageStreamEvent } from "#protocol/message.js";
7
8
  import type { SessionContext } from "#public/definitions/callback-context.js";
8
9
  import type { GenericChannelDefinition, GenericReceiveInput } from "#shared/channel-definition.js";
9
10
  declare const CHANNEL_METADATA_TYPE: unique symbol;
10
- export type { CancelTurnResult, ClearSessionResult, CompactSessionResult, GetEventStreamOptions, ResetSessionResult, SessionCallback, } from "#channel/types.js";
11
+ export type { CancelTurnResult, ClearSessionResult, CompactSessionResult, GetEventStreamOptions, ResetSessionResult, SessionCallback, TurnPolicy, } from "#channel/types.js";
11
12
  export type { Session, SessionHandle } from "#channel/session.js";
12
13
  export type { SessionRespondOptions, SessionSendOptions } from "#channel/session.js";
13
14
  export type { ChannelFrom, ChannelReceiveContext, ChannelResolveSession, ChannelRespondOptions, ChannelSendOptions, ChannelSource, };
@@ -160,6 +161,7 @@ export interface Channel<TState = undefined, TReceiveTarget = Record<string, unk
160
161
  readonly routes: readonly RouteDefinition<TState>[];
161
162
  readonly cors?: ChannelCorsOptions;
162
163
  readonly receive?: (input: ReceiveInput<TReceiveTarget>, ctx: ChannelReceiveContext<TState>) => Promise<Session>;
164
+ readonly turnPolicy?: TurnPolicy;
163
165
  }
164
166
  /**
165
167
  * Extracts the metadata projection type (`TMetadata`) from a {@link Channel}.
@@ -1 +1 @@
1
- import{CHANNEL_SENTINEL}from"#channel/compiled-channel.js";import{defaultDeliverResult}from"#channel/adapter.js";import{buildCallbackContext}from"#context/build-callback-context.js";import{normalizeChannelCors}from"#channel/cors.js";import{HTTP_ADAPTER_KIND}from"#channel/http.js";import{DELETE,GET,PATCH,POST,PUT,WS}from"#channel/routes.js";const DISABLED_ROUTE_SENTINEL_KIND=`eve:disabled-channel`;function disableRoute(){return{kind:DISABLED_ROUTE_SENTINEL_KIND}}function isDisabledRouteSentinel(e){return typeof e==`object`&&!!e&&e.kind===DISABLED_ROUTE_SENTINEL_KIND}function defineChannel(t){let n=buildAdapter(t),i=normalizeChannelCors(t.cors);return{__kind:CHANNEL_SENTINEL,routes:t.routes,adapter:n,cors:i,receive:t.receive}}const eventTypes=Object.keys({"context.cleared":null,"compaction.requested":null,"compaction.completed":null,"turn.started":null,"actions.requested":null,"action.partial":null,"action.result":null,"message.completed":null,"message.appended":null,"reasoning.appended":null,"reasoning.completed":null,"input.requested":null,"turn.failed":null,"turn.completed":null,"turn.cancelled":null,"session.failed":null,"session.completed":null,"session.waiting":null,"authorization.required":null,"authorization.completed":null});function buildAdapter(e){let r=e.state!=null,a=e.context!=null,o=e.fetchFile!==void 0,s=e.metadata,c=r||a||s!==void 0,l={},u=!1,d=e.events;for(let e of eventTypes){let t=d?.[e];t&&(u=!0,l[e]=(r,i)=>{let{session:a,...o}=i,s={...o,continuation:a?.continuation===void 0?void 0:{token:a.continuation.token,rekey:e=>a.continuation?.rekey(e)}};if(e===`session.failed`)return t(r,s);let c=buildCallbackContext();return t(r,s,c)})}return!c&&!u&&!o?{kind:e.kindHint??HTTP_ADAPTER_KIND}:{kind:e.kindHint??`defineChannel`,state:r?{...e.state}:{},fetchFile:e.fetchFile,instrumentation:s===void 0?void 0:{metadata(e){return s(e)}},createAdapterContext(t){let n=t.state,r=t.session;return{...a?e.context(n,r):{},state:n,ctx:t.ctx,session:r}},deliver(e){return defaultDeliverResult(e)},...l}}export{DELETE,GET,PATCH,POST,PUT,WS,defineChannel,disableRoute,isDisabledRouteSentinel};
1
+ import{CHANNEL_SENTINEL}from"#channel/compiled-channel.js";import{defaultDeliverResult}from"#channel/adapter.js";import{buildCallbackContext}from"#context/build-callback-context.js";import{normalizeChannelCors}from"#channel/cors.js";import{HTTP_ADAPTER_KIND}from"#channel/http.js";import{DELETE,GET,PATCH,POST,PUT,WS}from"#channel/routes.js";const DISABLED_ROUTE_SENTINEL_KIND=`eve:disabled-channel`;function disableRoute(){return{kind:DISABLED_ROUTE_SENTINEL_KIND}}function isDisabledRouteSentinel(e){return typeof e==`object`&&!!e&&e.kind===DISABLED_ROUTE_SENTINEL_KIND}function defineChannel(t){let n=buildAdapter(t),i=normalizeChannelCors(t.cors);return{__kind:CHANNEL_SENTINEL,routes:t.routes,adapter:n,cors:i,receive:t.receive,turnPolicy:t.turnPolicy}}const eventTypes=Object.keys({"context.cleared":null,"compaction.requested":null,"compaction.completed":null,"turn.started":null,"actions.requested":null,"action.partial":null,"action.result":null,"message.completed":null,"message.appended":null,"reasoning.appended":null,"reasoning.completed":null,"input.requested":null,"turn.failed":null,"turn.completed":null,"turn.cancelled":null,"session.failed":null,"session.completed":null,"session.waiting":null,"authorization.required":null,"authorization.completed":null});function buildAdapter(e){let r=e.state!=null,a=e.context!=null,o=e.fetchFile!==void 0,s=e.metadata,c=r||a||s!==void 0,l={},u=!1,d=e.events;for(let e of eventTypes){let t=d?.[e];t&&(u=!0,l[e]=(r,i)=>{let{session:a,...o}=i,s={...o,continuation:a?.continuation===void 0?void 0:{token:a.continuation.token,rekey:e=>a.continuation?.rekey(e)}};if(e===`session.failed`)return t(r,s);let c=buildCallbackContext();return t(r,s,c)})}return!c&&!u&&!o?{kind:e.kindHint??HTTP_ADAPTER_KIND}:{kind:e.kindHint??`defineChannel`,state:r?{...e.state}:{},fetchFile:e.fetchFile,instrumentation:s===void 0?void 0:{metadata(e){return s(e)}},createAdapterContext(t){let n=t.state,r=t.session;return{...a?e.context(n,r):{},state:n,ctx:t.ctx,session:r}},deliver(e){return defaultDeliverResult(e)},...l}}export{DELETE,GET,PATCH,POST,PUT,WS,defineChannel,disableRoute,isDisabledRouteSentinel};
@@ -4,7 +4,7 @@ import type { SessionContext } from "#public/definitions/callback-context.js";
4
4
  import type { Approval } from "#public/definitions/approval.js";
5
5
  import type { JsonObject } from "#shared/json.js";
6
6
  import type { AuthorizationDefinition, ConnectionAuthorizationContext, NonInteractiveAuthorizationDefinition, TokenResult } from "#runtime/connections/types.js";
7
- import { type DynamicEvents, type DynamicEventsWithFallback, type DynamicSentinel } from "#shared/dynamic-tool-definition.js";
7
+ import { type DynamicEvents, type DynamicSentinel } from "#shared/dynamic-tool-definition.js";
8
8
  type ApprovalContextInput<TInput> = unknown extends TInput ? Record<string, unknown> : TInput;
9
9
  type DynamicEventMapHandler<TEvents extends DynamicEvents> = Extract<NonNullable<TEvents[keyof TEvents]>, (...args: never[]) => unknown>;
10
10
  type DynamicEventMapResult<TEvents extends DynamicEvents> = Awaited<ReturnType<DynamicEventMapHandler<TEvents>>>;
@@ -209,10 +209,6 @@ export declare function defineTool<TInput = unknown, TOutput = unknown>(definiti
209
209
  export declare function defineDynamic<const TEvents extends DynamicEvents>(definition: {
210
210
  readonly events: TEvents;
211
211
  }): DynamicSentinel<DynamicEventMapResult<TEvents>>;
212
- export declare function defineDynamic<const TEvents extends DynamicEventsWithFallback, TFallback = unknown>(definition: {
213
- readonly fallback: TFallback;
214
- readonly events: TEvents;
215
- }): DynamicSentinel<Exclude<DynamicEventMapResult<TEvents>, undefined>, TFallback>;
216
212
  /**
217
213
  * Marker discriminator written into every {@link DisabledToolSentinel}.
218
214
  */
@@ -1 +1 @@
1
- import{DYNAMIC_SENTINEL_KIND,TOOL_BRAND}from"#shared/dynamic-tool-definition.js";import{stampDefinitionKey}from"#public/tool-result-narrowing.js";function defineTool(e){if(e.auth!==void 0)throw Error(`defineTool: The "auth" field is no longer supported. Pass auth providers inline to ctx.getToken(provider) or ctx.requireAuth(provider).`);return Object.assign(e,{[TOOL_BRAND]:!0}),stampDefinitionKey(e,`tool:${e.description}`),e}function defineDynamic(t){let n={kind:DYNAMIC_SENTINEL_KIND,events:t.events,...Object.hasOwn(t,`fallback`)?{fallback:t.fallback}:{}};return stampDefinitionKey(n,`dynamic:${Object.keys(t.events).join(`,`)}`),n}const DISABLED_TOOL_SENTINEL_KIND=`eve:disabled-tool`;function disableTool(){return{kind:DISABLED_TOOL_SENTINEL_KIND}}function isDisabledToolSentinel(e){return typeof e==`object`&&!!e&&e.kind===DISABLED_TOOL_SENTINEL_KIND}const EXPERIMENTAL_WORKFLOW_TOOL_KIND=`eve:enable-workflow-tool`;function experimental_workflow(e={}){let t={kind:EXPERIMENTAL_WORKFLOW_TOOL_KIND};return e.maxSubagents!==void 0&&(t.maxSubagents=e.maxSubagents),t}function isExperimentalWorkflowToolDefinition(e){return typeof e==`object`&&!!e&&e.kind===EXPERIMENTAL_WORKFLOW_TOOL_KIND}export{defineDynamic,defineTool,disableTool,experimental_workflow,isDisabledToolSentinel,isExperimentalWorkflowToolDefinition};
1
+ import{DYNAMIC_SENTINEL_KIND,TOOL_BRAND}from"#shared/dynamic-tool-definition.js";import{stampDefinitionKey}from"#public/tool-result-narrowing.js";function defineTool(e){if(e.auth!==void 0)throw Error(`defineTool: The "auth" field is no longer supported. Pass auth providers inline to ctx.getToken(provider) or ctx.requireAuth(provider).`);return Object.assign(e,{[TOOL_BRAND]:!0}),stampDefinitionKey(e,`tool:${e.description}`),e}function defineDynamic(t){let n={kind:DYNAMIC_SENTINEL_KIND,events:t.events};return stampDefinitionKey(n,`dynamic:${Object.keys(t.events).join(`,`)}`),n}const DISABLED_TOOL_SENTINEL_KIND=`eve:disabled-tool`;function disableTool(){return{kind:DISABLED_TOOL_SENTINEL_KIND}}function isDisabledToolSentinel(e){return typeof e==`object`&&!!e&&e.kind===DISABLED_TOOL_SENTINEL_KIND}const EXPERIMENTAL_WORKFLOW_TOOL_KIND=`eve:enable-workflow-tool`;function experimental_workflow(e={}){let t={kind:EXPERIMENTAL_WORKFLOW_TOOL_KIND};return e.maxSubagents!==void 0&&(t.maxSubagents=e.maxSubagents),t}function isExperimentalWorkflowToolDefinition(e){return typeof e==`object`&&!!e&&e.kind===EXPERIMENTAL_WORKFLOW_TOOL_KIND}export{defineDynamic,defineTool,disableTool,experimental_workflow,isDisabledToolSentinel,isExperimentalWorkflowToolDefinition};
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Core agent authoring helpers for `agent/agent.ts`.
3
3
  */
4
- export { type AgentCompactionDefinition, type AgentDefinition, type AgentExperimentalDefinition, type AgentLimitsDefinition, type AgentModelDefinition, type AgentModelOptionsDefinition, type AgentReasoningDefinition, type AgentWorkflowDefinition, type AgentWorkflowWorldDefinition, type DefinedAgent, type DynamicSubagentDefinition, type DynamicLocalSubagentDefinition, defineAgent, defineDynamic, } from "#public/definitions/agent.js";
4
+ export { type AgentCompactionDefinition, type AgentDefinition, type AgentExperimentalDefinition, type AgentLimitsDefinition, type AgentModelDefinition, type AgentModelOptionsDefinition, type AgentReasoningDefinition, type AgentStaticModelDefinition, type AgentWorkflowDefinition, type AgentWorkflowWorldDefinition, type DefinedAgent, type DynamicSubagentDefinition, type DynamicLocalSubagentDefinition, defineAgent, defineDynamic, } from "#public/definitions/agent.js";
5
5
  export type { DynamicResolveContext, DynamicSentinel } from "#shared/dynamic-tool-definition.js";
6
6
  export { type RemoteAgentDefinition, type RemoteAgentDefinitionInput, type RemoteAgentUrl, defineRemoteAgent, } from "#public/definitions/remote-agent.js";
@@ -1,5 +1,5 @@
1
1
  import type { PreparedRuntimeTool } from "#runtime/sessions/turn.js";
2
- import type { ResolvedAgent } from "#runtime/types.js";
2
+ import type { ResolvedAgent, ResolvedAgentDefinition } from "#runtime/types.js";
3
3
  import type { WorkspaceRuntimeSpec } from "#runtime/workspace/types.js";
4
4
  import type { InternalAgentModelDefinition } from "#shared/agent-definition.js";
5
5
  import type { ModuleSourceRef } from "#shared/source-ref.js";
@@ -22,7 +22,7 @@ export type RuntimeDynamicModelReference = Readonly<ModuleSourceRef & {
22
22
  /**
23
23
  * Minimal runtime-owned agent shape prepared for one harness turn.
24
24
  */
25
- export interface RuntimeTurnAgent {
25
+ interface RuntimeTurnAgentBase {
26
26
  readonly availableSkills?: readonly AvailableSkillDescription[];
27
27
  readonly id: string;
28
28
  readonly instructions: readonly string[];
@@ -32,14 +32,25 @@ export interface RuntimeTurnAgent {
32
32
  * When omitted, the harness uses the active turn model for compaction.
33
33
  */
34
34
  readonly compactionModel?: RuntimeModelReference;
35
- readonly dynamicModel?: RuntimeDynamicModelReference;
36
- readonly model: RuntimeModelReference;
37
35
  readonly nodeId?: string;
38
- readonly outputSchema?: ResolvedAgent["config"]["outputSchema"];
39
- readonly reasoning?: ResolvedAgent["config"]["reasoning"];
36
+ readonly outputSchema?: ResolvedAgentDefinition["outputSchema"];
37
+ readonly reasoning?: ResolvedAgentDefinition["reasoning"];
40
38
  readonly tools: readonly PreparedRuntimeTool[];
41
39
  readonly workspaceSpec: WorkspaceRuntimeSpec;
42
40
  }
41
+ export type RuntimeTurnAgent = RuntimeTurnAgentBase & ({
42
+ readonly configResolver?: never;
43
+ readonly dynamicModel?: never;
44
+ readonly model: RuntimeModelReference;
45
+ } | {
46
+ readonly dynamicModel: RuntimeDynamicModelReference;
47
+ readonly configResolver?: never;
48
+ readonly model?: never;
49
+ } | {
50
+ readonly configResolver: true;
51
+ readonly dynamicModel?: never;
52
+ readonly model?: never;
53
+ });
43
54
  /**
44
55
  * Static system prompt for the bootstrap runtime path.
45
56
  */
@@ -50,6 +61,8 @@ export declare const BOOTSTRAP_RUNTIME_SYSTEM_PROMPT = "You are the eve bootstra
50
61
  */
51
62
  export declare function createResolvedRuntimeTurnAgent(input: {
52
63
  readonly agent: ResolvedAgent;
64
+ readonly id?: string;
53
65
  readonly nodeId?: string;
54
66
  readonly tools: readonly PreparedRuntimeTool[];
55
67
  }): RuntimeTurnAgent;
68
+ export {};
@@ -1 +1 @@
1
- import{AGENT_TOOL_NAME,isImplicitAgentToolAvailable}from"#runtime/framework-tools/agent.js";import{composeRuntimeBasePrompt}from"#runtime/prompt/compose.js";const BOOTSTRAP_RUNTIME_MODEL_ID=`eve-bootstrap-model`,BOOTSTRAP_RUNTIME_SYSTEM_PROMPT=`You are the eve bootstrap agent. Be concise, stay grounded in the current conversation, and do not assume tools are available unless the runtime provides them.`;function createResolvedRuntimeTurnAgent(n){let r=n.agent,i=n.tools.some(e=>e.kind===`subagent`||e.kind===`remote`),a=isImplicitAgentToolAvailable({disabledFrameworkTools:r.disabledFrameworkTools,hasAuthoredAgentTool:n.tools.some(t=>t.name===AGENT_TOOL_NAME),nodeId:n.nodeId});return{availableSkills:r.skills.map(e=>({description:e.description,name:e.name})),id:r.config.name,instructions:composeRuntimeBasePrompt({connections:r.connections,instructions:r.instructions,persistentSubagentSessions:r.config.experimental?.subagentPersistentSessions===!0,subagentsAvailable:i||a,toolsAvailable:n.tools.length>0||a,workspaceSpec:r.workspaceSpec}),compactionModel:r.config.compaction?.model,dynamicModel:r.config.dynamicModel,model:r.config.model,nodeId:n.nodeId,outputSchema:r.config.outputSchema,reasoning:r.config.reasoning,tools:[...n.tools],workspaceSpec:r.workspaceSpec}}export{BOOTSTRAP_RUNTIME_MODEL_ID,BOOTSTRAP_RUNTIME_SYSTEM_PROMPT,createResolvedRuntimeTurnAgent};
1
+ import{AGENT_TOOL_NAME,isImplicitAgentToolAvailable}from"#runtime/framework-tools/agent.js";import{composeRuntimeBasePrompt}from"#runtime/prompt/compose.js";const BOOTSTRAP_RUNTIME_MODEL_ID=`eve-bootstrap-model`,BOOTSTRAP_RUNTIME_SYSTEM_PROMPT=`You are the eve bootstrap agent. Be concise, stay grounded in the current conversation, and do not assume tools are available unless the runtime provides them.`;function createResolvedRuntimeTurnAgent(n){let r=n.agent,i=r.config,a=n.id??i?.name;if(a===void 0)throw Error(`Expected a path-derived agent id while resolving agent resources.`);let o=n.tools.some(e=>e.kind===`subagent`||e.kind===`remote`),s=isImplicitAgentToolAvailable({disabledFrameworkTools:r.disabledFrameworkTools,hasAuthoredAgentTool:n.tools.some(t=>t.name===AGENT_TOOL_NAME),nodeId:n.nodeId}),c={availableSkills:r.skills.map(e=>({description:e.description,name:e.name})),id:a,instructions:composeRuntimeBasePrompt({connections:r.connections,instructions:r.instructions,persistentSubagentSessions:i?.experimental?.subagentPersistentSessions===!0,subagentsAvailable:o||s,toolsAvailable:n.tools.length>0||s,workspaceSpec:r.workspaceSpec}),compactionModel:i?.compaction?.model,nodeId:n.nodeId,outputSchema:i?.outputSchema,reasoning:i?.reasoning,tools:[...n.tools],workspaceSpec:r.workspaceSpec};return i===void 0?{...c,configResolver:!0}:i.dynamicModel===void 0?{...c,model:i.model}:{...c,dynamicModel:i.dynamicModel}}export{BOOTSTRAP_RUNTIME_MODEL_ID,BOOTSTRAP_RUNTIME_SYSTEM_PROMPT,createResolvedRuntimeTurnAgent};
@@ -0,0 +1,10 @@
1
+ export interface RuntimeModelMetadata {
2
+ readonly contextWindowTokens: number;
3
+ readonly maxOutputTokens?: number;
4
+ readonly resolvedModelId: string;
5
+ }
6
+ export interface RuntimeModelCatalog {
7
+ getByGatewayId(modelId: string): Promise<RuntimeModelMetadata | null>;
8
+ getByProviderModelId(provider: string, providerModelId: string): Promise<RuntimeModelMetadata | null>;
9
+ }
10
+ export declare function createRuntimeModelCatalog(fetchCatalog?: typeof globalThis.fetch): RuntimeModelCatalog;
@@ -0,0 +1 @@
1
+ import{AI_GATEWAY_MODELS_CATALOG_URL,vercelGatewayFetch}from"#internal/gateway.js";import{findCatalogModelByProviderModelId,findCatalogModelBySlug,modelCatalogLimitsFromProvider,modelCatalogResponseSchema}from"#internal/model-catalog.js";function createRuntimeModelCatalog(i=vercelGatewayFetch){let a=null,loadCatalog=async()=>(a===null&&(a=i(AI_GATEWAY_MODELS_CATALOG_URL).then(async e=>{if(!e.ok)throw Error(`AI Gateway model catalog request failed with HTTP ${e.status} ${e.statusText}.`);return parseCatalogResponse(await e.json())}).catch(e=>{throw a=null,e})),await a);return{async getByGatewayId(e){let t=findCatalogModelBySlug((await loadCatalog()).models,e);if(t===void 0)return null;for(let e of t.providers){let n=modelCatalogLimitsFromProvider(e);if(n!==null)return{...n,resolvedModelId:t.slug}}return null},async getByProviderModelId(e,t){let r=await loadCatalog(),i=findCatalogModelByProviderModelId({models:r.models,provider:e,providerAliases:r.providerAliases,providerModelId:t});if(i===null)return null;let a=modelCatalogLimitsFromProvider(i.provider);return a===null?null:{...a,resolvedModelId:i.model.slug}}}}function parseCatalogResponse(e){let t=modelCatalogResponseSchema.safeParse(e);if(!t.success)throw Error(`AI Gateway model catalog response did not match the expected schema.`);return t.data}export{createRuntimeModelCatalog};
@@ -1,8 +1,10 @@
1
1
  import type { LanguageModel } from "ai";
2
2
  import type { CompiledModuleMap } from "#compiler/module-map.js";
3
+ import type { ContextAccessor } from "#context/key.js";
3
4
  import type { RuntimeDynamicModelReference, RuntimeModelReference } from "#runtime/agent/bootstrap.js";
4
5
  import { shouldMockAuthoredRuntimeModels } from "#runtime/agent/mock-model-adapter.js";
5
6
  import { type PublicAgentDynamicModelDefinition, type PublicAgentDynamicModelResult } from "#shared/agent-definition.js";
7
+ import { type RuntimeModelCatalog } from "#runtime/agent/model-catalog.js";
6
8
  export { shouldMockAuthoredRuntimeModels };
7
9
  /** Loaded compiled-module scope used to resolve source-backed runtime models. */
8
10
  export interface RuntimeModelResolutionScope {
@@ -22,8 +24,10 @@ export declare function loadDynamicRuntimeModelDefinition(input: {
22
24
  readonly dynamicModel: RuntimeDynamicModelReference;
23
25
  readonly scope: RuntimeModelResolutionScope;
24
26
  }): Promise<PublicAgentDynamicModelDefinition>;
25
- export declare function normalizeDynamicRuntimeModelResult(input: {
26
- readonly fallback: RuntimeModelReference;
27
- readonly result: NonNullable<PublicAgentDynamicModelResult>;
28
- }): ResolvedRuntimeModelSelection;
27
+ export declare function resolveRuntimeModelSelection(input: {
28
+ readonly catalog?: RuntimeModelCatalog;
29
+ readonly durability: "durable" | "live";
30
+ readonly selection: PublicAgentDynamicModelResult;
31
+ readonly state: ContextAccessor;
32
+ }): Promise<ResolvedRuntimeModelSelection>;
29
33
  export declare function isRuntimeLanguageModel(value: unknown): value is LanguageModel;
@@ -1 +1 @@
1
- import{normalizeAgentDefinition}from"#internal/authored-definition/core.js";import{formatLanguageModelGatewayId}from"#internal/runtime-model.js";import{parseJsonObject}from"#shared/json.js";import{isDynamicModelDefinition}from"#shared/agent-definition.js";import{loadResolvedModuleExport}from"#runtime/resolve-helpers.js";import{resolveBootstrapRuntimeModel}from"#runtime/agent/bootstrap-model.js";import{resolveMockAuthoredRuntimeModel,shouldMockAuthoredRuntimeModels}from"#runtime/agent/mock-model-adapter.js";async function resolveRuntimeModelReference(e,t){let n=resolveBootstrapRuntimeModel(e);if(n!==null)return n;let r=resolveMockAuthoredRuntimeModel(e);return r===null?isSourceBackedRuntimeModelReference(e)?await loadSourceBackedRuntimeModelReference(e,t):e.id:r}async function loadSourceBackedRuntimeModelReference(t,n){if(n===void 0)throw Error(`Expected a compiled module-map scope to resolve the authored runtime model "${t.id}".`);let a=normalizeAgentDefinition(await loadResolvedModuleExport({definition:t.source,kindLabel:`runtime model "${t.id}"`,moduleMap:n.moduleMap,nodeId:n.nodeId}),`Expected the authored agent config export "${t.source.exportName??`default`}" from "${t.source.logicalPath}" to match the public eve shape.`).model;if(a===void 0)throw Error(`Expected the authored agent config export "${t.source.exportName??`default`}" from "${t.source.logicalPath}" to provide a runtime model.`);return isDynamicModelDefinition(a)?a.fallback:a}function isSourceBackedRuntimeModelReference(e){return e.source!==void 0}async function loadDynamicRuntimeModelDefinition(t){let n=normalizeAgentDefinition(await loadResolvedModuleExport({definition:t.dynamicModel,kindLabel:`dynamic runtime model`,moduleMap:t.scope.moduleMap,nodeId:t.scope.nodeId}),`Expected the authored agent config export "${t.dynamicModel.exportName??`default`}" from "${t.dynamicModel.logicalPath}" to match the public eve shape.`).model;if(!isDynamicModelDefinition(n))throw Error(`Expected the authored agent config export "${t.dynamicModel.exportName??`default`}" from "${t.dynamicModel.logicalPath}" to provide a dynamic model definition.`);return n}function normalizeDynamicRuntimeModelResult(e){let n=normalizeDynamicModelSelection(e.result);validateDynamicModelSelection(n);let r=n.modelOptions?.providerOptions===void 0?e.fallback.providerOptions:parseProviderOptionsRecord(n.modelOptions.providerOptions),i=n.modelContextWindowTokens;return typeof n.model==`string`?{reference:{id:formatLanguageModelGatewayId(n.model),contextWindowTokens:i,providerOptions:r}}:(validateRuntimeLanguageModel(n.model),{model:n.model,reference:{id:formatLanguageModelGatewayId(n.model),contextWindowTokens:i,providerOptions:r}})}const DYNAMIC_MODEL_SELECTION_KEYS=new Set([`model`,`modelContextWindowTokens`,`modelOptions`]);function validateDynamicModelSelection(e){let t=Object.keys(e).filter(e=>!DYNAMIC_MODEL_SELECTION_KEYS.has(e));if(t.length>0)throw Error(`Dynamic model resolver returned a selection with unknown key(s): ${t.join(`, `)}. Expected { model, modelContextWindowTokens?, modelOptions? }.`);let n=e.modelContextWindowTokens;if(n!==void 0&&(!Number.isInteger(n)||n<=0))throw Error(`Dynamic model resolver returned an invalid modelContextWindowTokens value. Expected a positive integer.`)}function normalizeDynamicModelSelection(e){return isModelSelectionDefinition(e)?e:{model:e}}function isModelSelectionDefinition(e){return typeof e==`object`&&!!e&&`model`in e&&!isRuntimeLanguageModel(e)}function validateRuntimeLanguageModel(e){if(!isRuntimeLanguageModel(e))throw Error(`Dynamic model resolver returned an invalid model. Return an AI Gateway model id string, an AI SDK language model, or { model, modelContextWindowTokens?, modelOptions? }.`)}function isRuntimeLanguageModel(e){if(typeof e!=`object`||!e)return!1;let t=e;return(t.specificationVersion===`v2`||t.specificationVersion===`v3`||t.specificationVersion===`v4`)&&typeof t.provider==`string`&&typeof t.modelId==`string`&&typeof t.doGenerate==`function`&&typeof t.doStream==`function`}function parseProviderOptionsRecord(e){if(e===void 0)return;let t={};for(let[r,i]of Object.entries(e))t[r]=parseJsonObject(i);return t}export{isRuntimeLanguageModel,loadDynamicRuntimeModelDefinition,normalizeDynamicRuntimeModelResult,resolveRuntimeModelReference,shouldMockAuthoredRuntimeModels};
1
+ import{RuntimeModelMetadataCacheKey}from"#context/keys.js";import{normalizeCatalogModelId}from"#internal/model-catalog.js";import{normalizeAgentDefinition}from"#internal/authored-definition/core.js";import{formatLanguageModelGatewayId}from"#internal/runtime-model.js";import{parseJsonObject}from"#shared/json.js";import{isDynamicModelDefinition}from"#shared/agent-definition.js";import{loadResolvedModuleExport}from"#runtime/resolve-helpers.js";import{resolveBootstrapRuntimeModel}from"#runtime/agent/bootstrap-model.js";import{resolveMockAuthoredRuntimeModel,shouldMockAuthoredRuntimeModels}from"#runtime/agent/mock-model-adapter.js";import{createRuntimeModelCatalog}from"#runtime/agent/model-catalog.js";async function resolveRuntimeModelReference(e,t){let n=resolveBootstrapRuntimeModel(e);if(n!==null)return n;let r=resolveMockAuthoredRuntimeModel(e);return r===null?isSourceBackedRuntimeModelReference(e)?await loadSourceBackedRuntimeModelReference(e,t):e.id:r}async function loadSourceBackedRuntimeModelReference(e,t){if(t===void 0)throw Error(`Expected a compiled module-map scope to resolve the authored runtime model "${e.id}".`);let r=normalizeAgentDefinition(await loadResolvedModuleExport({definition:e.source,kindLabel:`runtime model "${e.id}"`,moduleMap:t.moduleMap,nodeId:t.nodeId}),`Expected the authored agent config export "${e.source.exportName??`default`}" from "${e.source.logicalPath}" to match the public eve shape.`).model;if(r===void 0)throw Error(`Expected the authored agent config export "${e.source.exportName??`default`}" from "${e.source.logicalPath}" to provide a runtime model.`);if(isDynamicModelDefinition(r))throw Error(`Expected the authored agent config export "${e.source.exportName??`default`}" from "${e.source.logicalPath}" to provide a static runtime model.`);return r}function isSourceBackedRuntimeModelReference(e){return e.source!==void 0}async function loadDynamicRuntimeModelDefinition(e){let t=normalizeAgentDefinition(await loadResolvedModuleExport({definition:e.dynamicModel,kindLabel:`dynamic runtime model`,moduleMap:e.scope.moduleMap,nodeId:e.scope.nodeId}),`Expected the authored agent config export "${e.dynamicModel.exportName??`default`}" from "${e.dynamicModel.logicalPath}" to match the public eve shape.`).model;if(!isDynamicModelDefinition(t))throw Error(`Expected the authored agent config export "${e.dynamicModel.exportName??`default`}" from "${e.dynamicModel.logicalPath}" to provide a dynamic model definition.`);return t}async function resolveRuntimeModelSelection(e){if(e.selection===null||e.selection===void 0)throw Error(`Dynamic model resolver returned no model. Every matching dynamic model handler must return a concrete model selection.`);let n=normalizeDynamicModelSelection(e.selection);validateDynamicModelSelection(n);let i=n.modelOptions?.providerOptions===void 0?void 0:parseProviderOptionsRecord(n.modelOptions.providerOptions),a=n.model,o=e.catalog??runtimeModelCatalogForState(e.state);if(typeof a==`string`){let s=formatLanguageModelGatewayId(a),c=await resolveSelectionMetadata({cacheKey:`gateway:${normalizeCatalogModelId(s)}`,catalog:o,contextWindowTokens:n.modelContextWindowTokens,load:e=>e.getByGatewayId(s),modelLabel:s,state:e.state});return{reference:{id:c.resolvedModelId,contextWindowTokens:c.contextWindowTokens,maxOutputTokens:c.maxOutputTokens,providerOptions:i}}}if(validateRuntimeLanguageModel(a),e.durability===`durable`)throw Error(`Dynamic model selection returned a provider object, but durable model selections must be serializable. Return a model id string, or use a "step.started" model resolver.`);let s=formatLanguageModelGatewayId(a),c=a.provider.split(`.`)[0],l=await resolveSelectionMetadata({cacheKey:c===`gateway`?`gateway:${normalizeCatalogModelId(a.modelId)}`:`provider:${a.provider}:${normalizeCatalogModelId(a.modelId)}`,catalog:o,contextWindowTokens:n.modelContextWindowTokens,load:e=>c===`gateway`?e.getByGatewayId(a.modelId):e.getByProviderModelId(a.provider,a.modelId),modelLabel:s,state:e.state});return{model:a,reference:{id:l.resolvedModelId,contextWindowTokens:l.contextWindowTokens,maxOutputTokens:l.maxOutputTokens,providerOptions:i}}}const runtimeModelCatalogsByState=new WeakMap;function runtimeModelCatalogForState(e){let t=runtimeModelCatalogsByState.get(e);if(t!==void 0)return t;let n=createRuntimeModelCatalog();return runtimeModelCatalogsByState.set(e,n),n}async function resolveSelectionMetadata(t){if(t.contextWindowTokens!==void 0)return{contextWindowTokens:t.contextWindowTokens,resolvedModelId:t.modelLabel};let n=Date.now(),r=t.state.get(RuntimeModelMetadataCacheKey)?.[t.cacheKey];if(r!==void 0&&r.expiresAt>n)return r;let i=await t.load(t.catalog);if(i===null)throw Error(`Cannot select model "${t.modelLabel}" because AI Gateway did not provide context window metadata. Return modelContextWindowTokens with this selection for an unlisted or custom model.`);let a={...i,expiresAt:n+864e5};return t.state.set(RuntimeModelMetadataCacheKey,e=>({...Object.fromEntries(Object.entries(e??{}).filter(([,e])=>e.expiresAt>n)),[t.cacheKey]:a})),a}const DYNAMIC_MODEL_SELECTION_KEYS=new Set([`model`,`modelContextWindowTokens`,`modelOptions`]);function validateDynamicModelSelection(e){let t=Object.keys(e).filter(e=>!DYNAMIC_MODEL_SELECTION_KEYS.has(e));if(t.length>0)throw Error(`Dynamic model resolver returned a selection with unknown key(s): ${t.join(`, `)}. Expected { model, modelContextWindowTokens?, modelOptions? }.`);let n=e.modelContextWindowTokens;if(n!==void 0&&(!Number.isInteger(n)||n<=0))throw Error(`Dynamic model resolver returned an invalid modelContextWindowTokens value. Expected a positive integer.`);if(typeof e.model==`string`&&e.model.trim()===``)throw Error(`Dynamic model resolver returned an empty model id.`)}function normalizeDynamicModelSelection(e){return isModelSelectionDefinition(e)?e:{model:e}}function isModelSelectionDefinition(e){return typeof e==`object`&&!!e&&`model`in e&&!isRuntimeLanguageModel(e)}function validateRuntimeLanguageModel(e){if(!isRuntimeLanguageModel(e))throw Error(`Dynamic model resolver returned an invalid model. Return an AI Gateway model id string, an AI SDK language model, or { model, modelContextWindowTokens?, modelOptions? }.`)}function isRuntimeLanguageModel(e){if(typeof e!=`object`||!e)return!1;let t=e;return(t.specificationVersion===`v2`||t.specificationVersion===`v3`||t.specificationVersion===`v4`)&&typeof t.provider==`string`&&typeof t.modelId==`string`&&typeof t.doGenerate==`function`&&typeof t.doStream==`function`}function parseProviderOptionsRecord(e){if(e===void 0)return;let t={};for(let[n,r]of Object.entries(e))t[n]=parseJsonObject(r);return t}export{isRuntimeLanguageModel,loadDynamicRuntimeModelDefinition,resolveRuntimeModelReference,resolveRuntimeModelSelection,shouldMockAuthoredRuntimeModels};
@@ -1 +1 @@
1
- import{localDev,placeholderAuth,vercelOidc}from"#public/channels/auth.js";import{isHttpRouteDefinition}from"#channel/routes.js";import{eveChannel}from"#public/channels/eve.js";import{getConnectionCallbackChannelDefinitions,getConnectionCallbackChannelNames}from"#runtime/connections/callback-route.js";import{getSessionCallbackChannelDefinitions,getSessionCallbackChannelNames}from"#runtime/session-callback-route.js";function getFrameworkChannelDefinitions(){let r=eveChannel({auth:[vercelOidc(),localDev(),placeholderAuth()]}),i=[];for(let e of r.routes)isHttpRouteDefinition(e)&&i.push({name:`eve`,method:e.method.toUpperCase(),urlPath:e.path,cors:r.cors,fetch:async(t,n)=>e.handler(t,n),handler:e.handler,adapter:r.adapter,logicalPath:`framework://channels/${e.path}`,sourceId:`eve:framework:${e.method.toLowerCase()}-${e.path}`,sourceKind:`module`});return i.push(...getConnectionCallbackChannelDefinitions(),...getSessionCallbackChannelDefinitions()),i}function getAllFrameworkChannelNames(){return new Set([`eve`,...getConnectionCallbackChannelNames(),...getSessionCallbackChannelNames()])}export{getAllFrameworkChannelNames,getFrameworkChannelDefinitions};
1
+ import{localDev,placeholderAuth,vercelOidc}from"#public/channels/auth.js";import{isHttpRouteDefinition}from"#channel/routes.js";import{eveChannel}from"#public/channels/eve.js";import{getConnectionCallbackChannelDefinitions,getConnectionCallbackChannelNames}from"#runtime/connections/callback-route.js";import{getSessionCallbackChannelDefinitions,getSessionCallbackChannelNames}from"#runtime/session-callback-route.js";function getFrameworkChannelDefinitions(){let r=eveChannel({auth:[vercelOidc(),localDev(),placeholderAuth()]}),i=[];for(let e of r.routes)isHttpRouteDefinition(e)&&i.push({name:`eve`,method:e.method.toUpperCase(),urlPath:e.path,cors:r.cors,fetch:async(t,n)=>e.handler(t,n),handler:e.handler,adapter:r.adapter,turnPolicy:r.turnPolicy,logicalPath:`framework://channels/${e.path}`,sourceId:`eve:framework:${e.method.toLowerCase()}-${e.path}`,sourceKind:`module`});return i.push(...getConnectionCallbackChannelDefinitions(),...getSessionCallbackChannelDefinitions()),i}function getAllFrameworkChannelNames(){return new Set([`eve`,...getConnectionCallbackChannelNames(),...getSessionCallbackChannelNames()])}export{getAllFrameworkChannelNames,getFrameworkChannelDefinitions};
@@ -1 +1 @@
1
- import{expectObjectRecord}from"#internal/authored-module.js";import{ROOT_COMPILED_AGENT_NODE_ID}from"#compiler/manifest.js";import{createRuntimeSubagentRegistry}from"#runtime/subagents/registry.js";import{LOAD_SKILL_TOOL_NAME}from"#runtime/skills/fragment-context.js";import{createRuntimeToolRegistry}from"#runtime/tools/registry.js";import{ROOT_RUNTIME_AGENT_NODE_ID}from"#runtime/graph.js";import{WORKFLOW_TOOL_NAME}from"#shared/workflow-sandbox.js";import{getAllFrameworkChannelNames,getFrameworkChannelDefinitions}from"#runtime/framework-channels/index.js";import{getAllFrameworkToolNames,getFrameworkDynamicToolResolvers,getFrameworkToolDefinitions}from"#runtime/framework-tools/index.js";import{resolveAgent}from"#runtime/resolve-agent.js";import{loadResolvedModuleExport}from"#runtime/resolve-helpers.js";import{createResolvedRuntimeTurnAgent}from"#runtime/agent/bootstrap.js";import{createRuntimeHookRegistry}from"#runtime/hooks/registry.js";import{resolveDynamicSubagentDefinition}from"#runtime/resolve-dynamic-subagent.js";import{createRuntimeSandboxRegistry}from"#runtime/sandbox/registry.js";var ResolveRuntimeAgentGraphError=class extends Error{logicalPath;nodeId;sourceId;constructor(e,t={}){super(e),this.name=`ResolveRuntimeAgentGraphError`,t.logicalPath!==void 0&&(this.logicalPath=t.logicalPath),t.nodeId!==void 0&&(this.nodeId=t.nodeId),t.sourceId!==void 0&&(this.sourceId=t.sourceId)}};async function resolveRuntimeAgentGraph(e){let n=new Map,r=createChildNodeIdsByParentNodeId(e.manifest),i=new Map(e.manifest.subagents.map(e=>[e.nodeId,e]));return{nodesByNodeId:n,root:await resolveRuntimeAgentNode({childNodeIdsByParentNodeId:r,manifest:e.manifest,moduleMap:e.moduleMap,nodeId:ROOT_COMPILED_AGENT_NODE_ID,nodesByNodeId:n,subagentNodesById:i})}}async function resolveRuntimeAgentNode(e){let t=toRuntimeNodeId(e.nodeId);if(e.nodesByNodeId.has(t))throw new ResolveRuntimeAgentGraphError(`Found multiple runtime agent nodes for node id "${t}".`,{nodeId:t,sourceId:e.sourceId});let a=await resolveAgent({manifest:e.manifest,moduleMap:e.moduleMap,nodeId:e.nodeId}),o=getFrameworkToolDefinitions({authoredSkills:a.skills}),s=new Set(o.map(e=>e.name)),c=getAllFrameworkToolNames(),l=new Set(a.tools.map(e=>e.name));for(let n of a.disabledFrameworkTools)if(!c.has(n))throw new ResolveRuntimeAgentGraphError(`agent/tools/${n}.ts exports disableTool() but "${n}" is not a framework tool. Rename the file to one of: ${[...c].sort().join(`, `)}.`,{nodeId:t,sourceId:e.sourceId});let u=new Set(a.disabledFrameworkTools),d=await createRuntimeToolRegistry({tools:[...o.filter(e=>!l.has(e.name)&&!u.has(e.name)),...a.tools]},{reservedToolNames:[WORKFLOW_TOOL_NAME,...s.has(LOAD_SKILL_TOOL_NAME)||l.has(LOAD_SKILL_TOOL_NAME)?[]:[LOAD_SKILL_TOOL_NAME]]}),f=new Set(a.channels.map(e=>e.name)),p=getAllFrameworkChannelNames();for(let n of a.disabledFrameworkChannels)if(!p.has(n))throw new ResolveRuntimeAgentGraphError(`agent/channels/${n}.ts exports disableRoute() but "${n}" is not a framework channel. Rename the file to one of: ${[...p].sort().join(`, `)}.`,{nodeId:t,sourceId:e.sourceId});let m=new Set(a.disabledFrameworkChannels),h=[...getFrameworkChannelDefinitions().filter(e=>!f.has(e.name)&&!m.has(e.name)),...a.channels],g=createRuntimeSandboxRegistry({authoredSandbox:a.sandbox,workspaceResourceRoot:a.workspaceResourceRoot}),_=createRuntimeSubagentRegistry({persistentSessions:a.config.experimental?.subagentPersistentSessions===!0,reservedToolNames:[LOAD_SKILL_TOOL_NAME,...d.preparedTools.map(e=>e.name)],subagents:await resolveRuntimeSubagents({childNodeIdsByParentNodeId:e.childNodeIdsByParentNodeId,manifest:e.manifest,moduleMap:e.moduleMap,nodesByNodeId:e.nodesByNodeId,parentNodeId:e.nodeId,subagentNodesById:e.subagentNodesById})}),v={...a,dynamicToolResolvers:[...a.dynamicToolResolvers,...getFrameworkDynamicToolResolvers()]},y={agent:v,channels:h,hookRegistry:createRuntimeHookRegistry(v.hooks),nodeId:t,sandboxRegistry:g,sourceId:e.sourceId,subagentRegistry:_,toolRegistry:d,turnAgent:createResolvedRuntimeTurnAgent({agent:v,nodeId:t,tools:[...d.preparedTools,..._.preparedTools]})};return e.nodesByNodeId.set(t,y),y}async function resolveRuntimeSubagents(e){let t=[],n=e.childNodeIdsByParentNodeId.get(e.parentNodeId)??[];for(let r of n){let n=e.subagentNodesById.get(r);if(n===void 0)throw new ResolveRuntimeAgentGraphError(`Missing compiled subagent node "${r}" while resolving runtime subagents.`,{nodeId:toRuntimeNodeId(e.parentNodeId),sourceId:r});t.push(await resolveRuntimeSubagent({childNodeIdsByParentNodeId:e.childNodeIdsByParentNodeId,moduleMap:e.moduleMap,nodesByNodeId:e.nodesByNodeId,sourceRef:n,subagentNodesById:e.subagentNodesById}))}for(let n of e.manifest.remoteAgents)t.push(await resolveRuntimeRemoteAgent({moduleMap:e.moduleMap,nodeScopeId:e.parentNodeId,sourceRef:n}));return t}async function resolveRuntimeSubagent(e){let t=e.sourceRef.agent.config.source;if(e.sourceRef.dynamic!==void 0&&t===void 0)throw new ResolveRuntimeAgentGraphError(`Dynamic subagent "${e.sourceRef.logicalPath}" is missing its agent config source.`,{nodeId:toRuntimeNodeId(e.sourceRef.nodeId),sourceId:e.sourceRef.sourceId});let n={...e.sourceRef.dynamic===void 0?{description:e.sourceRef.description}:{dynamic:await resolveDynamicSubagentDefinition({definition:{...t,...e.sourceRef.dynamic},moduleMap:e.moduleMap,nodeId:e.sourceRef.nodeId})},kind:`subagent`,logicalPath:e.sourceRef.logicalPath,name:e.sourceRef.name,nodeId:toRuntimeNodeId(e.sourceRef.nodeId),sourceId:e.sourceRef.sourceId,sourceKind:`module`};return await resolveRuntimeAgentNode({childNodeIdsByParentNodeId:e.childNodeIdsByParentNodeId,manifest:e.sourceRef.agent,moduleMap:e.moduleMap,nodeId:e.sourceRef.nodeId,nodesByNodeId:e.nodesByNodeId,sourceId:e.sourceRef.sourceId,subagentNodesById:e.subagentNodesById}),n}async function resolveRuntimeRemoteAgent(t){let n=expectObjectRecord(await loadResolvedModuleExport({definition:t.sourceRef,kindLabel:`remote agent`,moduleMap:t.moduleMap,nodeId:t.nodeScopeId}),`Expected remote agent source "${t.sourceRef.logicalPath}" to export an object.`),r={description:t.sourceRef.description,kind:`remote`,logicalPath:t.sourceRef.logicalPath,name:t.sourceRef.name,nodeId:toRuntimeNodeId(t.sourceRef.nodeId),outputSchema:t.sourceRef.outputSchema,path:t.sourceRef.path,sourceId:t.sourceRef.sourceId,sourceKind:`module`,url:await resolveRemoteAgentUrl({bakedUrl:t.sourceRef.url,logicalPath:t.sourceRef.logicalPath,resolvedUrl:n.url})};typeof n.auth==`function`&&(r.auth=n.auth),n.forwardPrincipal===!0&&(r.forwardPrincipal=!0);let i=resolveRemoteAgentHeaders(n.headers);return i!==void 0&&(r.headers=i),r}async function resolveRemoteAgentUrl(e){if(typeof e.resolvedUrl==`function`){let t=await e.resolvedUrl();if(typeof t!=`string`||t.length===0)throw Error(`Remote agent "${e.logicalPath}" url function must return a non-empty string.`);return t}let t=e.bakedUrl??(typeof e.resolvedUrl==`string`?e.resolvedUrl:``);if(t.length===0)throw Error(`Remote agent "${e.logicalPath}" is missing a url.`);return t}function resolveRemoteAgentHeaders(e){if(e===void 0)return;if(typeof e==`function`)return e;if(typeof e!=`object`||!e||Array.isArray(e))return;let t={};for(let[n,r]of Object.entries(e))typeof r==`string`&&(t[n]=r);return t}function createChildNodeIdsByParentNodeId(e){let t=new Map;for(let n of e.subagentEdges){let e=t.get(n.parentNodeId);if(e===void 0){t.set(n.parentNodeId,[n.childNodeId]);continue}e.push(n.childNodeId)}return t}function toRuntimeNodeId(e){return e===ROOT_COMPILED_AGENT_NODE_ID?ROOT_RUNTIME_AGENT_NODE_ID:e}export{resolveRuntimeAgentGraph};
1
+ import{expectObjectRecord}from"#internal/authored-module.js";import{ROOT_COMPILED_AGENT_NODE_ID}from"#compiler/manifest.js";import{createRuntimeSubagentRegistry}from"#runtime/subagents/registry.js";import{LOAD_SKILL_TOOL_NAME}from"#runtime/skills/fragment-context.js";import{createRuntimeToolRegistry}from"#runtime/tools/registry.js";import{ROOT_RUNTIME_AGENT_NODE_ID}from"#runtime/graph.js";import{WORKFLOW_TOOL_NAME}from"#shared/workflow-sandbox.js";import{getAllFrameworkChannelNames,getFrameworkChannelDefinitions}from"#runtime/framework-channels/index.js";import{getAllFrameworkToolNames,getFrameworkDynamicToolResolvers,getFrameworkToolDefinitions}from"#runtime/framework-tools/index.js";import{resolveAgent}from"#runtime/resolve-agent.js";import{loadResolvedModuleExport}from"#runtime/resolve-helpers.js";import{createResolvedRuntimeTurnAgent}from"#runtime/agent/bootstrap.js";import{createRuntimeHookRegistry}from"#runtime/hooks/registry.js";import{resolveDynamicSubagentDefinition}from"#runtime/resolve-dynamic-subagent.js";import{createRuntimeSandboxRegistry}from"#runtime/sandbox/registry.js";var ResolveRuntimeAgentGraphError=class extends Error{logicalPath;nodeId;sourceId;constructor(e,t={}){super(e),this.name=`ResolveRuntimeAgentGraphError`,t.logicalPath!==void 0&&(this.logicalPath=t.logicalPath),t.nodeId!==void 0&&(this.nodeId=t.nodeId),t.sourceId!==void 0&&(this.sourceId=t.sourceId)}};async function resolveRuntimeAgentGraph(e){let n=new Map,r=createChildNodeIdsByParentNodeId(e.manifest),i=new Map(e.manifest.subagents.map(e=>[e.nodeId,e]));return{nodesByNodeId:n,root:await resolveRuntimeAgentNode({childNodeIdsByParentNodeId:r,manifest:e.manifest,moduleMap:e.moduleMap,nodeId:ROOT_COMPILED_AGENT_NODE_ID,nodesByNodeId:n,subagentNodesById:i})}}async function resolveRuntimeAgentNode(e){let t=toRuntimeNodeId(e.nodeId);if(e.nodesByNodeId.has(t))throw new ResolveRuntimeAgentGraphError(`Found multiple runtime agent nodes for node id "${t}".`,{nodeId:t,sourceId:e.sourceId});let a=await resolveAgent({manifest:e.manifest,moduleMap:e.moduleMap,nodeId:e.nodeId}),o=getFrameworkToolDefinitions({authoredSkills:a.skills}),s=new Set(o.map(e=>e.name)),c=getAllFrameworkToolNames(),l=new Set(a.tools.map(e=>e.name));for(let n of a.disabledFrameworkTools)if(!c.has(n))throw new ResolveRuntimeAgentGraphError(`agent/tools/${n}.ts exports disableTool() but "${n}" is not a framework tool. Rename the file to one of: ${[...c].sort().join(`, `)}.`,{nodeId:t,sourceId:e.sourceId});let u=new Set(a.disabledFrameworkTools),d=await createRuntimeToolRegistry({tools:[...o.filter(e=>!l.has(e.name)&&!u.has(e.name)),...a.tools]},{reservedToolNames:[WORKFLOW_TOOL_NAME,...s.has(LOAD_SKILL_TOOL_NAME)||l.has(LOAD_SKILL_TOOL_NAME)?[]:[LOAD_SKILL_TOOL_NAME]]}),f=new Set(a.channels.map(e=>e.name)),p=getAllFrameworkChannelNames();for(let n of a.disabledFrameworkChannels)if(!p.has(n))throw new ResolveRuntimeAgentGraphError(`agent/channels/${n}.ts exports disableRoute() but "${n}" is not a framework channel. Rename the file to one of: ${[...p].sort().join(`, `)}.`,{nodeId:t,sourceId:e.sourceId});let m=new Set(a.disabledFrameworkChannels),h=[...getFrameworkChannelDefinitions().filter(e=>!f.has(e.name)&&!m.has(e.name)),...a.channels],g=createRuntimeSandboxRegistry({authoredSandbox:a.sandbox,workspaceResourceRoot:a.workspaceResourceRoot}),_=createRuntimeSubagentRegistry({persistentSessions:a.config?.experimental?.subagentPersistentSessions===!0,reservedToolNames:[LOAD_SKILL_TOOL_NAME,...d.preparedTools.map(e=>e.name)],subagents:await resolveRuntimeSubagents({childNodeIdsByParentNodeId:e.childNodeIdsByParentNodeId,manifest:e.manifest,moduleMap:e.moduleMap,nodesByNodeId:e.nodesByNodeId,parentNodeId:e.nodeId,subagentNodesById:e.subagentNodesById})}),v={...a,dynamicToolResolvers:[...a.dynamicToolResolvers,...getFrameworkDynamicToolResolvers()]},y={agent:v,channels:h,hookRegistry:createRuntimeHookRegistry(v.hooks),nodeId:t,sandboxRegistry:g,sourceId:e.sourceId,subagentRegistry:_,toolRegistry:d,turnAgent:createResolvedRuntimeTurnAgent({agent:v,id:e.agentId,nodeId:t,tools:[...d.preparedTools,..._.preparedTools]})};return e.nodesByNodeId.set(t,y),y}async function resolveRuntimeSubagents(e){let t=[],n=e.childNodeIdsByParentNodeId.get(e.parentNodeId)??[];for(let r of n){let n=e.subagentNodesById.get(r);if(n===void 0)throw new ResolveRuntimeAgentGraphError(`Missing compiled subagent node "${r}" while resolving runtime subagents.`,{nodeId:toRuntimeNodeId(e.parentNodeId),sourceId:r});t.push(await resolveRuntimeSubagent({childNodeIdsByParentNodeId:e.childNodeIdsByParentNodeId,moduleMap:e.moduleMap,nodesByNodeId:e.nodesByNodeId,sourceRef:n,subagentNodesById:e.subagentNodesById}))}for(let n of e.manifest.remoteAgents)t.push(await resolveRuntimeRemoteAgent({moduleMap:e.moduleMap,nodeScopeId:e.parentNodeId,sourceRef:n}));return t}async function resolveRuntimeSubagent(e){let t={...e.sourceRef.configResolver===void 0?{description:e.sourceRef.description}:{dynamic:await resolveDynamicSubagentDefinition({definition:e.sourceRef.configResolver,moduleMap:e.moduleMap,nodeId:e.sourceRef.nodeId})},kind:`subagent`,logicalPath:e.sourceRef.logicalPath,name:e.sourceRef.name,nodeId:toRuntimeNodeId(e.sourceRef.nodeId),sourceId:e.sourceRef.sourceId,sourceKind:`module`};return await resolveRuntimeAgentNode({agentId:e.sourceRef.name,childNodeIdsByParentNodeId:e.childNodeIdsByParentNodeId,manifest:e.sourceRef.agent,moduleMap:e.moduleMap,nodeId:e.sourceRef.nodeId,nodesByNodeId:e.nodesByNodeId,sourceId:e.sourceRef.sourceId,subagentNodesById:e.subagentNodesById}),t}async function resolveRuntimeRemoteAgent(t){let n=expectObjectRecord(await loadResolvedModuleExport({definition:t.sourceRef,kindLabel:`remote agent`,moduleMap:t.moduleMap,nodeId:t.nodeScopeId}),`Expected remote agent source "${t.sourceRef.logicalPath}" to export an object.`),r={description:t.sourceRef.description,kind:`remote`,logicalPath:t.sourceRef.logicalPath,name:t.sourceRef.name,nodeId:toRuntimeNodeId(t.sourceRef.nodeId),outputSchema:t.sourceRef.outputSchema,path:t.sourceRef.path,sourceId:t.sourceRef.sourceId,sourceKind:`module`,url:await resolveRemoteAgentUrl({bakedUrl:t.sourceRef.url,logicalPath:t.sourceRef.logicalPath,resolvedUrl:n.url})};typeof n.auth==`function`&&(r.auth=n.auth),n.forwardPrincipal===!0&&(r.forwardPrincipal=!0);let i=resolveRemoteAgentHeaders(n.headers);return i!==void 0&&(r.headers=i),r}async function resolveRemoteAgentUrl(e){if(typeof e.resolvedUrl==`function`){let t=await e.resolvedUrl();if(typeof t!=`string`||t.length===0)throw Error(`Remote agent "${e.logicalPath}" url function must return a non-empty string.`);return t}let t=e.bakedUrl??(typeof e.resolvedUrl==`string`?e.resolvedUrl:``);if(t.length===0)throw Error(`Remote agent "${e.logicalPath}" is missing a url.`);return t}function resolveRemoteAgentHeaders(e){if(e===void 0)return;if(typeof e==`function`)return e;if(typeof e!=`object`||!e||Array.isArray(e))return;let t={};for(let[n,r]of Object.entries(e))typeof r==`string`&&(t[n]=r);return t}function createChildNodeIdsByParentNodeId(e){let t=new Map;for(let n of e.subagentEdges){let e=t.get(n.parentNodeId);if(e===void 0){t.set(n.parentNodeId,[n.childNodeId]);continue}e.push(n.childNodeId)}return t}function toRuntimeNodeId(e){return e===ROOT_COMPILED_AGENT_NODE_ID?ROOT_RUNTIME_AGENT_NODE_ID:e}export{resolveRuntimeAgentGraph};
@@ -1,4 +1,4 @@
1
- import type { CompiledAgentNodeManifest } from "#compiler/manifest.js";
1
+ import type { CompiledAgentNodeManifest, CompiledAgentResources } from "#compiler/manifest.js";
2
2
  import type { CompiledModuleMap } from "#compiler/module-map.js";
3
3
  export { ResolveAgentError } from "#runtime/resolve-helpers.js";
4
4
  import type { ResolvedAgent } from "#runtime/types.js";
@@ -6,7 +6,7 @@ import type { ResolvedAgent } from "#runtime/types.js";
6
6
  * Input for resolving one compiled authored agent into a runtime-owned model.
7
7
  */
8
8
  export interface ResolveAgentInput {
9
- manifest: CompiledAgentNodeManifest;
9
+ manifest: CompiledAgentNodeManifest | CompiledAgentResources;
10
10
  moduleMap: CompiledModuleMap;
11
11
  nodeId?: string;
12
12
  }
@@ -1 +1 @@
1
- import{ResolveAgentError,createResolvedModuleSourceRef}from"#runtime/resolve-helpers.js";import{resolveDynamicToolDefinition}from"#runtime/resolve-dynamic-tool.js";import{resolveChannelDefinition}from"#runtime/resolve-channel.js";import{resolveConnectionDefinition}from"#runtime/resolve-connection.js";import{resolveHookDefinition}from"#runtime/resolve-hook.js";import{resolveSandboxDefinition}from"#runtime/resolve-sandbox.js";import{resolveDynamicInstructionsDefinition}from"#runtime/resolve-dynamic-instructions.js";import{resolveDynamicSkillDefinition}from"#runtime/resolve-dynamic-skill.js";import{resolveToolDefinition}from"#runtime/resolve-tool.js";async function resolveAgent(e){let t=e.manifest.skills.map(e=>({...e,metadata:e.metadata===void 0?void 0:{...e.metadata}})),r=[],i=[];for(let t of e.manifest.channels){if(t.kind===`disabled`){i.push(t.name);continue}r.push(await resolveChannelDefinition(t,e.moduleMap,e.nodeId))}let a=await Promise.all(e.manifest.tools.map(t=>resolveToolDefinition(t,e.moduleMap,e.nodeId))),o=await Promise.all((e.manifest.dynamicInstructions??[]).map(t=>resolveDynamicInstructionsDefinition(t,e.moduleMap,e.nodeId))),s=await Promise.all((e.manifest.dynamicSkills??[]).map(t=>resolveDynamicSkillDefinition(t,e.moduleMap,e.nodeId))),c=await Promise.all(e.manifest.dynamicTools.map(t=>resolveDynamicToolDefinition(t,e.moduleMap,e.nodeId))),l=await Promise.all(e.manifest.hooks.map(t=>resolveHookDefinition(t,e.moduleMap,e.nodeId))),u=await Promise.all(e.manifest.connections.map(t=>resolveConnectionDefinition(t,e.moduleMap,e.nodeId))),d=e.manifest.sandbox===null?null:await resolveSandboxDefinition(e.manifest.sandbox,e.moduleMap,e.nodeId),f=createResolvedInstructionsDefinition(e.manifest.instructions),p=e.manifest.workspaceResourceRoot,m={channels:r,config:createResolvedAgentConfig(e.manifest),connections:u,disabledFrameworkChannels:i,disabledFrameworkTools:[...e.manifest.disabledFrameworkTools],workflowTool:e.manifest.workflowTool===void 0?void 0:{maxSubagents:e.manifest.workflowTool.maxSubagents},webSearchProvider:e.manifest.webSearchProvider,dynamicInstructionsResolvers:o,dynamicSkillResolvers:s,dynamicToolResolvers:c,hooks:l,metadata:{agentRoot:e.manifest.agentRoot,appRoot:e.manifest.appRoot,diagnosticsSummary:e.manifest.diagnosticsSummary},sandbox:d,workspaceResourceRoot:p,skills:t,tools:a,workspaceSpec:{rootEntries:[...p.rootEntries]}};return f===void 0?m:{...m,instructions:f}}function createResolvedInstructionsDefinition(e){if(e!==void 0)return{name:e.name,logicalPath:e.logicalPath,markdown:e.markdown,sourceId:e.sourceId,sourceKind:e.sourceKind}}function createResolvedAgentConfig(e){let n={model:e.config.model.source===void 0?{id:e.config.model.id,contextWindowTokens:e.config.model.contextWindowTokens,providerOptions:e.config.model.providerOptions}:{contextWindowTokens:e.config.model.contextWindowTokens,id:e.config.model.id,providerOptions:e.config.model.providerOptions,source:{exportName:e.config.model.source.exportName,sourceKind:`module`,logicalPath:e.config.model.source.logicalPath,sourceId:e.config.model.source.sourceId}},name:e.config.name};if(e.config.compaction!==void 0){let t={};e.config.compaction.model!==void 0&&(t.model=e.config.compaction.model.source===void 0?{contextWindowTokens:e.config.compaction.model.contextWindowTokens,id:e.config.compaction.model.id,providerOptions:e.config.compaction.model.providerOptions}:{contextWindowTokens:e.config.compaction.model.contextWindowTokens,id:e.config.compaction.model.id,providerOptions:e.config.compaction.model.providerOptions,source:{exportName:e.config.compaction.model.source.exportName,sourceKind:`module`,logicalPath:e.config.compaction.model.source.logicalPath,sourceId:e.config.compaction.model.source.sourceId}}),e.config.compaction.thresholdPercent!==void 0&&(t.thresholdPercent=e.config.compaction.thresholdPercent),n.compaction=t}return e.config.dynamicModel!==void 0&&(n.dynamicModel={...createResolvedModuleSourceRef(e.config.dynamicModel),eventNames:[...e.config.dynamicModel.eventNames]}),e.config.experimental!==void 0&&(n.experimental={subagentPersistentSessions:e.config.experimental.subagentPersistentSessions,workflow:e.config.experimental.workflow===void 0?void 0:{world:e.config.experimental.workflow.world}}),e.config.outputSchema!==void 0&&(n.outputSchema=e.config.outputSchema),e.config.reasoning!==void 0&&(n.reasoning=e.config.reasoning),e.config.source!==void 0&&(n.source=createResolvedModuleSourceRef(e.config.source)),e.config.limits!==void 0&&(n.limits={maxInputTokensPerSession:e.config.limits.maxInputTokensPerSession,maxOutputTokensPerSession:e.config.limits.maxOutputTokensPerSession,sessionTimeoutMs:e.config.limits.sessionTimeoutMs}),n}export{ResolveAgentError,resolveAgent};
1
+ import{ResolveAgentError,createResolvedModuleSourceRef}from"#runtime/resolve-helpers.js";import{resolveDynamicToolDefinition}from"#runtime/resolve-dynamic-tool.js";import{resolveChannelDefinition}from"#runtime/resolve-channel.js";import{resolveConnectionDefinition}from"#runtime/resolve-connection.js";import{resolveHookDefinition}from"#runtime/resolve-hook.js";import{resolveSandboxDefinition}from"#runtime/resolve-sandbox.js";import{resolveDynamicInstructionsDefinition}from"#runtime/resolve-dynamic-instructions.js";import{resolveDynamicSkillDefinition}from"#runtime/resolve-dynamic-skill.js";import{resolveToolDefinition}from"#runtime/resolve-tool.js";async function resolveAgent(e){let t=e.manifest.skills.map(e=>({...e,metadata:e.metadata===void 0?void 0:{...e.metadata}})),i=[],a=[];for(let t of e.manifest.channels){if(t.kind===`disabled`){a.push(t.name);continue}i.push(await resolveChannelDefinition(t,e.moduleMap,e.nodeId))}let o=await Promise.all(e.manifest.tools.map(t=>resolveToolDefinition(t,e.moduleMap,e.nodeId))),s=await Promise.all((e.manifest.dynamicInstructions??[]).map(t=>resolveDynamicInstructionsDefinition(t,e.moduleMap,e.nodeId))),c=await Promise.all((e.manifest.dynamicSkills??[]).map(t=>resolveDynamicSkillDefinition(t,e.moduleMap,e.nodeId))),l=await Promise.all(e.manifest.dynamicTools.map(t=>resolveDynamicToolDefinition(t,e.moduleMap,e.nodeId))),u=await Promise.all(e.manifest.hooks.map(t=>resolveHookDefinition(t,e.moduleMap,e.nodeId))),d=await Promise.all(e.manifest.connections.map(t=>resolveConnectionDefinition(t,e.moduleMap,e.nodeId))),f=e.manifest.sandbox===null?null:await resolveSandboxDefinition(e.manifest.sandbox,e.moduleMap,e.nodeId),p=createResolvedInstructionsDefinition(e.manifest.instructions),m=e.manifest.workspaceResourceRoot,h={channels:i,connections:d,disabledFrameworkChannels:a,disabledFrameworkTools:[...e.manifest.disabledFrameworkTools],workflowTool:e.manifest.workflowTool===void 0?void 0:{maxSubagents:e.manifest.workflowTool.maxSubagents},webSearchProvider:e.manifest.webSearchProvider,dynamicInstructionsResolvers:s,dynamicSkillResolvers:c,dynamicToolResolvers:l,hooks:u,metadata:{agentRoot:e.manifest.agentRoot,appRoot:e.manifest.appRoot,diagnosticsSummary:e.manifest.diagnosticsSummary},sandbox:f,workspaceResourceRoot:m,skills:t,tools:o,workspaceSpec:{rootEntries:[...m.rootEntries]}},g=p===void 0?h:{...h,instructions:p};return`config`in e.manifest?{...g,config:createResolvedAgentConfig(e.manifest)}:g}function createResolvedInstructionsDefinition(e){if(e!==void 0)return{name:e.name,logicalPath:e.logicalPath,markdown:e.markdown,sourceId:e.sourceId,sourceKind:e.sourceKind}}function createResolvedAgentConfig(e){let n={name:e.config.name};if(e.config.compaction!==void 0){let t={};e.config.compaction.model!==void 0&&(t.model=e.config.compaction.model.source===void 0?{contextWindowTokens:e.config.compaction.model.contextWindowTokens,id:e.config.compaction.model.id,maxOutputTokens:e.config.compaction.model.maxOutputTokens,providerOptions:e.config.compaction.model.providerOptions}:{contextWindowTokens:e.config.compaction.model.contextWindowTokens,id:e.config.compaction.model.id,maxOutputTokens:e.config.compaction.model.maxOutputTokens,providerOptions:e.config.compaction.model.providerOptions,source:{exportName:e.config.compaction.model.source.exportName,sourceKind:`module`,logicalPath:e.config.compaction.model.source.logicalPath,sourceId:e.config.compaction.model.source.sourceId}}),e.config.compaction.thresholdPercent!==void 0&&(t.thresholdPercent=e.config.compaction.thresholdPercent),n.compaction=t}if(e.config.experimental!==void 0&&(n.experimental={subagentPersistentSessions:e.config.experimental.subagentPersistentSessions,workflow:e.config.experimental.workflow===void 0?void 0:{world:e.config.experimental.workflow.world}}),e.config.outputSchema!==void 0&&(n.outputSchema=e.config.outputSchema),e.config.reasoning!==void 0&&(n.reasoning=e.config.reasoning),e.config.source!==void 0&&(n.source=createResolvedModuleSourceRef(e.config.source)),e.config.limits!==void 0&&(n.limits={maxInputTokensPerSession:e.config.limits.maxInputTokensPerSession,maxOutputTokensPerSession:e.config.limits.maxOutputTokensPerSession,sessionTimeoutMs:e.config.limits.sessionTimeoutMs}),e.config.dynamicModel!==void 0)return{...n,dynamicModel:{...createResolvedModuleSourceRef(e.config.dynamicModel),eventNames:[...e.config.dynamicModel.eventNames]}};let r=e.config.model;return{...n,model:r.source===void 0?{id:r.id,contextWindowTokens:r.contextWindowTokens,maxOutputTokens:r.maxOutputTokens,providerOptions:r.providerOptions}:{contextWindowTokens:r.contextWindowTokens,id:r.id,maxOutputTokens:r.maxOutputTokens,providerOptions:r.providerOptions,source:{exportName:r.source.exportName,sourceKind:`module`,logicalPath:r.source.logicalPath,sourceId:r.source.sourceId}}}}export{ResolveAgentError,resolveAgent};