eve 0.80.0 → 0.81.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 (177) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/dist/src/channel/channel-address.d.ts +1 -0
  3. package/dist/src/channel/channel-address.js +1 -1
  4. package/dist/src/channel/inactive-prompt.d.ts +46 -0
  5. package/dist/src/channel/inactive-prompt.js +1 -0
  6. package/dist/src/channel/principal-identity.d.ts +2 -0
  7. package/dist/src/channel/principal-identity.js +1 -1
  8. package/dist/src/channel/session-not-active-error.d.ts +16 -0
  9. package/dist/src/channel/session-not-active-error.js +1 -0
  10. package/dist/src/chunks/{use-eve-agent-Vsl-S0yI.js → use-eve-agent-Bp6nbhfV.js} +6 -0
  11. package/dist/src/chunks/{use-eve-agent-Ch-Q-s12.js → use-eve-agent-DLkjJIm3.js} +6 -0
  12. package/dist/src/compiled/.vendor-stamp.json +3 -3
  13. package/dist/src/compiled/@ai-sdk/mcp/index.js +1 -1
  14. package/dist/src/compiled/{@eve/tracing → @vercel/agent-runs}/adapters/ai-sdk-telemetry.d.ts +2 -2
  15. package/dist/src/compiled/{@eve/tracing/agent-tracing.d.ts → @vercel/agent-runs/agent-run.d.ts} +3 -3
  16. package/dist/src/compiled/{@eve/tracing → @vercel/agent-runs}/index.d.ts +1 -1
  17. package/dist/src/compiled/{@eve/tracing → @vercel/agent-runs}/index.js +1 -1
  18. package/dist/src/compiled/@workflow/world-vercel/index.js +3 -3
  19. package/dist/src/compiler/extension-compatibility.d.ts +18 -18
  20. package/dist/src/compiler/extension-compatibility.js +1 -1
  21. package/dist/src/context/provider.d.ts +5 -0
  22. package/dist/src/context/providers/connection.js +1 -1
  23. package/dist/src/context/run-step.js +1 -1
  24. package/dist/src/eve-channel/support.js +1 -1
  25. package/dist/src/execution/agent-sessions/steps.js +1 -1
  26. package/dist/src/execution/dynamic-workflow/tool.js +1 -1
  27. package/dist/src/execution/sandbox/bindings/vercel-lookup.d.ts +6 -0
  28. package/dist/src/execution/sandbox/bindings/vercel-lookup.js +1 -1
  29. package/dist/src/execution/sandbox/bindings/vercel.js +2 -2
  30. package/dist/src/execution/tools/agent-router-workflow.js +1 -1
  31. package/dist/src/execution/workflow-runtime.js +1 -1
  32. package/dist/src/extensions/code/extension/extension.d.ts +2 -0
  33. package/dist/src/extensions/code/extension/extension.js +1 -1
  34. package/dist/src/extensions/git/extension/extension.d.ts +3 -0
  35. package/dist/src/extensions/git/extension/extension.js +1 -1
  36. package/dist/src/extensions/git/extension/lib/attribution.d.ts +22 -0
  37. package/dist/src/extensions/git/extension/lib/attribution.js +4 -0
  38. package/dist/src/extensions/git/extension/lib/gh-tool.js +1 -1
  39. package/dist/src/extensions/git/extension/lib/github-shell.d.ts +13 -1
  40. package/dist/src/extensions/git/extension/lib/github-shell.js +1 -1
  41. package/dist/src/extensions/git/extension/lib/sandbox.d.ts +1 -1
  42. package/dist/src/harness/authorization-event-fields.d.ts +3 -0
  43. package/dist/src/harness/authorization-event-fields.js +1 -1
  44. package/dist/src/harness/compaction/engine.js +2 -2
  45. package/dist/src/harness/compaction/prompt.d.ts +6 -0
  46. package/dist/src/harness/compaction/prompt.js +1 -1
  47. package/dist/src/harness/hitl/approvals.d.ts +9 -9
  48. package/dist/src/harness/hitl/approvals.js +1 -1
  49. package/dist/src/harness/hitl/approved-calls.d.ts +4 -4
  50. package/dist/src/harness/hitl/approved-calls.js +1 -1
  51. package/dist/src/harness/hitl/candidates.d.ts +7 -1
  52. package/dist/src/harness/hitl/candidates.js +1 -1
  53. package/dist/src/harness/hitl/coordinator.d.ts +2 -2
  54. package/dist/src/harness/hitl/coordinator.js +1 -1
  55. package/dist/src/harness/hitl/index.d.ts +2 -2
  56. package/dist/src/harness/hitl/index.js +1 -1
  57. package/dist/src/harness/hitl/intake.js +1 -1
  58. package/dist/src/harness/hitl/sign-ins.d.ts +10 -0
  59. package/dist/src/harness/hitl/sign-ins.js +1 -1
  60. package/dist/src/harness/inline-tool-authorization.d.ts +10 -11
  61. package/dist/src/harness/inline-tool-authorization.js +1 -1
  62. package/dist/src/harness/session-machine/current.d.ts +5 -0
  63. package/dist/src/harness/session-machine/current.js +1 -1
  64. package/dist/src/harness/session-machine/state.d.ts +15 -3
  65. package/dist/src/harness/session-machine/transitions.d.ts +23 -5
  66. package/dist/src/harness/session-machine/transitions.js +1 -1
  67. package/dist/src/harness/step/after-model.js +1 -1
  68. package/dist/src/instrumentation/ai-sdk-hook-bridge.js +1 -1
  69. package/dist/src/instrumentation/principal-summary.js +1 -1
  70. package/dist/src/instrumentation/runtime.d.ts +1 -1
  71. package/dist/src/instrumentation/runtime.js +1 -1
  72. package/dist/src/instrumentation/session-init.js +1 -1
  73. package/dist/src/internal/application/stamped-package-version.js +1 -1
  74. package/dist/src/internal/authored-definition/source-identity.js +1 -1
  75. package/dist/src/internal/authored-package-boundary.d.ts +4 -0
  76. package/dist/src/internal/authored-package-boundary.js +1 -1
  77. package/dist/src/internal/bundler/nitro-rolldown.d.ts +2 -2
  78. package/dist/src/internal/logging.js +1 -1
  79. package/dist/src/internal/nitro/host/create-application-nitro.js +1 -1
  80. package/dist/src/internal/nitro/host/external-dependency-output-check-plugin.d.ts +23 -0
  81. package/dist/src/internal/nitro/host/external-dependency-output-check-plugin.js +3 -0
  82. package/dist/src/internal/nitro/routes/channel-request-instrumentation.js +1 -1
  83. package/dist/src/protocol/message.d.ts +30 -0
  84. package/dist/src/protocol/message.js +1 -1
  85. package/dist/src/protocol/session-projection.d.ts +8 -1
  86. package/dist/src/protocol/session-projection.js +1 -1
  87. package/dist/src/public/channels/auth.js +1 -1
  88. package/dist/src/public/channels/chat-sdk/chatSdkChannel.js +1 -1
  89. package/dist/src/public/channels/chat-sdk/input-actions.d.ts +5 -0
  90. package/dist/src/public/channels/chat-sdk/input-actions.js +2 -2
  91. package/dist/src/public/channels/discord/defaults.d.ts +6 -1
  92. package/dist/src/public/channels/discord/defaults.js +2 -2
  93. package/dist/src/public/channels/discord/discordChannel.js +1 -1
  94. package/dist/src/public/channels/slack/approval-cards.js +2 -2
  95. package/dist/src/public/channels/slack/interaction-cards.d.ts +19 -6
  96. package/dist/src/public/channels/slack/interaction-cards.js +1 -1
  97. package/dist/src/public/channels/slack/interactions.js +1 -1
  98. package/dist/src/public/channels/teams/hitl.d.ts +7 -0
  99. package/dist/src/public/channels/teams/hitl.js +1 -1
  100. package/dist/src/public/channels/teams/teamsChannel.js +1 -1
  101. package/dist/src/public/channels/telegram/hitl.d.ts +2 -0
  102. package/dist/src/public/channels/telegram/hitl.js +2 -2
  103. package/dist/src/public/channels/telegram/inbound.d.ts +2 -0
  104. package/dist/src/public/channels/telegram/inbound.js +1 -1
  105. package/dist/src/public/channels/telegram/telegramChannel.js +1 -1
  106. package/dist/src/public/definitions/channel.js +1 -1
  107. package/dist/src/runtime/connections/mcp-client.d.ts +1 -1
  108. package/dist/src/runtime/connections/mcp-client.js +1 -1
  109. package/dist/src/runtime/connections/openapi-client.js +1 -1
  110. package/dist/src/runtime/connections/registry-types.d.ts +4 -1
  111. package/dist/src/runtime/connections/registry.d.ts +3 -2
  112. package/dist/src/runtime/connections/scoped-authorization.js +1 -1
  113. package/dist/src/setup/scaffold/create/project.js +1 -1
  114. package/dist/src/svelte/index.js +1 -1
  115. package/dist/src/svelte/use-eve-agent.js +1 -1
  116. package/dist/src/tools/provided/ask-question-workflow.js +1 -1
  117. package/dist/src/tools/provided/sleep-workflow.js +1 -1
  118. package/dist/src/tracing/eve/agent-approval-instrumentation.d.ts +2 -2
  119. package/dist/src/tracing/eve/agent-channel-delivery-instrumentation.js +1 -1
  120. package/dist/src/tracing/eve/agent-memory-instrumentation.d.ts +2 -2
  121. package/dist/src/tracing/eve/agent-memory-instrumentation.js +1 -1
  122. package/dist/src/tracing/eve/agent-otel-provider.d.ts +1 -1
  123. package/dist/src/tracing/eve/agent-tool-instrumentation.d.ts +3 -3
  124. package/dist/src/tracing/eve/agent-trace-context.js +1 -1
  125. package/dist/src/tracing/eve/agent-trace-state.d.ts +1 -1
  126. package/dist/src/tracing/eve/connection-events.js +1 -1
  127. package/dist/src/tracing/eve/content-span-processor.js +1 -1
  128. package/dist/src/tracing/eve/delegation.js +1 -1
  129. package/dist/src/tracing/eve/gateway.d.ts +1 -1
  130. package/dist/src/tracing/eve/install-instrumentation-runtime.js +1 -1
  131. package/dist/src/tracing/eve/invoke-tool-span.js +1 -1
  132. package/dist/src/tracing/eve/mcp.d.ts +1 -1
  133. package/dist/src/tracing/eve/mcp.js +1 -1
  134. package/dist/src/tracing/eve/metadata.d.ts +1 -1
  135. package/dist/src/tracing/eve/operation-input.d.ts +2 -2
  136. package/dist/src/tracing/eve/operation-input.js +1 -1
  137. package/dist/src/tracing/eve/otel-registration.d.ts +2 -2
  138. package/dist/src/tracing/eve/otel-registration.js +1 -1
  139. package/dist/src/tracing/eve/profile.d.ts +1 -1
  140. package/dist/src/tracing/eve/session.d.ts +2 -2
  141. package/dist/src/tracing/local/trace-summary.js +1 -1
  142. package/dist/src/vue/index.js +1 -1
  143. package/dist/src/vue/use-eve-agent.js +1 -1
  144. package/docs/channels/slack.mdx +2 -0
  145. package/docs/channels/teams.mdx +1 -1
  146. package/docs/channels/telegram.mdx +1 -1
  147. package/docs/code-extension.mdx +20 -6
  148. package/docs/connections/mcp.mdx +4 -0
  149. package/docs/connections/openapi.mdx +2 -0
  150. package/docs/connections/overview.mdx +2 -2
  151. package/docs/evals/assertions.mdx +21 -0
  152. package/package.json +2 -2
  153. /package/dist/src/compiled/{@eve/tracing → @vercel/agent-runs}/adapters/agent-transport.d.ts +0 -0
  154. /package/dist/src/compiled/{@eve/tracing → @vercel/agent-runs}/adapters/ai-sdk-payload.d.ts +0 -0
  155. /package/dist/src/compiled/{@eve/tracing → @vercel/agent-runs}/adapters/otel-error.d.ts +0 -0
  156. /package/dist/src/compiled/{@eve/tracing → @vercel/agent-runs}/adapters/otel-ids.d.ts +0 -0
  157. /package/dist/src/compiled/{@eve/tracing → @vercel/agent-runs}/adapters/otel.d.ts +0 -0
  158. /package/dist/src/compiled/{@eve/tracing → @vercel/agent-runs}/adapters/serialization.d.ts +0 -0
  159. /package/dist/src/compiled/{@eve/tracing → @vercel/agent-runs}/ai-sdk.d.ts +0 -0
  160. /package/dist/src/compiled/{@eve/tracing → @vercel/agent-runs}/ai-sdk.js +0 -0
  161. /package/dist/src/compiled/{@eve/tracing → @vercel/agent-runs}/capture.d.ts +0 -0
  162. /package/dist/src/compiled/{@eve/tracing → @vercel/agent-runs}/core/activation.d.ts +0 -0
  163. /package/dist/src/compiled/{@eve/tracing → @vercel/agent-runs}/core/attributes.d.ts +0 -0
  164. /package/dist/src/compiled/{@eve/tracing → @vercel/agent-runs}/core/content-policy.d.ts +0 -0
  165. /package/dist/src/compiled/{@eve/tracing → @vercel/agent-runs}/core/context.d.ts +0 -0
  166. /package/dist/src/compiled/{@eve/tracing → @vercel/agent-runs}/core/delegation.d.ts +0 -0
  167. /package/dist/src/compiled/{@eve/tracing → @vercel/agent-runs}/core/mcp.d.ts +0 -0
  168. /package/dist/src/compiled/{@eve/tracing → @vercel/agent-runs}/core/scopes.d.ts +0 -0
  169. /package/dist/src/compiled/{@eve/tracing → @vercel/agent-runs}/core/snapshot.d.ts +0 -0
  170. /package/dist/src/compiled/{@eve/tracing → @vercel/agent-runs}/core/span-kinds.d.ts +0 -0
  171. /package/dist/src/compiled/{@eve/tracing → @vercel/agent-runs}/core/types.d.ts +0 -0
  172. /package/dist/src/compiled/{@eve/tracing → @vercel/agent-runs}/core/writer.d.ts +0 -0
  173. /package/dist/src/compiled/{@eve/tracing → @vercel/agent-runs}/delegation.d.ts +0 -0
  174. /package/dist/src/compiled/{@eve/tracing → @vercel/agent-runs}/delegation.js +0 -0
  175. /package/dist/src/compiled/{@eve/tracing → @vercel/agent-runs}/operations.d.ts +0 -0
  176. /package/dist/src/compiled/{@eve/tracing → @vercel/agent-runs}/otel.d.ts +0 -0
  177. /package/dist/src/compiled/{@eve/tracing → @vercel/agent-runs}/otel.js +0 -0
@@ -1 +1 @@
1
- import{createLogger,logError}from"#internal/logging.js";import{readNonEmptyString}from"#shared/guards.js";import{defaultDeliverResult}from"#channel/adapter.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,isTeamsToolApprovalResponseActivity,readTeamsInputReplyToActivityId,readTeamsToolApprovalPrompt,teamsInvokeResponse}from"#public/channels/teams/hitl.js";import{answerTeamsAuthorizationReveal,readTeamsAuthorizationReveal}from"#public/channels/teams/authorization.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),n=e.onMessage??defaultOnMessage,r=e.onInputResponse??(e.onMessage===void 0?defaultOnInputResponse:rejectInput),i={...defaultEvents,...e.events};return defineChannel({kindHint:`teams`,turnPolicy:e.turnPolicy,uploadPolicy:e.files?.uploadPolicy,state:initialTeamsState(),fetchFile:createTeamsFetchFile(t,{...e.api,credentials:e.credentials}),metadata:e=>({channelId:e.channelId,conversationType:e.conversationType,teamId:e.teamId}),audience:({state:e})=>teamsAudience(e.conversationType),context(t,n){return rebuildTeamsContext(t,n,e)},deliver(e,t){let n=e.state,r=n?.pendingPromptCards;r!==void 0&&(t.state.pendingPromptCards={...r,...t.state.pendingPromptCards});let i=n?.approvalResponderAccounts;return i!==void 0&&(t.state.approvalResponderAccounts={...t.state.approvalResponderAccounts,...i}),defaultDeliverResult(e)},routes:[POST(e.route??`/eve/v1/teams`,async(i,{from:a,resolveSession:o,waitUntil:s})=>{let c=await verifyInbound(i,e.credentials);if(c===null)return new Response(`unauthorized`,{status:401});let l;try{l=parseJsonObject(JSON.parse(c))}catch(e){return log.warn(`inbound Teams body is not valid JSON`,{error:e}),teamsOk()}let u=parseTeamsActivity(l);return u===null?teamsOk():u.type===`message`?(s(isTeamsInputResponseActivity(u)?dispatchInputResponses({activity:u,config:e,from:a,onInputResponse:r}):dispatchMessage({activity:u,config:e,filesPolicy:t,onMessage:n,from:a,resolveSession:o})),teamsOk()):u.type===`invoke`?handleInvoke({activity:u,config:e,onInputResponse:r,resolveSession:o,waitUntil:s,from:a}):teamsOk()})],async receive(t,{from:n}){let r=t.target,i=readNonEmptyString(r.serviceUrl),a=readNonEmptyString(r.conversationId);if(!i||!a)throw Error(`teamsChannel().receive requires target.serviceUrl and target.conversationId.`);let o=readNonEmptyString(r.conversationType)??null,s=readNonEmptyString(r.replyToActivityId)??null,c=r.initialMessage;if(c!==void 0&&s!==null)throw Error("teamsChannel().receive: `replyToActivityId` and `initialMessage` are mutually exclusive.");let l={...initialTeamsState(),channelId:readNonEmptyString(r.channelId)??null,conversationId:a,conversationType:o,replyToActivityId:s,serviceUrl:i,teamId:readNonEmptyString(r.teamId)??null,tenantId:readNonEmptyString(r.tenantId)??null};if(c!==void 0){let t=await buildTeamsBinding({config:e,state:l}).thread.post(c);o!==`personal`&&t.id&&(s=t.id,l.replyToActivityId=t.id)}return n(teamsContinuationToken({conversationId:a,replyToActivityId:s,tenantId:l.tenantId})).send(t.message,{auth:t.auth,state:l})},events:i})}function teamsAudience(e){return e===`personal`||e===`groupChat`?`private`:`unknown`}function rebuildTeamsContext(e,t,n){return{...buildTeamsBinding({config:n,session:t,state:e}),adaptiveCardVersion:n.adaptiveCardVersion??`1.5`,state:e}}function buildTeamsBinding(e){let t=buildTeamsHandle(e);return{teams:t,thread:{mentionUser:teamsMentionUser,post(e){return t.sendActivity(e)},async startTyping(){try{await t.startTyping()}catch(e){logError(log,`Teams typing indicator failed — swallowed`,e)}},update(e,n){return t.updateActivity(e,n)}}}}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?.alias(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:buildUpdateActivity(t,i),credentials:r,activityId:e,conversationId:normalizeTeamsContinuationAddress({conversationId:a.conversationId}).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,botId:e.activity.recipient.id,channelId:e.activity.teamsChannelId,conversationId:e.activity.conversation.id,conversationType:e.activity.conversationType,isMentioned:e.activity.isBotMentioned,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,title:a.title})}catch(e){log.error(`Teams message delivery failed`,{error:e})}}async function handleInvoke(e){let t=readTeamsAuthorizationReveal(e.activity);if(t!==null)return Response.json(await revealAuthorization({...e,reveal:t}));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 n=buildTeamsBinding({config:e.config,state:stateFromActivity(e.activity)}),r=await e.config.onInvoke(n,e.activity);return r instanceof Response?r:r&&typeof r==`object`?Response.json(r):teamsOk()}async function revealAuthorization(e){let t=stateFromActivity(e.activity),n=buildTeamsBinding({config:e.config,state:t}),r=null;try{r=(await e.onInputResponse(n,e.activity))?.auth??null}catch(e){log.error(`Teams sign-in press authorization failed`,{error:e})}let i=cardContinuationToken(e.activity,t,e.reveal.replyToActivityId??null);return await answerTeamsAuthorizationReveal({adaptiveCardVersion:e.config.adaptiveCardVersion??`1.5`,auth:r,presser:e.activity.from,resolveSession:()=>e.resolveSession(i),reveal:e.reveal})}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(cardContinuationToken(e.activity,n,readTeamsInputReplyToActivityId(e.activity))).respond(t,{auth:i.auth,state:approvalResponseStatePatch(e.activity,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 cardContinuationToken(e,t,n){return n===null?stateToken(t):teamsContinuationToken({conversationId:e.conversation.id,replyToActivityId:n,tenantId:e.tenantId})}function approvalResponseStatePatch(e,t){if(t?.principalId===void 0||!isTeamsToolApprovalResponseActivity(e))return;let n=deriveTeamsInputResponses(e)[0]?.requestId,r=e.replyToId;return n===void 0||r===void 0?{approvalResponderAccounts:{[t.principalId]:e.from}}:{approvalResponderAccounts:{[t.principalId]:e.from},pendingPromptCards:{[n]:{activityId:r,prompt:readTeamsToolApprovalPrompt(e)??`Tool approval`}}}}function defaultOnInputResponse(e,t){return{auth:defaultTeamsAuth(t)}}function rejectInput(){return null}function initialTeamsState(){return{bot:null,channelId:null,conversationId:null,conversationType:null,approvalResponderAccounts:{},pendingPromptCards:{},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 buildUpdateActivity(e,t){if(typeof t!=`string`&&`type`in t&&t.type===`typing`)throw Error(`teamsChannel: cannot replace an activity with a typing indicator.`);let{channelData:n,conversation:r,from:i,recipient:a,replyToId:o,type:s,...c}=normalizeTeamsPostInput(t);return{...c,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{defaultDeliverResult}from"#channel/adapter.js";import{parseJsonObject}from"#shared/json.js";import{POST,defineChannel}from"#public/definitions/channel.js";import{INACTIVE_REQUEST_NOTICE,respondOrRetireInactivePrompt}from"#channel/inactive-prompt.js";import{callTeamsConnectorApi,normalizeTeamsContinuationAddress,normalizeTeamsPostInput,replyToTeamsActivity,sendTeamsActivity,teamsContinuationToken,triggerTeamsTypingIndicator,updateTeamsActivity}from"#public/channels/teams/api.js";import{deriveTeamsInputResponses,isTeamsInputResponseActivity,isTeamsToolApprovalResponseActivity,readTeamsInputPrompt,readTeamsInputReplyToActivityId,readTeamsToolApprovalPrompt,renderInactiveInputRequestMessage,teamsInvokeResponse}from"#public/channels/teams/hitl.js";import{answerTeamsAuthorizationReveal,readTeamsAuthorizationReveal}from"#public/channels/teams/authorization.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),n=e.onMessage??defaultOnMessage,r=e.onInputResponse??(e.onMessage===void 0?defaultOnInputResponse:rejectInput),i={...defaultEvents,...e.events};return defineChannel({kindHint:`teams`,turnPolicy:e.turnPolicy,uploadPolicy:e.files?.uploadPolicy,state:initialTeamsState(),fetchFile:createTeamsFetchFile(t,{...e.api,credentials:e.credentials}),metadata:e=>({channelId:e.channelId,conversationType:e.conversationType,teamId:e.teamId}),audience:({state:e})=>teamsAudience(e.conversationType),context(t,n){return rebuildTeamsContext(t,n,e)},deliver(e,t){let n=e.state,r=n?.pendingPromptCards;r!==void 0&&(t.state.pendingPromptCards={...r,...t.state.pendingPromptCards});let i=n?.approvalResponderAccounts;return i!==void 0&&(t.state.approvalResponderAccounts={...t.state.approvalResponderAccounts,...i}),defaultDeliverResult(e)},routes:[POST(e.route??`/eve/v1/teams`,async(i,{from:a,resolveSession:o,waitUntil:s})=>{let c=await verifyInbound(i,e.credentials);if(c===null)return new Response(`unauthorized`,{status:401});let l;try{l=parseJsonObject(JSON.parse(c))}catch(e){return log.warn(`inbound Teams body is not valid JSON`,{error:e}),teamsOk()}let u=parseTeamsActivity(l);return u===null?teamsOk():u.type===`message`?(s(isTeamsInputResponseActivity(u)?dispatchInputResponses({activity:u,config:e,from:a,onInputResponse:r}).then(e=>e?.outcome===`inactive`?e.retirement:void 0):dispatchMessage({activity:u,config:e,filesPolicy:t,onMessage:n,from:a,resolveSession:o})),teamsOk()):u.type===`invoke`?handleInvoke({activity:u,config:e,onInputResponse:r,resolveSession:o,waitUntil:s,from:a}):teamsOk()})],async receive(t,{from:n}){let r=t.target,i=readNonEmptyString(r.serviceUrl),a=readNonEmptyString(r.conversationId);if(!i||!a)throw Error(`teamsChannel().receive requires target.serviceUrl and target.conversationId.`);let o=readNonEmptyString(r.conversationType)??null,s=readNonEmptyString(r.replyToActivityId)??null,c=r.initialMessage;if(c!==void 0&&s!==null)throw Error("teamsChannel().receive: `replyToActivityId` and `initialMessage` are mutually exclusive.");let l={...initialTeamsState(),channelId:readNonEmptyString(r.channelId)??null,conversationId:a,conversationType:o,replyToActivityId:s,serviceUrl:i,teamId:readNonEmptyString(r.teamId)??null,tenantId:readNonEmptyString(r.tenantId)??null};if(c!==void 0){let t=await buildTeamsBinding({config:e,state:l}).thread.post(c);o!==`personal`&&t.id&&(s=t.id,l.replyToActivityId=t.id)}return n(teamsContinuationToken({conversationId:a,replyToActivityId:s,tenantId:l.tenantId})).send(t.message,{auth:t.auth,state:l})},events:i})}function teamsAudience(e){return e===`personal`||e===`groupChat`?`private`:`unknown`}function rebuildTeamsContext(e,t,n){return{...buildTeamsBinding({config:n,session:t,state:e}),adaptiveCardVersion:n.adaptiveCardVersion??`1.5`,state:e}}function buildTeamsBinding(e){let t=buildTeamsHandle(e);return{teams:t,thread:{mentionUser:teamsMentionUser,post(e){return t.sendActivity(e)},async startTyping(){try{await t.startTyping()}catch(e){logError(log,`Teams typing indicator failed — swallowed`,e)}},update(e,n){return t.updateActivity(e,n)}}}}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?.alias(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:buildUpdateActivity(t,i),credentials:r,activityId:e,conversationId:normalizeTeamsContinuationAddress({conversationId:a.conversationId}).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,botId:e.activity.recipient.id,channelId:e.activity.teamsChannelId,conversationId:e.activity.conversation.id,conversationType:e.activity.conversationType,isMentioned:e.activity.isBotMentioned,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,title:a.title})}catch(e){log.error(`Teams message delivery failed`,{error:e})}}async function handleInvoke(e){let t=readTeamsAuthorizationReveal(e.activity);if(t!==null)return Response.json(await revealAuthorization({...e,reveal:t}));if(isTeamsInputResponseActivity(e.activity)){let t=await dispatchInputResponses({activity:e.activity,config:e.config,onInputResponse:e.onInputResponse,from:e.from});return t?.outcome===`inactive`?(e.waitUntil(t.retirement),Response.json(teamsInvokeResponse({message:INACTIVE_REQUEST_NOTICE}))):Response.json(teamsInvokeResponse())}if(e.config.onInvoke===void 0)return teamsOk();let n=buildTeamsBinding({config:e.config,state:stateFromActivity(e.activity)}),r=await e.config.onInvoke(n,e.activity);return r instanceof Response?r:r&&typeof r==`object`?Response.json(r):teamsOk()}async function revealAuthorization(e){let t=stateFromActivity(e.activity),n=buildTeamsBinding({config:e.config,state:t}),r=null;try{r=(await e.onInputResponse(n,e.activity))?.auth??null}catch(e){log.error(`Teams sign-in press authorization failed`,{error:e})}let i=cardContinuationToken(e.activity,t,e.reveal.replyToActivityId??null);return await answerTeamsAuthorizationReveal({adaptiveCardVersion:e.config.adaptiveCardVersion??`1.5`,auth:r,presser:e.activity.from,resolveSession:()=>e.resolveSession(i),reveal:e.reveal})}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)return;let a=i.auth,o=e.activity;return respondOrRetireInactivePrompt(()=>e.from(cardContinuationToken(o,n,readTeamsInputReplyToActivityId(o))).respond(t,{auth:a,state:approvalResponseStatePatch(o,a)}),{async retirePrompt(e){o.replyToId!==void 0&&await r.thread.update(o.replyToId,renderInactiveInputRequestMessage(readTeamsInputPrompt(o),e))}},log)}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 cardContinuationToken(e,t,n){return n===null?stateToken(t):teamsContinuationToken({conversationId:e.conversation.id,replyToActivityId:n,tenantId:e.tenantId})}function approvalResponseStatePatch(e,t){if(t?.principalId===void 0||!isTeamsToolApprovalResponseActivity(e))return;let n=deriveTeamsInputResponses(e)[0]?.requestId,r=e.replyToId;return n===void 0||r===void 0?{approvalResponderAccounts:{[t.principalId]:e.from}}:{approvalResponderAccounts:{[t.principalId]:e.from},pendingPromptCards:{[n]:{activityId:r,prompt:readTeamsToolApprovalPrompt(e)??`Tool approval`}}}}function defaultOnInputResponse(e,t){return{auth:defaultTeamsAuth(t)}}function rejectInput(){return null}function initialTeamsState(){return{bot:null,channelId:null,conversationId:null,conversationType:null,approvalResponderAccounts:{},pendingPromptCards:{},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 buildUpdateActivity(e,t){if(typeof t!=`string`&&`type`in t&&t.type===`typing`)throw Error(`teamsChannel: cannot replace an activity with a typing indicator.`);let{channelData:n,conversation:r,from:i,recipient:a,replyToId:o,type:s,...c}=normalizeTeamsPostInput(t);return{...c,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};
@@ -64,6 +64,8 @@ export declare function takeTelegramResolvedPrompt(state: TelegramHitlState, res
64
64
  readonly messageId: string;
65
65
  readonly text: string;
66
66
  } | undefined;
67
+ /** A resolved prompt's text: the prompt it asked, then `label`, how it ended. */
68
+ export declare function telegramResolvedPromptText(promptText: string, label: string): string;
67
69
  /**
68
70
  * Wraps Telegram callback data as a synthetic `InputResponse` (requestId prefixed
69
71
  * with `telegram_callback:`, optionId hardcoded to `"selected"`). It is a
@@ -1,2 +1,2 @@
1
- import{parseInputResponse,parseInputResponses}from"#shared/input.js";import{resolvedPromptLabel}from"#channel/resolved-prompt.js";const TELEGRAM_HITL_CALLBACK_PREFIX=`eve:`,TELEGRAM_CALLBACK_RESPONSE_PREFIX=`telegram_callback:`,TELEGRAM_REPLY_RESPONSE_PREFIX=`telegram_reply:`,TELEGRAM_PROMPT_MAX_LENGTH=4e3;function renderTelegramInputRequest(e,t){let n=e.options;return n&&n.length>0?{replyMarkup:{inline_keyboard:chunk(n.map(n=>({callback_data:registerTelegramCallback(t,{optionId:n.id,requestId:e.requestId}),text:truncate(n.label,64)})),2)},text:truncate(e.prompt,TELEGRAM_PROMPT_MAX_LENGTH)}:{freeformRequestId:e.requestId,replyMarkup:{force_reply:!0,input_field_placeholder:truncate(`Type your answer`,64),selective:!0},text:truncate(e.prompt,TELEGRAM_PROMPT_MAX_LENGTH)}}function registerTelegramFreeformPrompt(e,t){e.pendingFreeformReplies={...e.pendingFreeformReplies,[t.messageId]:t.requestId}}function registerTelegramHitlPrompt(e,t,n){e.hitlPrompts={...e.hitlPrompts,[t.requestId]:{...n,options:(t.options??[]).map(({id:e,label:t})=>({id:e,label:t}))}}}function takeTelegramResolvedPrompt(e,t){let n=e.hitlPrompts?.[t.requestId];if(n===void 0)return;let{[t.requestId]:r,...i}=e.hitlPrompts??{};e.hitlPrompts=i;let a=truncate(resolvedPromptLabel(t,n.options),90);return{messageId:n.messageId,text:`${n.text}\n\n${a}`}}function telegramCallbackInputResponse(e){return parseInputResponse({optionId:`selected`,requestId:`${TELEGRAM_CALLBACK_RESPONSE_PREFIX}${e}`})}function telegramReplyInputResponse(e){return parseInputResponse({requestId:`${TELEGRAM_REPLY_RESPONSE_PREFIX}${e.messageId}`,text:e.text})}function telegramReplyInputResponses(e,t){if(typeof e!=`string`)return[];let n=typeof t==`string`?t:(t??[]).flatMap(e=>e.type===`text`?[e.text]:[]).join(`
2
- `);return n.trim().length===0?[]:[telegramReplyInputResponse({messageId:e,text:n})]}function isTelegramSyntheticResponse(e){return e.requestId.startsWith(`telegram_callback:`)||e.requestId.startsWith(`telegram_reply:`)}function resolveTelegramInputResponses(e,t){let n=[];for(let r of t){if(r.requestId.startsWith(`telegram_callback:`)){let t=r.requestId.slice(18),i=e.hitlCallbacks?.[t];i!==void 0&&n.push(i);continue}if(r.requestId.startsWith(`telegram_reply:`)){let t=r.requestId.slice(15),i=e.pendingFreeformReplies?.[t];i!==void 0&&r.text!==void 0&&(n.push({requestId:i,text:r.text}),delete e.pendingFreeformReplies?.[t]);continue}n.push(r)}return[...parseInputResponses(n)]}function registerTelegramCallback(e,t){let n=e.nextHitlCallbackId??0;e.nextHitlCallbackId=n+1;let r=`${TELEGRAM_HITL_CALLBACK_PREFIX}${n.toString(36)}`;return e.hitlCallbacks={...e.hitlCallbacks,[r]:t},r}function truncate(e,t){if(e.length<=t)return e;let n=Math.max(0,t-3);return`${e.slice(0,n).trimEnd()}...`}function chunk(e,t){let n=[];for(let r=0;r<e.length;r+=t)n.push(e.slice(r,r+t));return n}export{TELEGRAM_CALLBACK_RESPONSE_PREFIX,TELEGRAM_HITL_CALLBACK_PREFIX,TELEGRAM_REPLY_RESPONSE_PREFIX,isTelegramSyntheticResponse,registerTelegramFreeformPrompt,registerTelegramHitlPrompt,renderTelegramInputRequest,resolveTelegramInputResponses,takeTelegramResolvedPrompt,telegramCallbackInputResponse,telegramReplyInputResponse,telegramReplyInputResponses};
1
+ import{parseInputResponse,parseInputResponses}from"#shared/input.js";import{resolvedPromptLabel}from"#channel/resolved-prompt.js";const TELEGRAM_HITL_CALLBACK_PREFIX=`eve:`,TELEGRAM_CALLBACK_RESPONSE_PREFIX=`telegram_callback:`,TELEGRAM_REPLY_RESPONSE_PREFIX=`telegram_reply:`,TELEGRAM_PROMPT_MAX_LENGTH=4e3;function renderTelegramInputRequest(e,t){let n=e.options;return n&&n.length>0?{replyMarkup:{inline_keyboard:chunk(n.map(n=>({callback_data:registerTelegramCallback(t,{optionId:n.id,requestId:e.requestId}),text:truncate(n.label,64)})),2)},text:truncate(e.prompt,TELEGRAM_PROMPT_MAX_LENGTH)}:{freeformRequestId:e.requestId,replyMarkup:{force_reply:!0,input_field_placeholder:truncate(`Type your answer`,64),selective:!0},text:truncate(e.prompt,TELEGRAM_PROMPT_MAX_LENGTH)}}function registerTelegramFreeformPrompt(e,t){e.pendingFreeformReplies={...e.pendingFreeformReplies,[t.messageId]:t.requestId}}function registerTelegramHitlPrompt(e,t,n){e.hitlPrompts={...e.hitlPrompts,[t.requestId]:{...n,options:(t.options??[]).map(({id:e,label:t})=>({id:e,label:t}))}}}function takeTelegramResolvedPrompt(e,t){let n=e.hitlPrompts?.[t.requestId];if(n===void 0)return;let{[t.requestId]:r,...i}=e.hitlPrompts??{};return e.hitlPrompts=i,{messageId:n.messageId,text:telegramResolvedPromptText(n.text,resolvedPromptLabel(t,n.options))}}function telegramResolvedPromptText(e,t){return`${e}\n\n${truncate(t,90)}`}function telegramCallbackInputResponse(e){return parseInputResponse({optionId:`selected`,requestId:`${TELEGRAM_CALLBACK_RESPONSE_PREFIX}${e}`})}function telegramReplyInputResponse(e){return parseInputResponse({requestId:`${TELEGRAM_REPLY_RESPONSE_PREFIX}${e.messageId}`,text:e.text})}function telegramReplyInputResponses(e,t){if(typeof e!=`string`)return[];let n=typeof t==`string`?t:(t??[]).flatMap(e=>e.type===`text`?[e.text]:[]).join(`
2
+ `);return n.trim().length===0?[]:[telegramReplyInputResponse({messageId:e,text:n})]}function isTelegramSyntheticResponse(e){return e.requestId.startsWith(`telegram_callback:`)||e.requestId.startsWith(`telegram_reply:`)}function resolveTelegramInputResponses(e,t){let n=[];for(let r of t){if(r.requestId.startsWith(`telegram_callback:`)){let t=r.requestId.slice(18),i=e.hitlCallbacks?.[t];i!==void 0&&n.push(i);continue}if(r.requestId.startsWith(`telegram_reply:`)){let t=r.requestId.slice(15),i=e.pendingFreeformReplies?.[t];i!==void 0&&r.text!==void 0&&(n.push({requestId:i,text:r.text}),delete e.pendingFreeformReplies?.[t]);continue}n.push(r)}return[...parseInputResponses(n)]}function registerTelegramCallback(e,t){let n=e.nextHitlCallbackId??0;e.nextHitlCallbackId=n+1;let r=`${TELEGRAM_HITL_CALLBACK_PREFIX}${n.toString(36)}`;return e.hitlCallbacks={...e.hitlCallbacks,[r]:t},r}function truncate(e,t){if(e.length<=t)return e;let n=Math.max(0,t-3);return`${e.slice(0,n).trimEnd()}...`}function chunk(e,t){let n=[];for(let r=0;r<e.length;r+=t)n.push(e.slice(r,r+t));return n}export{TELEGRAM_CALLBACK_RESPONSE_PREFIX,TELEGRAM_HITL_CALLBACK_PREFIX,TELEGRAM_REPLY_RESPONSE_PREFIX,isTelegramSyntheticResponse,registerTelegramFreeformPrompt,registerTelegramHitlPrompt,renderTelegramInputRequest,resolveTelegramInputResponses,takeTelegramResolvedPrompt,telegramCallbackInputResponse,telegramReplyInputResponse,telegramReplyInputResponses,telegramResolvedPromptText};
@@ -42,6 +42,8 @@ export interface TelegramMessageReference {
42
42
  readonly from?: TelegramUser;
43
43
  readonly messageId: string;
44
44
  readonly messageThreadId?: number;
45
+ /** The message's text, which Telegram includes on a callback query's message. */
46
+ readonly text?: string;
45
47
  }
46
48
  /**
47
49
  * Channel-owned representation of one inbound Telegram message. `text` and
@@ -1,2 +1,2 @@
1
1
  import{isNonEmptyString,isObject}from"#shared/guards.js";function parseTelegramUpdate(e){if(!isObject(e))return null;let t=parseTelegramMessage(e.message);if(t!==null)return{kind:`message`,message:t};let n=parseTelegramCallbackQuery(e.callback_query);return n===null?null:{callbackQuery:n,kind:`callback_query`}}function formatTelegramContextBlock(e){return[`<telegram_context>`,`response_medium: telegram`,`response_instructions: Reply for Telegram in concise plain text. Avoid tables, long code fences, and formatting that depends on Markdown rendering.`,`chat_id: ${e.chatId}`,`chat_type: ${e.chatType}`,...e.chatTitle?[`chat_title: ${e.chatTitle}`]:[],`message_id: ${e.messageId}`,...e.messageThreadId===void 0?[]:[`message_thread_id: ${e.messageThreadId}`],...e.userId?[`user_id: ${e.userId}`]:[],...e.username?[`username: ${e.username}`]:[],...e.botUsername?[`bot_username: ${e.botUsername}`]:[],...e.isMentioned===void 0?[]:[`is_mentioned: ${e.isMentioned}`],`</telegram_context>`].join(`
2
- `)}function parseTelegramMessage(e){if(!isObject(e))return null;let t=parseTelegramChat(e.chat),n=numberLikeToString(e.message_id);return!t||!n?null:{attachments:parseAttachments(e),caption:typeof e.caption==`string`?e.caption:``,chat:t,from:parseTelegramUser(e.from),messageId:n,messageThreadId:typeof e.message_thread_id==`number`?e.message_thread_id:void 0,raw:e,replyToMessage:parseMessageReference(e.reply_to_message),text:typeof e.text==`string`?e.text:``}}function parseTelegramCallbackQuery(e){if(!isObject(e)||!isNonEmptyString(e.id))return null;let t=parseTelegramUser(e.from);return t?{data:typeof e.data==`string`?e.data:void 0,from:t,id:e.id,message:parseMessageReference(e.message),raw:e}:null}function parseMessageReference(e){if(!isObject(e))return;let t=parseTelegramChat(e.chat),n=numberLikeToString(e.message_id);if(t&&n)return{chat:t,from:parseTelegramUser(e.from),messageId:n,messageThreadId:typeof e.message_thread_id==`number`?e.message_thread_id:void 0}}function parseTelegramChat(e){if(!isObject(e))return null;let t=numberLikeToString(e.id),n=parseTelegramChatType(e.type);return!t||!n?null:{id:t,title:typeof e.title==`string`?e.title:void 0,type:n,username:typeof e.username==`string`?e.username:void 0}}function parseTelegramUser(e){if(!isObject(e))return;let t=numberLikeToString(e.id);if(t)return{firstName:typeof e.first_name==`string`?e.first_name:void 0,id:t,isBot:e.is_bot===!0,languageCode:typeof e.language_code==`string`?e.language_code:void 0,lastName:typeof e.last_name==`string`?e.last_name:void 0,username:typeof e.username==`string`?e.username:void 0}}function parseAttachments(e){let t=[],n=parseLargestPhoto(e.photo);n!==null&&t.push(n);let r=parseDocument(e.document);return r!==null&&t.push(r),t}function parseLargestPhoto(e){if(!Array.isArray(e)||e.length===0)return null;let t=e.filter(isObject).map(e=>({fileId:typeof e.file_id==`string`?e.file_id:``,fileUniqueId:typeof e.file_unique_id==`string`?e.file_unique_id:void 0,height:typeof e.height==`number`?e.height:void 0,size:typeof e.file_size==`number`?e.file_size:void 0,width:typeof e.width==`number`?e.width:void 0})).filter(e=>e.fileId.length>0).sort((e,t)=>scorePhoto(t)-scorePhoto(e))[0];return t?{fileId:t.fileId,fileName:`photo.jpg`,fileUniqueId:t.fileUniqueId,height:t.height,kind:`photo`,mediaType:`image/jpeg`,size:t.size,width:t.width}:null}function parseDocument(e){return!isObject(e)||typeof e.file_id!=`string`?null:{fileId:e.file_id,fileName:typeof e.file_name==`string`?e.file_name:void 0,fileUniqueId:typeof e.file_unique_id==`string`?e.file_unique_id:void 0,kind:`document`,mediaType:typeof e.mime_type==`string`?e.mime_type:void 0,size:typeof e.file_size==`number`?e.file_size:void 0}}function scorePhoto(e){return e.size===void 0?(e.width??0)*(e.height??0):e.size}function parseTelegramChatType(e){return e===`channel`||e===`group`||e===`private`||e===`supergroup`?e:null}function numberLikeToString(e){if(typeof e==`string`&&e.length>0)return e;if(typeof e==`number`&&Number.isFinite(e))return String(e)}export{formatTelegramContextBlock,parseTelegramChatType,parseTelegramUpdate};
2
+ `)}function parseTelegramMessage(e){if(!isObject(e))return null;let t=parseTelegramChat(e.chat),n=numberLikeToString(e.message_id);return!t||!n?null:{attachments:parseAttachments(e),caption:typeof e.caption==`string`?e.caption:``,chat:t,from:parseTelegramUser(e.from),messageId:n,messageThreadId:typeof e.message_thread_id==`number`?e.message_thread_id:void 0,raw:e,replyToMessage:parseMessageReference(e.reply_to_message),text:typeof e.text==`string`?e.text:``}}function parseTelegramCallbackQuery(e){if(!isObject(e)||!isNonEmptyString(e.id))return null;let t=parseTelegramUser(e.from);return t?{data:typeof e.data==`string`?e.data:void 0,from:t,id:e.id,message:parseMessageReference(e.message),raw:e}:null}function parseMessageReference(e){if(!isObject(e))return;let t=parseTelegramChat(e.chat),n=numberLikeToString(e.message_id);if(t&&n)return{chat:t,from:parseTelegramUser(e.from),messageId:n,messageThreadId:typeof e.message_thread_id==`number`?e.message_thread_id:void 0,text:typeof e.text==`string`?e.text:void 0}}function parseTelegramChat(e){if(!isObject(e))return null;let t=numberLikeToString(e.id),n=parseTelegramChatType(e.type);return!t||!n?null:{id:t,title:typeof e.title==`string`?e.title:void 0,type:n,username:typeof e.username==`string`?e.username:void 0}}function parseTelegramUser(e){if(!isObject(e))return;let t=numberLikeToString(e.id);if(t)return{firstName:typeof e.first_name==`string`?e.first_name:void 0,id:t,isBot:e.is_bot===!0,languageCode:typeof e.language_code==`string`?e.language_code:void 0,lastName:typeof e.last_name==`string`?e.last_name:void 0,username:typeof e.username==`string`?e.username:void 0}}function parseAttachments(e){let t=[],n=parseLargestPhoto(e.photo);n!==null&&t.push(n);let r=parseDocument(e.document);return r!==null&&t.push(r),t}function parseLargestPhoto(e){if(!Array.isArray(e)||e.length===0)return null;let t=e.filter(isObject).map(e=>({fileId:typeof e.file_id==`string`?e.file_id:``,fileUniqueId:typeof e.file_unique_id==`string`?e.file_unique_id:void 0,height:typeof e.height==`number`?e.height:void 0,size:typeof e.file_size==`number`?e.file_size:void 0,width:typeof e.width==`number`?e.width:void 0})).filter(e=>e.fileId.length>0).sort((e,t)=>scorePhoto(t)-scorePhoto(e))[0];return t?{fileId:t.fileId,fileName:`photo.jpg`,fileUniqueId:t.fileUniqueId,height:t.height,kind:`photo`,mediaType:`image/jpeg`,size:t.size,width:t.width}:null}function parseDocument(e){return!isObject(e)||typeof e.file_id!=`string`?null:{fileId:e.file_id,fileName:typeof e.file_name==`string`?e.file_name:void 0,fileUniqueId:typeof e.file_unique_id==`string`?e.file_unique_id:void 0,kind:`document`,mediaType:typeof e.mime_type==`string`?e.mime_type:void 0,size:typeof e.file_size==`number`?e.file_size:void 0}}function scorePhoto(e){return e.size===void 0?(e.width??0)*(e.height??0):e.size}function parseTelegramChatType(e){return e===`channel`||e===`group`||e===`private`||e===`supergroup`?e:null}function numberLikeToString(e){if(typeof e==`string`&&e.length>0)return e;if(typeof e==`number`&&Number.isFinite(e))return String(e)}export{formatTelegramContextBlock,parseTelegramChatType,parseTelegramUpdate};
@@ -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,editTelegramMessageText,sendTelegramChatAction,sendTelegramMessage,splitTelegramMessageText,telegramContinuationToken}from"#public/channels/telegram/api.js";import{TELEGRAM_AUTHORIZATION_CALLBACK_PREFIX}from"#public/channels/telegram/authorization.js";import{TELEGRAM_HITL_CALLBACK_PREFIX,isTelegramSyntheticResponse,resolveTelegramInputResponses,telegramCallbackInputResponse,telegramReplyInputResponses}from"#public/channels/telegram/hitl.js";import{buildTelegramTurnMessage,collectTelegramFileParts,createTelegramFetchFile}from"#public/channels/telegram/attachments.js";import{defaultEvents,defaultOnMessage,defaultTelegramAuth,isTelegramBotMentioned}from"#public/channels/telegram/defaults.js";import{verifyTelegramRequest}from"#public/channels/telegram/verify.js";import{dispatchTelegramAuthorizationCallback}from"#public/channels/telegram/authorization-callback.js";import{initialTelegramState,stateFromTelegramCallbackQuery,stateFromTelegramMessage,telegramContinuationTokenFromState}from"#public/channels/telegram/state.js";import{telegramInstrumentation}from"#public/channels/telegram/audience.js";const log=createLogger(`telegram.channel`);function telegramChannel(e={}){let t=mergeUploadPolicy(e.uploadPolicy),n=e.onMessage??defaultOnMessage,r={...defaultEvents,...e.events},i=defineChannel({kindHint:`telegram`,turnPolicy:e.turnPolicy,uploadPolicy:e.uploadPolicy,state:initialTelegramState(e.botUsername),...telegramInstrumentation,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:i,resolveSession: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 l=parseTelegramUpdate(c);return l===null?new Response(`ok`):l.kind===`message`?(o(dispatchMessage({config:e,message:l.message,onMessage:n,uploadPolicy:t,from:i})),new Response(`ok`)):(o(dispatchCallbackQuery({config:e,query:l.callbackQuery,from:i,resolveSession: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=readChatId(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(telegramContinuationTokenFromState(c)).send(t.message,{auth:t.auth,state:c})},events:r});return attachTelegramDeliver(i),i}function rebuildTelegramContext(e,t,n){return{state:e,telegram:buildTelegramHandle({config:n,session:t,state:e})}}function buildTelegramHandle(e){let t=e.config.api,n=e.state,r=e.config.credentials;function anchor(t){let r=n.chatType??t.chatType??null;n.chatType===null&&t.chatType!==void 0&&(n.chatType=t.chatType),t.id&&shouldAnchorTelegramConversation(r)&&(n.conversationId=t.id,n.chatId&&e.session?.continuation?.alias(telegramContinuationToken({chatId:n.chatId,conversationId:t.id,messageThreadId:n.messageThreadId??void 0})))}async function sendOne(e){let t=await sendMessage(e);return anchor(t),t}async function sendMessage(e){let i=n.chatId??``;if(!i)throw Error(`telegramChannel: missing chat id for outbound message.`);return sendTelegramMessage({apiBaseUrl:t?.apiBaseUrl,body:{...e,message_thread_id:e.message_thread_id??n.messageThreadId??void 0},credentials:r,fetch:t?.fetch,fileBaseUrl:t?.fileBaseUrl,chatId:i})}return{botUsername:n.botUsername??e.config.botUsername,chatId:n.chatId??``,chatType:n.chatType??void 0,conversationId:n.conversationId??void 0,messageThreadId:n.messageThreadId??void 0,answerCallbackQuery(e){return answerTelegramCallbackQuery({apiBaseUrl:t?.apiBaseUrl,callbackQueryId:e.callbackQueryId,credentials:r,fetch:t?.fetch,showAlert:e.showAlert,text:e.text})},editMessageReplyMarkup(e){let i=n.chatId??``;if(!i)throw Error(`telegramChannel: missing chat id for reply-markup edit.`);return editTelegramMessageReplyMarkup({apiBaseUrl:t?.apiBaseUrl,chatId:i,credentials:r,fetch:t?.fetch,messageId:e.messageId,replyMarkup:e.replyMarkup})},editMessageText(e){let i=n.chatId??``;if(!i)throw Error(`telegramChannel: missing chat id for text edit.`);return editTelegramMessageText({apiBaseUrl:t?.apiBaseUrl,chatId:i,credentials:r,fetch:t?.fetch,messageId:e.messageId,replyMarkup:e.replyMarkup,text:e.text})},post(e){return postTelegramMessage(e,sendOne)},postEphemeral(e,t,n){return postTelegramMessage({...typeof t==`string`?{text:t}:t,ephemeral_message_parameters:{...n?.callbackQueryId===void 0?{}:{callback_query_id:n.callbackQueryId},receiver_user_id:e}},sendMessage)},request(e,n){return callTelegramApi({apiBaseUrl:t?.apiBaseUrl,body:n,botToken:r?.botToken,fetch:t?.fetch,method:e})},sendMessage(e){return postTelegramMessage(e,sendOne)},async startTyping(e=`typing`){let i=n.chatId??``;if(i)try{await sendTelegramChatAction({action:e,apiBaseUrl:t?.apiBaseUrl,chatId:i,credentials:r,fetch:t?.fetch,messageThreadId:n.messageThreadId??void 0})}catch(e){logError(log,`Telegram typing indicator failed — swallowed`,e,{chatId:i})}}}}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}:{...n.ephemeral_message_parameters===void 0?{}:{ephemeral_message_parameters:n.ephemeral_message_parameters},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=stateFromTelegramMessage(e.message,e.config.botUsername),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,isMentioned:isTelegramBotMentioned(e.message,e.config.botUsername),messageId:e.message.messageId,messageThreadId:e.message.messageThreadId,userId:e.message.from?.id,username:e.message.from?.username}),s=r.context??[];try{await e.from(telegramContinuationTokenFromState(t)).send(a,{auth:r.auth,context:[o,...s],state:t,title:r.title})}catch(e){log.error(`message delivery failed`,{error:e})}}async function dispatchCallbackQuery(e){let t=stateFromTelegramCallbackQuery(e.query,e.config.botUsername),n={telegram:buildTelegramHandle({config:e.config,state:t})};if(e.query.data?.startsWith(TELEGRAM_AUTHORIZATION_CALLBACK_PREFIX)===!0){await dispatchTelegramAuthorizationCallback({continuationToken:telegramContinuationTokenFromState(t),query:e.query,resolveSession:e.resolveSession,state:t,telegram:n});return}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(telegramContinuationTokenFromState(t)).respond([telegramCallbackInputResponse(e.query.data)],{auth:defaultTelegramAuth({...e.query.message,from:e.query.from})})}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.state,r=[...e.inputResponses??[],...telegramReplyInputResponses(n?.replyToBotMessageId,e.message)];if(r.some(isTelegramSyntheticResponse)){let n=resolveTelegramInputResponses(t.state,r);return n.length>0?{inputResponses:n,context:e.context}:e.message===void 0?void 0:{message:e.message,context:e.context}}return defaultDeliverResult(e)}}function readChatId(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{INACTIVE_REQUEST_NOTICE,respondOrRetireInactivePrompt}from"#channel/inactive-prompt.js";import{formatTelegramContextBlock,parseTelegramUpdate}from"#public/channels/telegram/inbound.js";import{answerTelegramCallbackQuery,callTelegramApi,editTelegramMessageReplyMarkup,editTelegramMessageText,sendTelegramChatAction,sendTelegramMessage,splitTelegramMessageText,telegramContinuationToken}from"#public/channels/telegram/api.js";import{TELEGRAM_AUTHORIZATION_CALLBACK_PREFIX}from"#public/channels/telegram/authorization.js";import{TELEGRAM_HITL_CALLBACK_PREFIX,isTelegramSyntheticResponse,resolveTelegramInputResponses,telegramCallbackInputResponse,telegramReplyInputResponses,telegramResolvedPromptText}from"#public/channels/telegram/hitl.js";import{buildTelegramTurnMessage,collectTelegramFileParts,createTelegramFetchFile}from"#public/channels/telegram/attachments.js";import{defaultEvents,defaultOnMessage,defaultTelegramAuth,isTelegramBotMentioned}from"#public/channels/telegram/defaults.js";import{verifyTelegramRequest}from"#public/channels/telegram/verify.js";import{dispatchTelegramAuthorizationCallback}from"#public/channels/telegram/authorization-callback.js";import{initialTelegramState,stateFromTelegramCallbackQuery,stateFromTelegramMessage,telegramContinuationTokenFromState}from"#public/channels/telegram/state.js";import{telegramInstrumentation}from"#public/channels/telegram/audience.js";const log=createLogger(`telegram.channel`);function telegramChannel(e={}){let t=mergeUploadPolicy(e.uploadPolicy),n=e.onMessage??defaultOnMessage,r={...defaultEvents,...e.events},i=defineChannel({kindHint:`telegram`,turnPolicy:e.turnPolicy,uploadPolicy:e.uploadPolicy,state:initialTelegramState(e.botUsername),...telegramInstrumentation,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:i,resolveSession: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 l=parseTelegramUpdate(c);return l===null?new Response(`ok`):l.kind===`message`?(o(dispatchMessage({config:e,message:l.message,onMessage:n,uploadPolicy:t,from:i})),new Response(`ok`)):(o(dispatchCallbackQuery({config:e,query:l.callbackQuery,from:i,resolveSession: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=readChatId(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(telegramContinuationTokenFromState(c)).send(t.message,{auth:t.auth,state:c})},events:r});return attachTelegramDeliver(i),i}function rebuildTelegramContext(e,t,n){return{state:e,telegram:buildTelegramHandle({config:n,session:t,state:e})}}function buildTelegramHandle(e){let t=e.config.api,n=e.state,r=e.config.credentials;function anchor(t){let r=n.chatType??t.chatType??null;n.chatType===null&&t.chatType!==void 0&&(n.chatType=t.chatType),t.id&&shouldAnchorTelegramConversation(r)&&(n.conversationId=t.id,n.chatId&&e.session?.continuation?.alias(telegramContinuationToken({chatId:n.chatId,conversationId:t.id,messageThreadId:n.messageThreadId??void 0})))}async function sendOne(e){let t=await sendMessage(e);return anchor(t),t}async function sendMessage(e){let i=n.chatId??``;if(!i)throw Error(`telegramChannel: missing chat id for outbound message.`);return sendTelegramMessage({apiBaseUrl:t?.apiBaseUrl,body:{...e,message_thread_id:e.message_thread_id??n.messageThreadId??void 0},credentials:r,fetch:t?.fetch,fileBaseUrl:t?.fileBaseUrl,chatId:i})}return{botUsername:n.botUsername??e.config.botUsername,chatId:n.chatId??``,chatType:n.chatType??void 0,conversationId:n.conversationId??void 0,messageThreadId:n.messageThreadId??void 0,answerCallbackQuery(e){return answerTelegramCallbackQuery({apiBaseUrl:t?.apiBaseUrl,callbackQueryId:e.callbackQueryId,credentials:r,fetch:t?.fetch,showAlert:e.showAlert,text:e.text})},editMessageReplyMarkup(e){let i=n.chatId??``;if(!i)throw Error(`telegramChannel: missing chat id for reply-markup edit.`);return editTelegramMessageReplyMarkup({apiBaseUrl:t?.apiBaseUrl,chatId:i,credentials:r,fetch:t?.fetch,messageId:e.messageId,replyMarkup:e.replyMarkup})},editMessageText(e){let i=n.chatId??``;if(!i)throw Error(`telegramChannel: missing chat id for text edit.`);return editTelegramMessageText({apiBaseUrl:t?.apiBaseUrl,chatId:i,credentials:r,fetch:t?.fetch,messageId:e.messageId,replyMarkup:e.replyMarkup,text:e.text})},post(e){return postTelegramMessage(e,sendOne)},postEphemeral(e,t,n){return postTelegramMessage({...typeof t==`string`?{text:t}:t,ephemeral_message_parameters:{...n?.callbackQueryId===void 0?{}:{callback_query_id:n.callbackQueryId},receiver_user_id:e}},sendMessage)},request(e,n){return callTelegramApi({apiBaseUrl:t?.apiBaseUrl,body:n,botToken:r?.botToken,fetch:t?.fetch,method:e})},sendMessage(e){return postTelegramMessage(e,sendOne)},async startTyping(e=`typing`){let i=n.chatId??``;if(i)try{await sendTelegramChatAction({action:e,apiBaseUrl:t?.apiBaseUrl,chatId:i,credentials:r,fetch:t?.fetch,messageThreadId:n.messageThreadId??void 0})}catch(e){logError(log,`Telegram typing indicator failed — swallowed`,e,{chatId:i})}}}}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}:{...n.ephemeral_message_parameters===void 0?{}:{ephemeral_message_parameters:n.ephemeral_message_parameters},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=stateFromTelegramMessage(e.message,e.config.botUsername),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,isMentioned:isTelegramBotMentioned(e.message,e.config.botUsername),messageId:e.message.messageId,messageThreadId:e.message.messageThreadId,userId:e.message.from?.id,username:e.message.from?.username}),s=r.context??[];try{await e.from(telegramContinuationTokenFromState(t)).send(a,{auth:r.auth,context:[o,...s],state:t,title:r.title})}catch(e){log.error(`message delivery failed`,{error:e})}}async function dispatchCallbackQuery(e){let t=stateFromTelegramCallbackQuery(e.query,e.config.botUsername),n={telegram:buildTelegramHandle({config:e.config,state:t})};if(e.query.data?.startsWith(TELEGRAM_AUTHORIZATION_CALLBACK_PREFIX)===!0){await dispatchTelegramAuthorizationCallback({continuationToken:telegramContinuationTokenFromState(t),query:e.query,resolveSession:e.resolveSession,state:t,telegram:n});return}if(e.query.data?.startsWith(TELEGRAM_HITL_CALLBACK_PREFIX)===!0){let r=e.query.message,i=e.query.data,a=r&&t.chatId?await respondOrRetireInactivePrompt(()=>e.from(telegramContinuationTokenFromState(t)).respond([telegramCallbackInputResponse(i)],{auth:defaultTelegramAuth({...r,from:e.query.from})}),{retirePrompt:e=>retireInactivePrompt(n,r,e)},log):void 0;try{await n.telegram.answerCallbackQuery({callbackQueryId:e.query.id,text:a?.outcome===`inactive`?INACTIVE_REQUEST_NOTICE:`Answer received.`})}catch(e){log.warn(`Telegram callback-query acknowledgement failed`,{error:e})}a?.outcome===`inactive`&&await a.retirement;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})}}async function retireInactivePrompt(e,t,n){let r={inline_keyboard:[]};if(t.text===void 0){await e.telegram.editMessageReplyMarkup({messageId:t.messageId,replyMarkup:r});return}await e.telegram.editMessageText({messageId:t.messageId,replyMarkup:r,text:telegramResolvedPromptText(t.text,n)})}function attachTelegramDeliver(e){if(!isCompiledChannel(e))return;let t=e.adapter;t.deliver=(e,t)=>{let n=e.state,r=[...e.inputResponses??[],...telegramReplyInputResponses(n?.replyToBotMessageId,e.message)];if(r.some(isTelegramSyntheticResponse)){let n=resolveTelegramInputResponses(t.state,r);return n.length>0?{inputResponses:n,context:e.context}:e.message===void 0?void 0:{message:e.message,context:e.context}}return defaultDeliverResult(e)}}function readChatId(e){if(typeof e==`string`&&e.length>0)return e;if(typeof e==`number`&&Number.isFinite(e))return String(e)}export{telegramChannel};
@@ -1 +1 @@
1
- import{createMetadataAudienceProjector}from"#channel/audience.js";import{CHANNEL_SENTINEL}from"#channel/compiled-channel.js";import{defaultDeliverResult}from"#channel/adapter.js";import{buildCallbackContext}from"#context/build-callback-context.js";import{mergeUploadPolicy}from"#public/channels/upload-policy.js";import{SessionStrandedError}from"#channel/session-stranded-error.js";import{normalizeChannelCors}from"#channel/cors.js";import{HTTP_ADAPTER_KIND}from"#channel/http.js";import{DELETE,GET,HEAD,OPTIONS,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(e){let t=buildAdapter(e),n=normalizeChannelCors(e.cors);return{__kind:CHANNEL_SENTINEL,routes:e.routes,adapter:t,cors:n,receive:e.receive,turnPolicy:e.turnPolicy}}const eventTypes=Object.keys({"approval.candidate":null,"approval.settled":null,"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,"step.started":null,"step.completed":null,"input.requested":null,"input.resolved":null,"task.started":null,"task.settled":null,"turn.waiting":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 t=e.state!=null,n=e.context!=null,r=e.fetchFile!==void 0,i=e.metadata,a=i!==void 0,o=e.audience,s=e.uploadPolicy===void 0?void 0:mergeUploadPolicy(e.uploadPolicy),c=t||n||a||s!==void 0,l={},u=!1,d={kind:e.kindHint??`defineChannel`},f=e.events;for(let e of eventTypes){let t=f?.[e];t&&(u=!0,l[e]=(n,r)=>{let{session:i,...a}=r,o={...a,continuation:i?.continuation===void 0?void 0:{token:i.continuation.token,alias:e=>i.continuation?.alias(e)}};if(e===`session.failed`)return t(n,o);let s=buildCallbackContext();return t(n,o,s)})}return!c&&!u&&!r?{kind:e.kindHint??HTTP_ADAPTER_KIND,...o===void 0?void 0:{instrumentation:{audience:o}}}:{kind:e.kindHint??`defineChannel`,state:t?{...e.state}:{},fetchFile:e.fetchFile,uploadPolicy:s,instrumentation:i===void 0&&o===void 0?void 0:{...i===void 0?void 0:{metadata(e){let{audience:t,...n}=i(e);return n}},...o===void 0?i===void 0?void 0:{audience:createMetadataAudienceProjector(d,i)}:{audience:o}},createAdapterContext(t){let r=t.state,i=t.session;return{...n?e.context(r,i):{},state:r,ctx:t.ctx,session:i}},deliver(t,n){return e.deliver===void 0?defaultDeliverResult(t):e.deliver(t,n)},...l}}export{DELETE,GET,HEAD,OPTIONS,PATCH,POST,PUT,SessionStrandedError,WS,defineChannel,disableRoute,isDisabledRouteSentinel};
1
+ import{createMetadataAudienceProjector}from"#channel/audience.js";import{CHANNEL_SENTINEL}from"#channel/compiled-channel.js";import{defaultDeliverResult}from"#channel/adapter.js";import{SessionStrandedError}from"#channel/session-stranded-error.js";import{buildCallbackContext}from"#context/build-callback-context.js";import{mergeUploadPolicy}from"#public/channels/upload-policy.js";import{normalizeChannelCors}from"#channel/cors.js";import{HTTP_ADAPTER_KIND}from"#channel/http.js";import{DELETE,GET,HEAD,OPTIONS,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(e){let t=buildAdapter(e),n=normalizeChannelCors(e.cors);return{__kind:CHANNEL_SENTINEL,routes:e.routes,adapter:t,cors:n,receive:e.receive,turnPolicy:e.turnPolicy}}const eventTypes=Object.keys({"approval.candidate":null,"approval.settled":null,"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,"step.started":null,"step.completed":null,"input.requested":null,"input.resolved":null,"task.started":null,"task.settled":null,"turn.waiting":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 t=e.state!=null,n=e.context!=null,r=e.fetchFile!==void 0,i=e.metadata,a=i!==void 0,o=e.audience,s=e.uploadPolicy===void 0?void 0:mergeUploadPolicy(e.uploadPolicy),c=t||n||a||s!==void 0,l={},u=!1,d={kind:e.kindHint??`defineChannel`},f=e.events;for(let e of eventTypes){let t=f?.[e];t&&(u=!0,l[e]=(n,r)=>{let{session:i,...a}=r,o={...a,continuation:i?.continuation===void 0?void 0:{token:i.continuation.token,alias:e=>i.continuation?.alias(e)}};if(e===`session.failed`)return t(n,o);let s=buildCallbackContext();return t(n,o,s)})}return!c&&!u&&!r?{kind:e.kindHint??HTTP_ADAPTER_KIND,...o===void 0?void 0:{instrumentation:{audience:o}}}:{kind:e.kindHint??`defineChannel`,state:t?{...e.state}:{},fetchFile:e.fetchFile,uploadPolicy:s,instrumentation:i===void 0&&o===void 0?void 0:{...i===void 0?void 0:{metadata(e){let{audience:t,...n}=i(e);return n}},...o===void 0?i===void 0?void 0:{audience:createMetadataAudienceProjector(d,i)}:{audience:o}},createAdapterContext(t){let r=t.state,i=t.session;return{...n?e.context(r,i):{},state:r,ctx:t.ctx,session:i}},deliver(t,n){return e.deliver===void 0?defaultDeliverResult(t):e.deliver(t,n)},...l}}export{DELETE,GET,HEAD,OPTIONS,PATCH,POST,PUT,SessionStrandedError,WS,defineChannel,disableRoute,isDisabledRouteSentinel};
@@ -4,7 +4,7 @@ import type { ConnectionClient, ConnectionToolExecuteOptions, ConnectionToolMeta
4
4
  /**
5
5
  * Wraps one `MCPClient` from `@ai-sdk/mcp` for a single connection.
6
6
  *
7
- * Created lazily per-connection per-session. Caches tool metadata after
7
+ * Created lazily per connection per step. Caches tool metadata after
8
8
  * the first `getToolMetadata()` call.
9
9
  *
10
10
  * When the connection declares `authorization` but no token is available
@@ -1 +1 @@
1
- import{isObject}from"#shared/guards.js";import{buildCallbackContext}from"#context/build-callback-context.js";import{ConnectionAuthorizationRequiredError,isConnectionAuthorizationRequiredError}from"#connections/errors.js";import{resolveConnectionAuthorization}from"#runtime/connections/resolve-authorization.js";import{evictScopedToken,resolveScopedToken}from"#runtime/connections/scoped-authorization.js";import{FORWARDED_PRINCIPAL_HEADER,encodeForwardedPrincipalHeader}from"#internal/mcp/forwarded-principal-header.js";import{createMcpTraceFetch,withMcpToolCallSpan,withMcpToolsListSpan}from"#runtime/connections/mcp-tracing.js";import{createMCPClient}from"#compiled/@ai-sdk/mcp/index.js";import{ConnectionEventActions,isEventAction}from"#runtime/connections/events/actions.js";import{readTurnPrincipals}from"#context/turn-principals.js";import{omitProvidedArgumentsFromSchema,resolveProvidedArguments}from"#runtime/connections/provided-arguments.js";var McpConnectionClient=class{#e;#t;#n;#r;#i;#a=!1;eventActions;constructor(e){if(this.#i=e,e.experimental_events!==void 0){let t=new ConnectionEventActions(e,e.experimental_events,()=>resolveHeaders(e),this.#s());this.eventActions={ownsName:isEventAction,recoveryMetadata:()=>t.recoveryMetadata(),metadata:async()=>{try{return await t.metadata()}catch(e){return await this.#d(e)}},execute:async(e,n,r)=>{try{return await t.execute(e,n,r)}catch(e){return await this.#d(e)}}}}}async connect(){if(this.#t!==void 0)return this.#t;if(this.#e!==void 0)return this.#e;this.#e=this.#o();try{return this.#t=await this.#e,this.#t}catch(e){throw this.#e=void 0,e}}async#o(){let{anonymous:e,headers:t}=await resolveConnectionHeaders(this.#i,{anonymousWhenAuthorizationRequired:!0});this.#a=e;let n=this.#i.url,r=createMcpTraceFetch({connectionName:this.#i.connectionName,fetcher:this.#s(),getProtocolVersion:()=>this.#t?.initializeResult?.protocolVersion});try{return await createMCPClient({protocolVersionDiscovery:this.#i.protocolVersionDiscovery,transport:{fetch:r,headers:t,type:`http`,url:n}})}catch(e){if(!isMcpHttpFallbackRetryableError(e))throw e;return await createMCPClient({protocolVersionDiscovery:this.#i.protocolVersionDiscovery,transport:{fetch:r,headers:t,type:`sse`,url:n}})}}#s(){if(this.#i.forwardPrincipal!==!0)return;let e=this.#i.connectionName;return async(t,n)=>{let r=readTurnPrincipals();if(r===void 0)return await globalThis.fetch(t,n);let i=new Headers(n?.headers);return i.set(FORWARDED_PRINCIPAL_HEADER,encodeForwardedPrincipalHeader(r,e)),await globalThis.fetch(t,{...n,headers:i,redirect:`error`})}}async getToolMetadata(){return(await this.#c()).metadata}async executeTool(e,t,n){let r;try{let{tools:i}=await this.#c(),a=i[e];if(a?.execute===void 0)throw Error(`Tool "${e}" not found in connection "${this.#i.connectionName}".`);let o=a.execute,s=await resolveProvidedArguments({args:t,callId:n.callId,connection:this.#i,toolName:e});r=await withMcpToolCallSpan({arguments:t,connectionName:this.#i.connectionName,execute:async()=>await o(s,{abortSignal:n.abortSignal}),protocolVersion:this.#t?.initializeResult?.protocolVersion,toolName:e})}catch(e){return await this.#d(e)}return isMcpAuthChallengeResult(r)?await this.#f(`the server asked for sign-in to call "${e}"`):r}async#c(){if(this.#r!==void 0)return this.#r;if(this.#n!==void 0)return this.#n;this.#n=this.#l();try{return this.#r=await this.#n,this.#r}catch(e){throw this.#n=void 0,e}}async#l(){try{return await this.#u()}catch(e){return await this.#d(e)}}async#u(){let e=await this.connect(),t=await withMcpToolsListSpan({connectionName:this.#i.connectionName,execute:()=>e.listTools(),protocolVersion:e.initializeResult?.protocolVersion}),n=Object.keys(this.#i.toolCall?.providedArguments??{}),r=t.tools.map(e=>({...e,inputSchema:omitProvidedArgumentsFromSchema(e.inputSchema,n)})),i=e.toolsFromDefinitions({tools:r});return{metadata:r.map(e=>({annotations:e.annotations,description:e.description??``,inputSchema:e.inputSchema??{},name:e.name,outputSchema:`outputSchema`in e&&e.outputSchema!==void 0?e.outputSchema:void 0})),tools:i}}async close(){this.#t!==void 0&&(await this.#t.close(),this.#t=void 0),this.#e=void 0,this.#n=void 0,this.#r=void 0,this.#a=!1}async#d(e){if(!isMcpAuthRequiredError(e))throw e;return await this.#f(this.#a?`the server requires sign-in`:`the server rejected the token`)}async#f(e){throw this.#a||await this.#p(),await this.close(),new ConnectionAuthorizationRequiredError(this.#i.connectionName,{message:`Connection "${this.#i.connectionName}" requires authorization (${e}).`})}async#p(){let e=await resolveConnectionAuthorization(this.#i);e!==void 0&&await evictScopedToken({authorization:e,connection:{url:this.#i.url},instanceId:this.#i.instanceId,scope:this.#i.connectionName})}};function isMcpAuthRequiredError(e){return readHttpStatus(e)===401}const MCP_WWW_AUTHENTICATE_META_KEY=`mcp/www_authenticate`;function isMcpAuthChallengeResult(e){if(!isObject(e)||e.isError!==!0||!isObject(e._meta))return!1;let t=e._meta[MCP_WWW_AUTHENTICATE_META_KEY];return(typeof t==`string`||Array.isArray(t))&&t.length>0}function isMcpHttpFallbackRetryableError(e){let t=readHttpStatus(e);return t===400||t===404||t===405}function readHttpStatus(e){for(let t of walkErrorChain(e)){if(!isObject(t))continue;let e=readStatusField(t);if(e!==void 0)return e;let n=t.response;if(isObject(n)){let e=readStatusField(n);if(e!==void 0)return e}if(typeof t.message==`string`){let e=/\bHTTP\s+(\d{3})\b/u.exec(t.message);if(e?.[1]!==void 0)return Number(e[1])}}}function readStatusField(e){if(typeof e.status==`number`)return e.status;if(typeof e.statusCode==`number`)return e.statusCode}function*walkErrorChain(e){let t=e,n=new Set;for(;t!=null&&!n.has(t);){if(n.add(t),yield t,!isObject(t)||!(`cause`in t))return;t=t.cause}}function passesToolFilter(e,t){return t===void 0?!0:`allow`in t?t.allow.includes(e):!t.block.includes(e)}async function resolveHeaders(e){let{headers:t}=await resolveConnectionHeaders(e,{anonymousWhenAuthorizationRequired:!1});return t}async function resolveConnectionHeaders(e,t){let n={},r=!1,i,getCallbackContext=()=>i??=buildCallbackContext(),a=await resolveConnectionAuthorization(e,typeof e.authorization==`function`?getCallbackContext():void 0);if(a!==void 0)try{n.Authorization=`Bearer ${(await resolveToken(e,a)).token}`}catch(e){if(!t.anonymousWhenAuthorizationRequired||!isConnectionAuthorizationRequiredError(e))throw e;r=!0}if(e.headers!==void 0){let t=await resolveHeadersDefinition(e.headers,getCallbackContext);for(let[r,i]of Object.entries(t)){if(a!==void 0&&r.toLowerCase()===`authorization`)throw Error(`Connection "${e.connectionName}" headers must not include an "Authorization" key when "authorization" is also provided.`);n[r]=i}}return{anonymous:r,headers:n}}async function resolveToken(e,t){return await resolveScopedToken({authorization:t,connection:{url:e.url},instanceId:e.instanceId,scope:e.connectionName})}async function resolveHeadersDefinition(e,t){if(typeof e==`function`)return{...await e(t())};let n={},r=Object.entries(e);for(let[e,i]of r)n[e]=await resolveHeaderValue(i,t);return n}async function resolveHeaderValue(e,t){return typeof e==`function`?await e(t()):await e}export{MCP_WWW_AUTHENTICATE_META_KEY,McpConnectionClient,isMcpAuthChallengeResult,isMcpAuthRequiredError,passesToolFilter,readHttpStatus,resolveHeaders};
1
+ import{isObject}from"#shared/guards.js";import{buildCallbackContext}from"#context/build-callback-context.js";import{ConnectionAuthorizationRequiredError,isConnectionAuthorizationRequiredError}from"#connections/errors.js";import{resolveConnectionAuthorization}from"#runtime/connections/resolve-authorization.js";import{evictScopedToken,resolveScopedToken}from"#runtime/connections/scoped-authorization.js";import{FORWARDED_PRINCIPAL_HEADER,encodeForwardedPrincipalHeader}from"#internal/mcp/forwarded-principal-header.js";import{createMcpTraceFetch,withMcpToolCallSpan,withMcpToolsListSpan}from"#runtime/connections/mcp-tracing.js";import{createMCPClient}from"#compiled/@ai-sdk/mcp/index.js";import{ConnectionEventActions,isEventAction}from"#runtime/connections/events/actions.js";import{readTurnPrincipals}from"#context/turn-principals.js";import{omitProvidedArgumentsFromSchema,resolveProvidedArguments}from"#runtime/connections/provided-arguments.js";var McpUnauthorizedError=class extends Error{statusCode=401;anonymous;constructor(e){super(`MCP HTTP request failed (HTTP 401).`),this.anonymous=e}};async function checkAuthorizationResponse(e,t){if(e.status===401)throw await e.body?.cancel(),new McpUnauthorizedError(t);return e}var McpConnectionClient=class{#e;#t;#n;#r;#i;eventActions;constructor(e){if(this.#i=e,e.experimental_events!==void 0){let t=new ConnectionEventActions(e,e.experimental_events,()=>resolveHeaders(e),this.#s());this.eventActions={ownsName:isEventAction,recoveryMetadata:()=>t.recoveryMetadata(),metadata:async()=>{try{return await t.metadata()}catch(e){return await this.#d(e)}},execute:async(e,n,r)=>{try{return await t.execute(e,n,r)}catch(e){return await this.#d(e)}}}}}async connect(){if(this.#t!==void 0)return this.#t;if(this.#e!==void 0)return this.#e;this.#e=this.#a();try{return this.#t=await this.#e,this.#t}catch(e){throw this.#e=void 0,e}}async#a(){let{headers:e}=await resolveConnectionHeaders(this.#i,{anonymousWhenAuthorizationRequired:!0}),t=this.#i.url,n=createMcpTraceFetch({connectionName:this.#i.connectionName,fetcher:this.#o(Object.keys(e)),getProtocolVersion:()=>this.#t?.initializeResult?.protocolVersion});try{return await createMCPClient({protocolVersionDiscovery:this.#i.protocolVersionDiscovery,transport:{fetch:n,headers:e,type:`http`,url:t}})}catch(r){if(!isMcpHttpFallbackRetryableError(r))throw r;return await createMCPClient({protocolVersionDiscovery:this.#i.protocolVersionDiscovery,transport:{fetch:n,headers:e,type:`sse`,url:t}})}}#o(e){let t=this.#s()??globalThis.fetch;return async(n,r)=>{let resolve=()=>resolveConnectionHeaders(this.#i,{anonymousWhenAuthorizationRequired:!0}),send=async i=>{let a=new Headers(r?.headers);for(let t of e)a.delete(t);for(let[e,t]of Object.entries(i.headers))a.set(e,t);return await t(n,{...r,headers:a})},i=await resolve(),a=await send(i);if(a.status!==401||i.anonymous||this.#i.authorization===void 0||r?.signal?.aborted)return await checkAuthorizationResponse(a,i.anonymous);await this.#p();let o=await resolve();return o.anonymous?await checkAuthorizationResponse(a,!0):(await a.body?.cancel(),await checkAuthorizationResponse(await send(o),o.anonymous))}}#s(){if(this.#i.forwardPrincipal!==!0)return;let e=this.#i.connectionName;return async(t,n)=>{let r=readTurnPrincipals();if(r===void 0)return await globalThis.fetch(t,n);let i=new Headers(n?.headers);return i.set(FORWARDED_PRINCIPAL_HEADER,encodeForwardedPrincipalHeader(r,e)),await globalThis.fetch(t,{...n,headers:i,redirect:`error`})}}async getToolMetadata(){return(await this.#c()).metadata}async executeTool(e,t,n){let r;try{let{tools:i}=await this.#c(),a=i[e];if(a?.execute===void 0)throw Error(`Tool "${e}" not found in connection "${this.#i.connectionName}".`);let o=a.execute,s=await resolveProvidedArguments({args:t,callId:n.callId,connection:this.#i,toolName:e});r=await withMcpToolCallSpan({arguments:t,connectionName:this.#i.connectionName,execute:async()=>await o(s,{abortSignal:n.abortSignal}),protocolVersion:this.#t?.initializeResult?.protocolVersion,toolName:e})}catch(e){return await this.#d(e)}return isMcpAuthChallengeResult(r)?await this.#f(`the server asked for sign-in to call "${e}"`):r}async#c(){if(this.#r!==void 0)return this.#r;if(this.#n!==void 0)return this.#n;this.#n=this.#l();try{return this.#r=await this.#n,this.#r}catch(e){throw this.#n=void 0,e}}async#l(){try{return await this.#u()}catch(e){return await this.#d(e)}}async#u(){let e=await this.connect(),t=await withMcpToolsListSpan({connectionName:this.#i.connectionName,execute:()=>e.listTools(),protocolVersion:e.initializeResult?.protocolVersion}),n=Object.keys(this.#i.toolCall?.providedArguments??{}),r=t.tools.map(e=>({...e,inputSchema:omitProvidedArgumentsFromSchema(e.inputSchema,n)})),i=e.toolsFromDefinitions({tools:r});return{metadata:r.map(e=>({annotations:e.annotations,description:e.description??``,inputSchema:e.inputSchema??{},name:e.name,outputSchema:`outputSchema`in e&&e.outputSchema!==void 0?e.outputSchema:void 0})),tools:i}}async close(){this.#t!==void 0&&(await this.#t.close(),this.#t=void 0),this.#e=void 0,this.#n=void 0,this.#r=void 0}async#d(e){if(!isMcpAuthRequiredError(e))throw e;let t=[...walkErrorChain(e)].find(e=>e instanceof McpUnauthorizedError)?.anonymous??(await resolveConnectionHeaders(this.#i,{anonymousWhenAuthorizationRequired:!0})).anonymous;return await this.#f(t?`the server requires sign-in`:`the server rejected the token`,t)}async#f(e,t){throw t??=(await resolveConnectionHeaders(this.#i,{anonymousWhenAuthorizationRequired:!0})).anonymous,t||await this.#p(),await this.close(),new ConnectionAuthorizationRequiredError(this.#i.connectionName,{message:`Connection "${this.#i.connectionName}" requires authorization (${e}).`})}async#p(){let e=await resolveConnectionAuthorization(this.#i);e!==void 0&&await evictScopedToken({authorization:e,connection:{url:this.#i.url},instanceId:this.#i.instanceId,scope:this.#i.connectionName})}};function isMcpAuthRequiredError(e){return readHttpStatus(e)===401}const MCP_WWW_AUTHENTICATE_META_KEY=`mcp/www_authenticate`;function isMcpAuthChallengeResult(e){if(!isObject(e)||e.isError!==!0||!isObject(e._meta))return!1;let t=e._meta[MCP_WWW_AUTHENTICATE_META_KEY];return(typeof t==`string`||Array.isArray(t))&&t.length>0}function isMcpHttpFallbackRetryableError(e){let t=readHttpStatus(e);return t===400||t===404||t===405}function readHttpStatus(e){for(let t of walkErrorChain(e)){if(!isObject(t))continue;let e=readStatusField(t);if(e!==void 0)return e;let n=t.response;if(isObject(n)){let e=readStatusField(n);if(e!==void 0)return e}if(typeof t.message==`string`){let e=/\bHTTP\s+(\d{3})\b/u.exec(t.message);if(e?.[1]!==void 0)return Number(e[1])}}}function readStatusField(e){if(typeof e.status==`number`)return e.status;if(typeof e.statusCode==`number`)return e.statusCode}function*walkErrorChain(e){let t=e,n=new Set;for(;t!=null&&!n.has(t);){if(n.add(t),yield t,!isObject(t)||!(`cause`in t))return;t=t.cause}}function passesToolFilter(e,t){return t===void 0?!0:`allow`in t?t.allow.includes(e):!t.block.includes(e)}async function resolveHeaders(e){let{headers:t}=await resolveConnectionHeaders(e,{anonymousWhenAuthorizationRequired:!1});return t}async function resolveConnectionHeaders(e,t){let n={},r=!1,i,getCallbackContext=()=>i??=buildCallbackContext(),a=await resolveConnectionAuthorization(e,typeof e.authorization==`function`?getCallbackContext():void 0);if(a!==void 0)try{n.Authorization=`Bearer ${(await resolveToken(e,a)).token}`}catch(e){if(!t.anonymousWhenAuthorizationRequired||!isConnectionAuthorizationRequiredError(e))throw e;r=!0}if(e.headers!==void 0){let t=await resolveHeadersDefinition(e.headers,getCallbackContext);for(let[r,i]of Object.entries(t)){if(a!==void 0&&r.toLowerCase()===`authorization`)throw Error(`Connection "${e.connectionName}" headers must not include an "Authorization" key when "authorization" is also provided.`);n[r]=i}}return{anonymous:r,headers:n}}async function resolveToken(e,t){return await resolveScopedToken({authorization:t,connection:{url:e.url},instanceId:e.instanceId,scope:e.connectionName})}async function resolveHeadersDefinition(e,t){if(typeof e==`function`)return{...await e(t())};let n={},r=Object.entries(e);for(let[e,i]of r)n[e]=await resolveHeaderValue(i,t);return n}async function resolveHeaderValue(e,t){return typeof e==`function`?await e(t()):await e}export{MCP_WWW_AUTHENTICATE_META_KEY,McpConnectionClient,isMcpAuthChallengeResult,isMcpAuthRequiredError,passesToolFilter,readHttpStatus,resolveHeaders};
@@ -1 +1 @@
1
- import{createLogger}from"#internal/logging.js";import{isObject}from"#shared/guards.js";import{isLoopbackHostname}from"#shared/network-address.js";import{parseJsonObject}from"#shared/json.js";import{resolveHeaders}from"#runtime/connections/mcp-client.js";import{omitProvidedArgumentsFromSchema,resolveProvidedArguments}from"#runtime/connections/provided-arguments.js";import{HTTP_METHODS,operationDescription,operationName,uniqueName}from"#runtime/connections/openapi-operations.js";import{buildInputSchema,deref,derefSchema,isArray}from"#runtime/connections/openapi-schema.js";import{applySecurity,resolveSecurity}from"#runtime/connections/openapi-security.js";import{extractServerUrl,parseSpecDocument}from"#runtime/connections/openapi-spec.js";const log=createLogger(`runtime.connections.openapi-client`),SWAGGER_PARAMETER_SCHEMA_KEYS=[`default`,`enum`,`exclusiveMaximum`,`exclusiveMinimum`,`format`,`items`,`maximum`,`maxItems`,`maxLength`,`minimum`,`minItems`,`minLength`,`multipleOf`,`pattern`,`type`,`uniqueItems`];var OpenApiConnectionClient=class{#e;#t;#n;constructor(e){this.#n=e}async connect(){return this.#r()}async getToolMetadata(){return(await this.#r()).metadata}async executeTool(e,t,n){let r=await this.#r(),i=r.operations.get(e);if(i===void 0)throw Error(`Tool "${e}" not found in connection "${this.#n.connectionName}".`);return this.#f(i,r.baseUrl,isObject(t)?t:{},{abortSignal:n.abortSignal,callId:n.callId})}async close(){this.#e=void 0,this.#t=void 0}async#r(){if(this.#t!==void 0)return this.#t;if(this.#e!==void 0)return this.#e;this.#e=this.#i();try{return this.#t=await this.#e,this.#t}catch(e){throw this.#e=void 0,e}}async#i(){let e=await this.#o(),t=this.#a(e),n=this.#s(e),r=[],i=new Map,a=Object.keys(this.#n.toolCall?.providedArguments??{});for(let e of n){let t;try{t=parseJsonObject(omitProvidedArgumentsFromSchema(e.inputSchema,a))}catch(t){log.warn(`omitting OpenAPI operation with an invalid input schema`,{connectionName:this.#n.connectionName,error:t,toolName:e.toolName});continue}i.set(e.toolName,e),r.push({description:e.description,inputSchema:t,name:e.toolName})}return{metadata:r,operations:i,baseUrl:t}}#a(e){let t=this.#n.url,n=typeof t==`string`&&t.trim().length>0?t:extractServerUrl(e,this.#n.spec);if(n===void 0)throw Error(`OpenAPI connection "${this.#n.connectionName}" has no base URL: set "baseUrl" or ensure the document declares an absolute "servers" entry or Swagger "host".`);return assertSecureUrl(n,this.#n.connectionName,`base`),n}async#o(){let e=this.#n.spec;if(e===void 0)throw Error(`OpenAPI connection "${this.#n.connectionName}" is missing its "spec" source.`);if(typeof e!=`string`)return e;assertSecureUrl(e,this.#n.connectionName,`spec`);let t;try{t=await fetch(e,{headers:{accept:`application/json, application/yaml, text/yaml, */*`}})}catch(t){throw Error(`OpenAPI connection "${this.#n.connectionName}" failed to fetch its spec from "${e}": ${String(t)}`)}if(t.redirected&&assertSecureUrl(t.url,this.#n.connectionName,`spec`),!t.ok)throw Error(`OpenAPI connection "${this.#n.connectionName}" failed to fetch its spec from "${e}": HTTP ${t.status}.`);let n=await t.text(),r;try{r=parseSpecDocument(n)}catch(t){throw Error(`OpenAPI connection "${this.#n.connectionName}" spec at "${e}" could not be parsed as JSON or YAML: ${String(t)}`)}if(!isObject(r))throw Error(`OpenAPI connection "${this.#n.connectionName}" spec at "${e}" is not an OpenAPI document object.`);return r}#s(e){let t=e.paths;if(!isObject(t))return[];let n=[],r=new Set;for(let[i,a]of Object.entries(t)){if(!isObject(a))continue;let t=isArray(a.parameters)?a.parameters:[];for(let o of HTTP_METHODS){let s=a[o];if(!isObject(s))continue;let c=uniqueName(operationName(s,o,i),r),l=isArray(s.parameters)?s.parameters:[],u=[...t,...l],d=this.#c(e,u),f=this.#l(e,s.requestBody,u);n.push({toolName:c,method:o,pathTemplate:i,description:operationDescription(s),parameters:d,requestBody:f,inputSchema:buildInputSchema(d,f),security:resolveSecurity(e,s)})}}return n}#c(e,t){let n=[];for(let r of t){let t=isObject(r)?deref(e,r):r;if(!isObject(t))continue;let i=t.in;if(i!==`path`&&i!==`query`&&i!==`header`&&i!==`cookie`||typeof t.name!=`string`)continue;let a=this.#u(e,t);n.push({name:t.name,location:i,required:t.required===!0||i===`path`,schema:a,description:typeof t.description==`string`?t.description:void 0})}return n}#l(e,t,n=[]){if(isObject(t)){let n=deref(e,t);if(isObject(n)&&isObject(n.content)){let t=n.content,r=`application/json`in t?`application/json`:Object.keys(t)[0];if(r!==void 0){let i=t[r],a=isObject(i)&&isObject(i.schema)?derefSchema(e,i.schema):{};return{required:n.required===!0,contentType:r,schema:a}}}}return this.#d(e,n)}#u(e,t){if(isObject(t.schema))return derefSchema(e,t.schema);let n={};for(let e of SWAGGER_PARAMETER_SCHEMA_KEYS)t[e]!==void 0&&(n[e]=t[e]);return derefSchema(e,n)}#d(e,t){for(let n of t){let t=isObject(n)?deref(e,n):n;if(!isObject(t)||t.in!==`body`)continue;let r=isObject(t.schema)?derefSchema(e,t.schema):{};return{required:t.required===!0,contentType:`application/json`,schema:r}}}async#f(e,t,n,r){let i=await resolveProvidedArguments({args:n,callId:r.callId,connection:this.#n,toolName:e.toolName}),a=await resolveHeaders(this.#n),o=e.pathTemplate,s=new URLSearchParams,c=[];for(let t of e.parameters){let e=i[t.name];e!=null&&(t.location===`path`?o=o.replace(`{${t.name}}`,encodeURIComponent(String(e))):t.location===`query`?appendQuery(s,t.name,e):t.location===`cookie`?c.push(`${t.name}=${encodeURIComponent(String(e))}`):a[t.name]=String(e))}if(applySecurity(e.security,this.#n,a,s,c),c.length>0){let e=a.cookie??a.Cookie;delete a.Cookie,a.cookie=[e,...c].filter(e=>!!e).join(`; `)}let l=new URL(joinPath(t,o));l.search=s.toString();let u;e.requestBody!==void 0&&i.body!==void 0&&(u=JSON.stringify(i.body),a[`content-type`]=e.requestBody.contentType);let d=await fetch(l,{method:e.method.toUpperCase(),headers:a,body:u,signal:r?.abortSignal});return{status:d.status,statusText:d.statusText,body:await readResponseBody(d)}}};function appendQuery(e,t,n){if(isArray(n)){for(let r of n)e.append(t,String(r));return}e.append(t,String(n))}function joinPath(e,t){return`${e.endsWith(`/`)?e.slice(0,-1):e}${t.startsWith(`/`)?t:`/${t}`}`}function assertSecureUrl(e,t,n){let r;try{r=new URL(e)}catch{throw Error(`OpenAPI connection "${t}" has an invalid ${n} URL "${e}".`)}if(r.protocol!==`https:`&&!(r.protocol===`http:`&&isLoopbackHostname(r.hostname)))throw Error(`OpenAPI connection "${t}" must use https for its ${n} (got "${r.protocol}//${r.host}").`)}async function readResponseBody(e){let t=await e.text();if(t.length===0)return null;if((e.headers.get(`content-type`)??``).includes(`application/json`))try{return JSON.parse(t)}catch{return t}return t}export{OpenApiConnectionClient};
1
+ import{createLogger}from"#internal/logging.js";import{isObject}from"#shared/guards.js";import{isLoopbackHostname}from"#shared/network-address.js";import{parseJsonObject}from"#shared/json.js";import{resolveHeaders}from"#runtime/connections/mcp-client.js";import{omitProvidedArgumentsFromSchema,resolveProvidedArguments}from"#runtime/connections/provided-arguments.js";import{HTTP_METHODS,operationDescription,operationName,uniqueName}from"#runtime/connections/openapi-operations.js";import{buildInputSchema,deref,derefSchema,isArray}from"#runtime/connections/openapi-schema.js";import{applySecurity,resolveSecurity}from"#runtime/connections/openapi-security.js";import{extractServerUrl,parseSpecDocument}from"#runtime/connections/openapi-spec.js";const log=createLogger(`runtime.connections.openapi-client`),SWAGGER_PARAMETER_SCHEMA_KEYS=[`default`,`enum`,`exclusiveMaximum`,`exclusiveMinimum`,`format`,`items`,`maximum`,`maxItems`,`maxLength`,`minimum`,`minItems`,`minLength`,`multipleOf`,`pattern`,`type`,`uniqueItems`];var OpenApiConnectionClient=class{#e;#t;#n;constructor(e){this.#n=e}async connect(){return this.#r()}async getToolMetadata(){return(await this.#r()).metadata}async executeTool(e,t,n){let r=await this.#r(),i=r.operations.get(e);if(i===void 0)throw Error(`Tool "${e}" not found in connection "${this.#n.connectionName}".`);return this.#f(i,r.baseUrl,isObject(t)?t:{},{abortSignal:n.abortSignal,callId:n.callId})}async close(){this.#e=void 0,this.#t=void 0}async#r(){if(this.#t!==void 0)return this.#t;if(this.#e!==void 0)return this.#e;this.#e=this.#i();try{return this.#t=await this.#e,this.#t}catch(e){throw this.#e=void 0,e}}async#i(){let e=await this.#o(),t=this.#a(e),n=this.#s(e),r=[],i=new Map,a=Object.keys(this.#n.toolCall?.providedArguments??{});for(let e of n){let t;try{t=parseJsonObject(omitProvidedArgumentsFromSchema(e.inputSchema,a))}catch(t){log.warn(`omitting OpenAPI operation with an invalid input schema`,{connectionName:this.#n.connectionName,error:t,toolName:e.toolName});continue}i.set(e.toolName,e),r.push({description:e.description,inputSchema:t,name:e.toolName})}return{metadata:r,operations:i,baseUrl:t}}#a(e){let t=this.#n.url,n=typeof t==`string`&&t.trim().length>0?t:extractServerUrl(e,this.#n.spec);if(n===void 0)throw Error(`OpenAPI connection "${this.#n.connectionName}" has no base URL: set "baseUrl" or ensure the document declares an absolute "servers" entry or Swagger "host".`);return assertSecureUrl(n,this.#n.connectionName,`base`),n}async#o(){let e=this.#n.spec;if(e===void 0)throw Error(`OpenAPI connection "${this.#n.connectionName}" is missing its "spec" source.`);if(typeof e!=`string`)return e;assertSecureUrl(e,this.#n.connectionName,`spec`);let t;try{t=await fetch(e,{headers:{accept:`application/json, application/yaml, text/yaml, */*`}})}catch(t){throw Error(`OpenAPI connection "${this.#n.connectionName}" failed to fetch its spec from "${e}": ${String(t)}`)}if(t.redirected&&assertSecureUrl(t.url,this.#n.connectionName,`spec`),!t.ok)throw Error(`OpenAPI connection "${this.#n.connectionName}" failed to fetch its spec from "${e}": HTTP ${t.status}.`);let n=await t.text(),r;try{r=parseSpecDocument(n)}catch(t){throw Error(`OpenAPI connection "${this.#n.connectionName}" spec at "${e}" could not be parsed as JSON or YAML: ${String(t)}`)}if(!isObject(r))throw Error(`OpenAPI connection "${this.#n.connectionName}" spec at "${e}" is not an OpenAPI document object.`);return r}#s(e){let t=e.paths;if(!isObject(t))return[];let n=[],r=new Set;for(let[i,a]of Object.entries(t)){if(!isObject(a))continue;let t=isArray(a.parameters)?a.parameters:[];for(let o of HTTP_METHODS){let s=a[o];if(!isObject(s))continue;let c=uniqueName(operationName(s,o,i),r),l=isArray(s.parameters)?s.parameters:[],u=[...t,...l],d=this.#c(e,u),f=this.#l(e,s.requestBody,u);n.push({toolName:c,method:o,pathTemplate:i,description:operationDescription(s),parameters:d,requestBody:f,inputSchema:buildInputSchema(d,f),security:resolveSecurity(e,s)})}}return n}#c(e,t){let n=[];for(let r of t){let t=isObject(r)?deref(e,r):r;if(!isObject(t))continue;let i=t.in;if(i!==`path`&&i!==`query`&&i!==`header`&&i!==`cookie`||typeof t.name!=`string`)continue;let a=this.#u(e,t);n.push({name:t.name,location:i,required:t.required===!0||i===`path`,schema:a,description:typeof t.description==`string`?t.description:void 0})}return n}#l(e,t,n=[]){if(isObject(t)){let n=deref(e,t);if(isObject(n)&&isObject(n.content)){let t=n.content,r=`application/json`in t?`application/json`:Object.keys(t)[0];if(r!==void 0){let i=t[r],a=isObject(i)&&isObject(i.schema)?derefSchema(e,i.schema):{};return{required:n.required===!0,contentType:r,schema:a}}}}return this.#d(e,n)}#u(e,t){if(isObject(t.schema))return derefSchema(e,t.schema);let n={};for(let e of SWAGGER_PARAMETER_SCHEMA_KEYS)t[e]!==void 0&&(n[e]=t[e]);return derefSchema(e,n)}#d(e,t){for(let n of t){let t=isObject(n)?deref(e,n):n;if(!isObject(t)||t.in!==`body`)continue;let r=isObject(t.schema)?derefSchema(e,t.schema):{};return{required:t.required===!0,contentType:`application/json`,schema:r}}}async#f(e,t,n,r){let i=await resolveProvidedArguments({args:n,callId:r.callId,connection:this.#n,toolName:e.toolName}),a=await resolveHeaders(this.#n),o=e.pathTemplate,s=new URLSearchParams,c=[];for(let t of e.parameters){let n=i[t.name];if(n!=null){if(t.location===`path`){let r=String(n);if(r===`.`||r===`..`)throw Error(`Path parameter "${t.name}" for tool "${e.toolName}" in connection "${this.#n.connectionName}" must not be "." or "..".`);o=o.replace(`{${t.name}}`,encodeURIComponent(r))}else t.location===`query`?appendQuery(s,t.name,n):t.location===`cookie`?c.push(`${t.name}=${encodeURIComponent(String(n))}`):a[t.name]=String(n)}}if(applySecurity(e.security,this.#n,a,s,c),c.length>0){let e=a.cookie??a.Cookie;delete a.Cookie,a.cookie=[e,...c].filter(e=>!!e).join(`; `)}let l=new URL(joinPath(t,o));l.search=s.toString();let u;e.requestBody!==void 0&&i.body!==void 0&&(u=JSON.stringify(i.body),a[`content-type`]=e.requestBody.contentType);let d=await fetch(l,{method:e.method.toUpperCase(),headers:a,body:u,signal:r?.abortSignal});return{status:d.status,statusText:d.statusText,body:await readResponseBody(d)}}};function appendQuery(e,t,n){if(isArray(n)){for(let r of n)e.append(t,String(r));return}e.append(t,String(n))}function joinPath(e,t){return`${e.endsWith(`/`)?e.slice(0,-1):e}${t.startsWith(`/`)?t:`/${t}`}`}function assertSecureUrl(e,t,n){let r;try{r=new URL(e)}catch{throw Error(`OpenAPI connection "${t}" has an invalid ${n} URL "${e}".`)}if(r.protocol!==`https:`&&!(r.protocol===`http:`&&isLoopbackHostname(r.hostname)))throw Error(`OpenAPI connection "${t}" must use https for its ${n} (got "${r.protocol}//${r.host}").`)}async function readResponseBody(e){let t=await e.text();if(t.length===0)return null;if((e.headers.get(`content-type`)??``).includes(`application/json`))try{return JSON.parse(t)}catch{return t}return t}export{OpenApiConnectionClient};
@@ -1,7 +1,10 @@
1
1
  import type { Approval } from "#approval/definition.js";
2
2
  import type { ConnectionClient } from "#shared/connection-types.js";
3
3
  import type { ResolvedConnectionDefinition } from "#runtime/types.js";
4
- /** Per-session container mapping compiled connection names to live clients. */
4
+ /**
5
+ * Per-step container mapping compiled connection names to live clients. The
6
+ * step that creates it disposes it when the step ends.
7
+ */
5
8
  export interface ConnectionRegistry {
6
9
  dispose(): Promise<void>;
7
10
  getClient(connectionName: string): ConnectionClient;
@@ -3,8 +3,9 @@ import type { ResolvedConnectionDefinition } from "#runtime/types.js";
3
3
  import type { ConnectionClient } from "#shared/connection-types.js";
4
4
  import type { ConnectionRegistry } from "#runtime/connections/registry-types.js";
5
5
  /**
6
- * Per-session container mapping connection names to lazily-initialized
7
- * client wrappers.
6
+ * Per-step container mapping connection names to lazily-initialized
7
+ * client wrappers. `withContextScope` builds one per step, and the connection
8
+ * provider disposes it when the step ends.
8
9
  *
9
10
  * The registry is protocol-agnostic: it dispatches to the client
10
11
  * implementation matching each connection's `protocol` (MCP or OpenAPI).
@@ -1 +1 @@
1
- import{contextStorage,loadContext}from"#context/container.js";import{AuthKey}from"#context/keys.js";import{ConnectionAuthorizationFailedError,ConnectionAuthorizationRequiredError,isConnectionAuthorizationRequiredError}from"#connections/errors.js";import{consumeAuthorizationResult,createAuthorizationAttempt,requestAuthorization}from"#harness/authorization.js";import{supportsInteractiveAuthorization}from"#shared/connection-types.js";import{isAsyncIterable}from"#shared/async-iterable.js";import{principalKey,resolveConnectionPrincipal,resolveConnectionPrincipalFromAuth}from"#runtime/connections/principal.js";import{evictCachedToken,readCachedToken,writeCachedToken}from"#runtime/connections/authorization-tokens.js";const LOCAL_HTTP_VERCEL_CONNECT_HOSTNAMES=new Set([`127.0.0.1`,`[::1]`]);function createAuthorizationExecution(e={}){let t=new Set;async function complete(n){let r=n.instanceId??n.scope;!t.has(r)&&await(e.completeAuthorization??completeScopedAuthorization)(n)&&t.add(r)}function requireAuth(e,n){throw new ScopedAuthorizationRequiredError(e,t.has(e.instanceId??e.scope),n)}return{complete,isJustAuthorized(e){return t.has(e.instanceId??e.scope)},async getToken(e){await complete(e);try{return await resolveScopedToken(e)}catch(t){if(!isConnectionAuthorizationRequiredError(t))throw t;return requireAuth(e,t)}},async getResponderToken(e){try{return await resolveScopedToken(e)}catch(t){throw isConnectionAuthorizationRequiredError(t)?new ConnectionAuthorizationFailedError(e.scope,{message:`The approver of "${e.scope}" has no token for this provider, and an approved call doesn't start a sign-in.`,reason:`approver_authorization_required`,retryable:!1}):t}},requireAuth,async handleError(e,n){return n!==void 0&&isConnectionAuthorizationRequiredError(e)?await handleAuthorizationError(new ScopedAuthorizationRequiredError(n,t.has(n.instanceId??n.scope),e),{evictToken:!1}):await handleAuthorizationError(e)},run:executeWithAuthorization}}var ScopedAuthorizationRequiredError=class extends Error{scoped;justAuthorized;constructor(e,t,n){super(`Authorization required.`,{cause:n}),this.name=`ScopedAuthorizationRequiredError`,this.scoped=e,this.justAuthorized=t}};function isScopedAuthorizationRequiredError(e){return e instanceof Error&&e.name===`ScopedAuthorizationRequiredError`}async function handleAuthorizationError(e,t={evictToken:!0}){if(!isScopedAuthorizationRequiredError(e))throw e;let{scoped:n}=e;if(e.justAuthorized)throw new ConnectionAuthorizationFailedError(n.scope,{message:`Authorization for "${n.scope}" failed: the service rejected the token immediately after authorization.`,reason:`token_rejected_after_authorization`,retryable:!1});t.evictToken&&await evictScopedToken(n);let r=await startScopedAuthorization(n);if(r!==void 0)return r;throw supportsInteractiveAuthorization(n.authorization)?new ConnectionAuthorizationFailedError(n.scope,{message:`Authorization for "${n.scope}" requires sign-in, but no authorization callback URL could be minted for this run (missing session context).`,reason:`authorization_callback_unavailable`,retryable:!1}):e.cause??new ConnectionAuthorizationRequiredError(n.scope)}function executeWithAuthorization(e){try{let t=e();return isAsyncIterable(t)?handleIterable(t):Promise.resolve(t).catch(handleAuthorizationError)}catch(e){return handleAuthorizationError(e)}}async function*handleIterable(e){try{for await(let t of e)yield t}catch(e){yield await handleAuthorizationError(e)}}async function resolveScopedToken(e){let{scope:t,authorization:n,connection:r}=e,i=e.instanceId??t,a=contextStorage.getStore(),o=resolveScopedPrincipal(e,a);if(a===void 0)return await n.getToken({connection:r,principal:o});let s=principalKey(o),c=readCachedToken(a,i,s);if(c!==void 0)return c;let l=await n.getToken({connection:r,principal:o});return writeCachedToken(a,i,s,l),l}async function evictScopedToken(e){let{scope:t,authorization:n,connection:r}=e,i=e.instanceId??t,a=contextStorage.getStore();if(a===void 0)return;let o;try{o=resolveScopedPrincipal(e,a),evictCachedToken(a,i,principalKey(o))}catch{return}try{await n.evict?.({connection:r,principal:o})}catch{}}async function completeScopedAuthorization(e){let{scope:t,authorization:n,connection:r}=e;if(!supportsInteractiveAuthorization(n))return!1;let i=consumeAuthorizationResult(t,e.instanceId);if(i===void 0)return!1;let a=n,o=loadContext(),s=i.principal??resolveScopedPrincipal(e,o),c=await a.completeAuthorization({callbackUrl:i.hookUrl,connection:r,principal:s,resume:i.resume,callback:i.callback});return writeCachedToken(o,e.instanceId??t,principalKey(s),c),!0}async function startScopedAuthorization(e){let{scope:t,authorization:n,connection:r}=e;if(!supportsInteractiveAuthorization(n))return;let i=createAuthorizationAttempt(t);if(i===void 0)return;let a=n,o=resolveScopedPrincipal(e),s=e.boundResponder??contextStorage.getStore()?.get(AuthKey)??void 0,c=resolveAuthorizationCallbackUrl({authorization:n,callbackUrl:i.hookUrl}),{challenge:l,resume:u}=await a.startAuthorization({callbackUrl:c,connection:r,principal:o});return requestAuthorization([{attemptId:i.attemptId,challenge:stampChallengeDisplayName(l,n),grant:n.vercelConnect?.connector,hookUrl:c,instanceId:e.instanceId,name:t,principal:o,principalId:s?.principalId,requester:s,resume:u}])}function resolveScopedPrincipal(e,t){return e.boundResponder===void 0?resolveConnectionPrincipal(e.scope,e.authorization,t):resolveConnectionPrincipalFromAuth(e.scope,e.authorization,e.boundResponder,t)}function resolveAuthorizationCallbackUrl(e){if(e.authorization.vercelConnect===void 0)return e.callbackUrl;let t;try{t=new URL(e.callbackUrl)}catch{return e.callbackUrl}return t.protocol!==`http:`||!LOCAL_HTTP_VERCEL_CONNECT_HOSTNAMES.has(t.hostname)?e.callbackUrl:(t.hostname=`localhost`,t.toString())}function stampChallengeDisplayName(e,t){let n=t.displayName??e.displayName;return n===e.displayName?e:{...e,displayName:n}}export{completeScopedAuthorization,createAuthorizationExecution,evictScopedToken,handleAuthorizationError,resolveAuthorizationCallbackUrl,resolveScopedToken,stampChallengeDisplayName};
1
+ import{contextStorage,loadContext}from"#context/container.js";import{liveProjection}from"#harness/session-machine/current.js";import{AuthKey}from"#context/keys.js";import{ConnectionAuthorizationFailedError,ConnectionAuthorizationRequiredError,isConnectionAuthorizationRequiredError}from"#connections/errors.js";import{consumeAuthorizationResult,createAuthorizationAttempt,requestAuthorization}from"#harness/authorization.js";import{supportsInteractiveAuthorization}from"#shared/connection-types.js";import{isAsyncIterable}from"#shared/async-iterable.js";import{terminalSignInFailure}from"#harness/hitl/sign-ins.js";import{principalKey,resolveConnectionPrincipal,resolveConnectionPrincipalFromAuth}from"#runtime/connections/principal.js";import{evictCachedToken,readCachedToken,writeCachedToken}from"#runtime/connections/authorization-tokens.js";const LOCAL_HTTP_VERCEL_CONNECT_HOSTNAMES=new Set([`127.0.0.1`,`[::1]`]);function createAuthorizationExecution(e={}){let t=new Set;async function complete(n){let r=n.instanceId??n.scope;!t.has(r)&&await(e.completeAuthorization??completeScopedAuthorization)(n)&&t.add(r)}function requireAuth(e,n){throw new ScopedAuthorizationRequiredError(e,t.has(e.instanceId??e.scope),n)}return{complete,isJustAuthorized(e){return t.has(e.instanceId??e.scope)},async getToken(e){await complete(e);try{return await resolveScopedToken(e)}catch(t){if(!isConnectionAuthorizationRequiredError(t))throw t;return requireAuth(e,t)}},async getResponderToken(e){try{return await resolveScopedToken(e)}catch(t){throw isConnectionAuthorizationRequiredError(t)?new ConnectionAuthorizationFailedError(e.scope,{message:`The approver of "${e.scope}" has no token for this provider, and an approved call doesn't start a sign-in.`,reason:`approver_authorization_required`,retryable:!1}):t}},requireAuth,async handleError(e,n){return n!==void 0&&isConnectionAuthorizationRequiredError(e)?await handleAuthorizationError(new ScopedAuthorizationRequiredError(n,t.has(n.instanceId??n.scope),e),{evictToken:!1}):await handleAuthorizationError(e)},run:executeWithAuthorization}}var ScopedAuthorizationRequiredError=class extends Error{scoped;justAuthorized;constructor(e,t,n){super(`Authorization required.`,{cause:n}),this.name=`ScopedAuthorizationRequiredError`,this.scoped=e,this.justAuthorized=t}};function isScopedAuthorizationRequiredError(e){return e instanceof Error&&e.name===`ScopedAuthorizationRequiredError`}async function handleAuthorizationError(e,t={evictToken:!0}){if(!isScopedAuthorizationRequiredError(e))throw e;let{scoped:n}=e;if(e.justAuthorized)throw new ConnectionAuthorizationFailedError(n.scope,{message:`Authorization for "${n.scope}" failed: the service rejected the token immediately after authorization.`,reason:`token_rejected_after_authorization`,retryable:!1});let r=liveProjection(),i=r===void 0?void 0:terminalSignInFailure(r,{grant:n.authorization.vercelConnect?.connector,name:n.scope,principal:resolveScopedPrincipal(n)});if(i!==void 0)throw new ConnectionAuthorizationFailedError(n.scope,{message:`Authorization for "${n.scope}" already failed in this turn and can't be retried${i.reason===void 0?`.`:`: ${i.reason}`}`,...i.reason!==void 0&&{reason:i.reason},retryable:!1});t.evictToken&&await evictScopedToken(n);let a=await startScopedAuthorization(n);if(a!==void 0)return a;throw supportsInteractiveAuthorization(n.authorization)?new ConnectionAuthorizationFailedError(n.scope,{message:`Authorization for "${n.scope}" requires sign-in, but no authorization callback URL could be minted for this run (missing session context).`,reason:`authorization_callback_unavailable`,retryable:!1}):e.cause??new ConnectionAuthorizationRequiredError(n.scope)}function executeWithAuthorization(e){try{let t=e();return isAsyncIterable(t)?handleIterable(t):Promise.resolve(t).catch(handleAuthorizationError)}catch(e){return handleAuthorizationError(e)}}async function*handleIterable(e){try{for await(let t of e)yield t}catch(e){yield await handleAuthorizationError(e)}}async function resolveScopedToken(e){let{scope:t,authorization:n,connection:r}=e,i=e.instanceId??t,a=contextStorage.getStore(),o=resolveScopedPrincipal(e,a);if(a===void 0)return await n.getToken({connection:r,principal:o});let s=principalKey(o),c=readCachedToken(a,i,s);if(c!==void 0)return c;let l=await n.getToken({connection:r,principal:o});return writeCachedToken(a,i,s,l),l}async function evictScopedToken(e){let{scope:t,authorization:n,connection:r}=e,i=e.instanceId??t,a=contextStorage.getStore();if(a===void 0)return;let o;try{o=resolveScopedPrincipal(e,a),evictCachedToken(a,i,principalKey(o))}catch{return}try{await n.evict?.({connection:r,principal:o})}catch{}}async function completeScopedAuthorization(e){let{scope:t,authorization:n,connection:r}=e;if(!supportsInteractiveAuthorization(n))return!1;let i=consumeAuthorizationResult(t,e.instanceId);if(i===void 0)return!1;let a=n,o=loadContext(),s=i.principal??resolveScopedPrincipal(e,o),c=await a.completeAuthorization({callbackUrl:i.hookUrl,connection:r,principal:s,resume:i.resume,callback:i.callback});return writeCachedToken(o,e.instanceId??t,principalKey(s),c),!0}async function startScopedAuthorization(e){let{scope:t,authorization:n,connection:r}=e;if(!supportsInteractiveAuthorization(n))return;let i=createAuthorizationAttempt(t);if(i===void 0)return;let a=n,o=resolveScopedPrincipal(e),s=e.boundResponder??contextStorage.getStore()?.get(AuthKey)??void 0,c=resolveAuthorizationCallbackUrl({authorization:n,callbackUrl:i.hookUrl}),{challenge:l,resume:u}=await a.startAuthorization({callbackUrl:c,connection:r,principal:o});return requestAuthorization([{attemptId:i.attemptId,challenge:stampChallengeDisplayName(l,n),grant:n.vercelConnect?.connector,hookUrl:c,instanceId:e.instanceId,name:t,principal:o,principalId:s?.principalId,requester:s,resume:u}])}function resolveScopedPrincipal(e,t){return e.boundResponder===void 0?resolveConnectionPrincipal(e.scope,e.authorization,t):resolveConnectionPrincipalFromAuth(e.scope,e.authorization,e.boundResponder,t)}function resolveAuthorizationCallbackUrl(e){if(e.authorization.vercelConnect===void 0)return e.callbackUrl;let t;try{t=new URL(e.callbackUrl)}catch{return e.callbackUrl}return t.protocol!==`http:`||!LOCAL_HTTP_VERCEL_CONNECT_HOSTNAMES.has(t.hostname)?e.callbackUrl:(t.hostname=`localhost`,t.toString())}function stampChallengeDisplayName(e,t){let n=t.displayName??e.displayName;return n===e.displayName?e:{...e,displayName:n}}export{completeScopedAuthorization,createAuthorizationExecution,evictScopedToken,handleAuthorizationError,resolveAuthorizationCallbackUrl,resolveScopedToken,stampChallengeDisplayName};
@@ -1,4 +1,4 @@
1
- import{pinnedNodeEngineMajor}from"../../node-engine.js";import{parseChatGptModelSelection}from"../../../shared/chatgpt-model.js";import{SUPPORTED_AUTHORED_MODULE_FILE_EXTENSIONS}from"../update/module-files.js";import{pathExists,writeTextFile}from"../files.js";import{blockingCreateInPlaceEntries}from"../create-in-place.js";import{DEFAULT_CONNECT_PACKAGE_VERSION,resolveVersionToken}from"../version-tokens.js";import{applyPackageManagerWorkspaceConfiguration,isPackageManagerWorkspaceMember,patchWorkspaceRootPackageJson}from"../workspace-root.js";import{WEB_CHANNEL_TEMPLATES}from"./web-template.js";import{AGENT_INSTRUCTIONS_TEMPLATE}from"./instructions-template.js";import{SCAFFOLDED_AGENT_PATHS}from"./agent-paths.js";import{mkdir,readdir,stat}from"node:fs/promises";import{basename,join,resolve}from"node:path";const CURRENT_DIRECTORY_PROJECT_NAME=`.`,DEFAULT_AI_PACKAGE_VERSION=`^7.0.137`,DEFAULT_ZOD_PACKAGE_VERSION=`4.5.4`,DEFAULT_EVE_PACKAGE_CONTRACT={version:`0.80.0`,nodeEngine:`>=24`};function resolveEvePackageContract(e=DEFAULT_EVE_PACKAGE_CONTRACT){return{version:resolveVersionToken(`evePackage.version`,e.version),nodeEngine:resolveVersionToken(`evePackage.nodeEngine`,e.nodeEngine)}}function modelProviderSlug(e){let t=(e.split(`/`)[0]??``).replaceAll(/[^A-Za-z0-9._-]/gu,``);return t.length>0?t:`anthropic`}function byokProviderEnvVar(e){let t=modelProviderSlug(e).toUpperCase().replaceAll(/[^A-Z0-9]/gu,`_`);return`${/^[0-9]/.test(t)?`_`:``}${t}_API_KEY`}function agentTemplateFiles(e,t){return{[SCAFFOLDED_AGENT_PATHS.config]:renderAgentTemplate(e,t),[SCAFFOLDED_AGENT_PATHS.channel]:WEB_CHANNEL_TEMPLATES.default,[SCAFFOLDED_AGENT_PATHS.instructions]:AGENT_INSTRUCTIONS_TEMPLATE}}function renderAgentTemplate(e,t){let n=parseChatGptModelSelection(e);return n===void 0?BASE_AGENT_TEMPLATE.replaceAll(`__EVE_INIT_MODEL__`,e).replaceAll(`__EVE_INIT_REASONING__`,reasoningTemplateLine(t)):`import { defineAgent } from "eve";\nimport { chatgpt } from "eve/models/openai";\n\nexport default defineAgent({\n model: chatgpt(${JSON.stringify(n)}),\n${reasoningTemplateLine(t)}});\n`}function reasoningTemplateLine(e){return e===void 0||e===`provider-default`?``:` reasoning: "${e}",\n`}function renderTemplate(e,t){return e===BASE_AGENT_TEMPLATE&&parseChatGptModelSelection(t.model)!==void 0?renderAgentTemplate(t.model,t.reasoning):e.replaceAll(`__EVE_INIT_APP_NAME__`,t.appName).replaceAll(`__EVE_INIT_MODEL__`,t.model).replaceAll(`__EVE_INIT_REASONING__`,reasoningTemplateLine(t.reasoning)).replaceAll(`__EVE_INIT_BYOK_PROVIDER__`,modelProviderSlug(t.model)).replaceAll(`__EVE_INIT_BYOK_ENV_VAR__`,byokProviderEnvVar(t.model)).replaceAll(`__EVE_INIT_PACKAGE_VERSION__`,formatEveDependencySpecifier(t.eveVersion)).replaceAll(`__EVE_INIT_AI_SDK_VERSION__`,t.aiPackageVersion).replaceAll(`__EVE_INIT_CONNECT_VERSION__`,t.connectPackageVersion).replaceAll(`__EVE_INIT_ZOD_VERSION__`,t.zodPackageVersion).replaceAll(`__EVE_INIT_TYPESCRIPT_VERSION__`,t.typescriptPackageVersion).replaceAll(`__EVE_INIT_TYPES_NODE_VERSION__`,t.nodeTypesVersion).replaceAll(`__EVE_INIT_NODE_ENGINE__`,t.nodeEngine)}function formatEveDependencySpecifier(e){return/^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z-.]+)?$/.test(e)?`^${e}`:e}const BASE_AGENT_TEMPLATE=`import { defineAgent } from "eve";
1
+ import{pinnedNodeEngineMajor}from"../../node-engine.js";import{parseChatGptModelSelection}from"../../../shared/chatgpt-model.js";import{SUPPORTED_AUTHORED_MODULE_FILE_EXTENSIONS}from"../update/module-files.js";import{pathExists,writeTextFile}from"../files.js";import{blockingCreateInPlaceEntries}from"../create-in-place.js";import{DEFAULT_CONNECT_PACKAGE_VERSION,resolveVersionToken}from"../version-tokens.js";import{applyPackageManagerWorkspaceConfiguration,isPackageManagerWorkspaceMember,patchWorkspaceRootPackageJson}from"../workspace-root.js";import{WEB_CHANNEL_TEMPLATES}from"./web-template.js";import{AGENT_INSTRUCTIONS_TEMPLATE}from"./instructions-template.js";import{SCAFFOLDED_AGENT_PATHS}from"./agent-paths.js";import{mkdir,readdir,stat}from"node:fs/promises";import{basename,join,resolve}from"node:path";const CURRENT_DIRECTORY_PROJECT_NAME=`.`,DEFAULT_AI_PACKAGE_VERSION=`^7.0.137`,DEFAULT_ZOD_PACKAGE_VERSION=`4.5.4`,DEFAULT_EVE_PACKAGE_CONTRACT={version:`0.81.0`,nodeEngine:`>=24`};function resolveEvePackageContract(e=DEFAULT_EVE_PACKAGE_CONTRACT){return{version:resolveVersionToken(`evePackage.version`,e.version),nodeEngine:resolveVersionToken(`evePackage.nodeEngine`,e.nodeEngine)}}function modelProviderSlug(e){let t=(e.split(`/`)[0]??``).replaceAll(/[^A-Za-z0-9._-]/gu,``);return t.length>0?t:`anthropic`}function byokProviderEnvVar(e){let t=modelProviderSlug(e).toUpperCase().replaceAll(/[^A-Z0-9]/gu,`_`);return`${/^[0-9]/.test(t)?`_`:``}${t}_API_KEY`}function agentTemplateFiles(e,t){return{[SCAFFOLDED_AGENT_PATHS.config]:renderAgentTemplate(e,t),[SCAFFOLDED_AGENT_PATHS.channel]:WEB_CHANNEL_TEMPLATES.default,[SCAFFOLDED_AGENT_PATHS.instructions]:AGENT_INSTRUCTIONS_TEMPLATE}}function renderAgentTemplate(e,t){let n=parseChatGptModelSelection(e);return n===void 0?BASE_AGENT_TEMPLATE.replaceAll(`__EVE_INIT_MODEL__`,e).replaceAll(`__EVE_INIT_REASONING__`,reasoningTemplateLine(t)):`import { defineAgent } from "eve";\nimport { chatgpt } from "eve/models/openai";\n\nexport default defineAgent({\n model: chatgpt(${JSON.stringify(n)}),\n${reasoningTemplateLine(t)}});\n`}function reasoningTemplateLine(e){return e===void 0||e===`provider-default`?``:` reasoning: "${e}",\n`}function renderTemplate(e,t){return e===BASE_AGENT_TEMPLATE&&parseChatGptModelSelection(t.model)!==void 0?renderAgentTemplate(t.model,t.reasoning):e.replaceAll(`__EVE_INIT_APP_NAME__`,t.appName).replaceAll(`__EVE_INIT_MODEL__`,t.model).replaceAll(`__EVE_INIT_REASONING__`,reasoningTemplateLine(t.reasoning)).replaceAll(`__EVE_INIT_BYOK_PROVIDER__`,modelProviderSlug(t.model)).replaceAll(`__EVE_INIT_BYOK_ENV_VAR__`,byokProviderEnvVar(t.model)).replaceAll(`__EVE_INIT_PACKAGE_VERSION__`,formatEveDependencySpecifier(t.eveVersion)).replaceAll(`__EVE_INIT_AI_SDK_VERSION__`,t.aiPackageVersion).replaceAll(`__EVE_INIT_CONNECT_VERSION__`,t.connectPackageVersion).replaceAll(`__EVE_INIT_ZOD_VERSION__`,t.zodPackageVersion).replaceAll(`__EVE_INIT_TYPESCRIPT_VERSION__`,t.typescriptPackageVersion).replaceAll(`__EVE_INIT_TYPES_NODE_VERSION__`,t.nodeTypesVersion).replaceAll(`__EVE_INIT_NODE_ENGINE__`,t.nodeEngine)}function formatEveDependencySpecifier(e){return/^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z-.]+)?$/.test(e)?`^${e}`:e}const BASE_AGENT_TEMPLATE=`import { defineAgent } from "eve";
2
2
 
3
3
  export default defineAgent({
4
4
  model: "__EVE_INIT_MODEL__",
@@ -1,4 +1,4 @@
1
- import { a as conversationProjection, i as openConversationInputs, n as conversationReducer, o as callStatus, r as defaultMessageReducer, t as useEveAgent } from "../chunks/use-eve-agent-Ch-Q-s12.js";
1
+ import { a as conversationProjection, i as openConversationInputs, n as conversationReducer, o as callStatus, r as defaultMessageReducer, t as useEveAgent } from "../chunks/use-eve-agent-DLkjJIm3.js";
2
2
 
3
3
  //#region src/client/tool-call-state.ts
4
4
  function toolCallState(conversation, callId, options = {}) {
@@ -1,3 +1,3 @@
1
- import { t as useEveAgent } from "../chunks/use-eve-agent-Ch-Q-s12.js";
1
+ import { t as useEveAgent } from "../chunks/use-eve-agent-DLkjJIm3.js";
2
2
 
3
3
  export { useEveAgent };
@@ -1 +1 @@
1
- async function executeAskQuestionTool(e,t){"use workflow";return toAskQuestionOutput(await t.ask(toAskQuestionRequest(e)))}function toAskQuestionRequest(e){let t=e.options?.map(e=>({description:e.description,id:e.label,label:e.label}));return{allowFreeform:!0,display:t===void 0?`text`:`select`,prompt:e.question,...t!==void 0&&{options:t}}}function toAskQuestionOutput(e){switch(e.status){case`answered`:return{answer:e.optionId??e.text??``,status:`answered`};case`cancelled`:return{interrupted:!0};case`unavailable`:return{status:`unavailable`}}}executeAskQuestionTool.workflowId=`workflow//eve@0.80.0//executeAskQuestionTool`;export{executeAskQuestionTool,toAskQuestionOutput,toAskQuestionRequest};
1
+ async function executeAskQuestionTool(e,t){"use workflow";return toAskQuestionOutput(await t.ask(toAskQuestionRequest(e)))}function toAskQuestionRequest(e){let t=e.options?.map(e=>({description:e.description,id:e.label,label:e.label}));return{allowFreeform:!0,display:t===void 0?`text`:`select`,prompt:e.question,...t!==void 0&&{options:t}}}function toAskQuestionOutput(e){switch(e.status){case`answered`:return{answer:e.optionId??e.text??``,status:`answered`};case`cancelled`:return{interrupted:!0};case`unavailable`:return{status:`unavailable`}}}executeAskQuestionTool.workflowId=`workflow//eve@0.81.0//executeAskQuestionTool`;export{executeAskQuestionTool,toAskQuestionOutput,toAskQuestionRequest};
@@ -1 +1 @@
1
- import{sleep}from"#compiled/@workflow/core/index.js";async function executeSleepTool(e,t){"use workflow";if(t.abortSignal.aborted)return{interrupted:!0};let n=new Promise(e=>t.abortSignal.addEventListener(`abort`,()=>e(`interrupted`),{once:!0})),r=sleep(Math.ceil(e.seconds*1e3)).then(()=>`elapsed`);return await Promise.race([r,n])===`elapsed`?{waitedSeconds:e.seconds}:{interrupted:!0}}executeSleepTool.workflowId=`workflow//eve@0.80.0//executeSleepTool`;export{executeSleepTool};
1
+ import{sleep}from"#compiled/@workflow/core/index.js";async function executeSleepTool(e,t){"use workflow";if(t.abortSignal.aborted)return{interrupted:!0};let n=new Promise(e=>t.abortSignal.addEventListener(`abort`,()=>e(`interrupted`),{once:!0})),r=sleep(Math.ceil(e.seconds*1e3)).then(()=>`elapsed`);return await Promise.race([r,n])===`elapsed`?{waitedSeconds:e.seconds}:{interrupted:!0}}executeSleepTool.workflowId=`workflow//eve@0.81.0//executeSleepTool`;export{executeSleepTool};
@@ -1,8 +1,8 @@
1
1
  import type { InstrumentationProviderDefinition } from "#instrumentation/lifecycle.js";
2
2
  import type { AgentActionTraceState } from "#tracing/eve/agent-trace-state.js";
3
- import type { AgentTracing } from "#compiled/@eve/tracing/index.js";
3
+ import type { AgentRun } from "#compiled/@vercel/agent-runs/index.js";
4
4
  /** Approval spans live under their tool call; hook state keeps only the locator. */
5
5
  export declare function createAgentApprovalInstrumentation(input: {
6
- readonly tracing: AgentTracing;
6
+ readonly tracing: AgentRun;
7
7
  readonly actionStateFor: (sessionId: string, turnId: string, callId: string) => Promise<AgentActionTraceState | undefined>;
8
8
  }): Pick<NonNullable<InstrumentationProviderDefinition["events"]>, "input.requested" | "input.resolved">;
@@ -1 +1 @@
1
- import{contextStorage}from"#context/container.js";import{ActiveChannelDeliveriesKey}from"#context/keys.js";import{isSampledTrace}from"#shared/trace-policy.js";import{contentAttribute}from"#compiled/@eve/tracing/otel.js";function createAgentChannelDeliveryInstrumentation(e){let onStarted=async(t,n)=>{let r=await e.stateStore.get(`session`,t.sessionId),i=(t.turnId===void 0||t.sequence===void 0?void 0:await e.stateStore.get(`turn`,JSON.stringify([t.sessionId,t.turnId])))?.context??r?.context;if(i===void 0||!isSampledTrace(i))return;let a=e.recordInputs?contentAttribute(t.input):void 0,o={};a!==void 0&&(o.inputAttribute=a),t.delivery.requestTraceContext!==void 0&&(o.requestTraceContext={spanId:t.delivery.requestTraceContext.spanId,traceFlags:t.delivery.requestTraceContext.traceFlags,traceId:t.delivery.requestTraceContext.traceId}),n.state.set(o)},onTerminal=async(t,n)=>{let r=readState(n.state.get());if(r===void 0||t.turnId===void 0)return;let i=await e.stateStore.get(`turn`,JSON.stringify([t.sessionId,t.turnId]));i!==void 0&&isSampledTrace(i.context)&&isOnlyActiveDelivery(t.sessionId,t.turnId,t.delivery.deliveryId)&&await e.stateStore.update(`turn`,JSON.stringify([t.sessionId,t.turnId]),e=>({...e,channelDelivery:{channelKind:t.delivery.channelKind,channelName:t.delivery.channelName,deliveryId:t.delivery.deliveryId,...r.inputAttribute===void 0?void 0:{inputAttribute:r.inputAttribute},...t.delivery.requestId===void 0?void 0:{requestId:t.delivery.requestId},...r.requestTraceContext===void 0?void 0:{requestTraceContext:r.requestTraceContext}}}))};return{"channel.delivery.cancelled":onTerminal,"channel.delivery.completed":onTerminal,"channel.delivery.failed":onTerminal,"channel.delivery.started":onStarted}}function isOnlyActiveDelivery(e,t,n){let r=contextStorage.getStore()?.get(ActiveChannelDeliveriesKey),i=r?.[0];return r?.length===1&&i?.sessionId===e&&i.turnId===t&&i.delivery.deliveryId===n}function readState(e){if(!isRecord(e))return;let t=isSpanContext(e.requestTraceContext)?e.requestTraceContext:void 0;return{inputAttribute:typeof e.inputAttribute==`string`?e.inputAttribute:void 0,requestTraceContext:t}}function isSpanContext(e){return isRecord(e)&&typeof e.spanId==`string`&&typeof e.traceFlags==`number`&&typeof e.traceId==`string`}function isRecord(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}export{createAgentChannelDeliveryInstrumentation};
1
+ import{contextStorage}from"#context/container.js";import{ActiveChannelDeliveriesKey}from"#context/keys.js";import{isSampledTrace}from"#shared/trace-policy.js";import{contentAttribute}from"#compiled/@vercel/agent-runs/otel.js";function createAgentChannelDeliveryInstrumentation(e){let onStarted=async(t,n)=>{let r=await e.stateStore.get(`session`,t.sessionId),i=(t.turnId===void 0||t.sequence===void 0?void 0:await e.stateStore.get(`turn`,JSON.stringify([t.sessionId,t.turnId])))?.context??r?.context;if(i===void 0||!isSampledTrace(i))return;let a=e.recordInputs?contentAttribute(t.input):void 0,o={};a!==void 0&&(o.inputAttribute=a),t.delivery.requestTraceContext!==void 0&&(o.requestTraceContext={spanId:t.delivery.requestTraceContext.spanId,traceFlags:t.delivery.requestTraceContext.traceFlags,traceId:t.delivery.requestTraceContext.traceId}),n.state.set(o)},onTerminal=async(t,n)=>{let r=readState(n.state.get());if(r===void 0||t.turnId===void 0)return;let i=await e.stateStore.get(`turn`,JSON.stringify([t.sessionId,t.turnId]));i!==void 0&&isSampledTrace(i.context)&&isOnlyActiveDelivery(t.sessionId,t.turnId,t.delivery.deliveryId)&&await e.stateStore.update(`turn`,JSON.stringify([t.sessionId,t.turnId]),e=>({...e,channelDelivery:{channelKind:t.delivery.channelKind,channelName:t.delivery.channelName,deliveryId:t.delivery.deliveryId,...r.inputAttribute===void 0?void 0:{inputAttribute:r.inputAttribute},...t.delivery.requestId===void 0?void 0:{requestId:t.delivery.requestId},...r.requestTraceContext===void 0?void 0:{requestTraceContext:r.requestTraceContext}}}))};return{"channel.delivery.cancelled":onTerminal,"channel.delivery.completed":onTerminal,"channel.delivery.failed":onTerminal,"channel.delivery.started":onStarted}}function isOnlyActiveDelivery(e,t,n){let r=contextStorage.getStore()?.get(ActiveChannelDeliveriesKey),i=r?.[0];return r?.length===1&&i?.sessionId===e&&i.turnId===t&&i.delivery.deliveryId===n}function readState(e){if(!isRecord(e))return;let t=isSpanContext(e.requestTraceContext)?e.requestTraceContext:void 0;return{inputAttribute:typeof e.inputAttribute==`string`?e.inputAttribute:void 0,requestTraceContext:t}}function isSpanContext(e){return isRecord(e)&&typeof e.spanId==`string`&&typeof e.traceFlags==`number`&&typeof e.traceId==`string`}function isRecord(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}export{createAgentChannelDeliveryInstrumentation};
@@ -1,9 +1,9 @@
1
1
  import type { InstrumentationMemoryExecutionOperation } from "#instrumentation/memory.js";
2
2
  import type { ConversationEnvironment } from "#shared/conversation-context.js";
3
3
  import type { AgentTraceStateStore } from "#tracing/eve/agent-trace-state.js";
4
- import { type AgentTracing } from "#compiled/@eve/tracing/index.js";
4
+ import { type AgentRun } from "#compiled/@vercel/agent-runs/index.js";
5
5
  export declare function createAgentMemoryInstrumentation(input: {
6
- tracing: AgentTracing;
6
+ tracing: AgentRun;
7
7
  environment: ConversationEnvironment;
8
8
  recordOutputs?: boolean;
9
9
  stateStore: AgentTraceStateStore;
@@ -1 +1 @@
1
- import{normalizeChannelAudience}from"#shared/channel-audience.js";import{applyLiveDeliveryAudienceCeiling,resolveForwardedTraceSeed}from"#shared/forwarded-trace-policy.js";import{contextStorage}from"#context/container.js";import{SessionTraceSeedKey}from"#context/keys.js";import{ROOT_CONTEXT,context,trace}from"#compiled/@opentelemetry/api/index.js";import{activeTraceOperation}from"#compiled/@eve/tracing/otel.js";import"#compiled/@eve/tracing/index.js";import{withChannelAudience}from"#tracing/eve/channel-audience-context.js";import{eveTurnIdentity}from"#tracing/eve/operation-input.js";function createAgentMemoryInstrumentation(e){return{async runInContext(t,n){let r=await e.stateStore.get(`session`,t.sessionId),i=t.turnId===void 0?void 0:await e.stateStore.get(`turn`,JSON.stringify([t.sessionId,t.turnId])),a=activeTraceOperation(),o=a?.reference??i?.context??r?.context;if(o===void 0)return await n();let s=a===void 0?withChannelAudience(trace.setSpan(ROOT_CONTEXT,trace.wrapSpanContext(o)),r?.channelAudience):context.active(),c=resolveForwardedTraceSeed(contextStorage.getStore()?.get(SessionTraceSeedKey)),l=c?.decision??r?.decision,u=l===void 0?void 0:applyLiveDeliveryAudienceCeiling(l,normalizeChannelAudience(r?.channelAudience),c?.forwardedTracePolicy,e.environment),d={emit:!!(o.traceFlags&1),recordInputs:u?.action===`record`&&u.recordInputs,recordOutputs:e.recordOutputs===!0&&u?.action===`record`&&u.recordOutputs},f={identity:eveTurnIdentity({...t,turnId:t.turnId??``}),parent:o,context:s,capture:d,phase:t.phase,slot:t.slot,storeId:t.storeId,describe(e){let t=e;return{recordCount:t.recordCount,records:t.outputRecords}}},p=e.tracing.memory;return t.operationName===`search_memory`?await p.search(f,n):await p.write(f,n)}}}export{createAgentMemoryInstrumentation};
1
+ import{normalizeChannelAudience}from"#shared/channel-audience.js";import{applyLiveDeliveryAudienceCeiling,resolveForwardedTraceSeed}from"#shared/forwarded-trace-policy.js";import{contextStorage}from"#context/container.js";import{SessionTraceSeedKey}from"#context/keys.js";import{ROOT_CONTEXT,context,trace}from"#compiled/@opentelemetry/api/index.js";import{activeTraceOperation}from"#compiled/@vercel/agent-runs/otel.js";import"#compiled/@vercel/agent-runs/index.js";import{withChannelAudience}from"#tracing/eve/channel-audience-context.js";import{eveTurnIdentity}from"#tracing/eve/operation-input.js";function createAgentMemoryInstrumentation(e){return{async runInContext(t,n){let r=await e.stateStore.get(`session`,t.sessionId),i=t.turnId===void 0?void 0:await e.stateStore.get(`turn`,JSON.stringify([t.sessionId,t.turnId])),a=activeTraceOperation(),o=a?.reference??i?.context??r?.context;if(o===void 0)return await n();let s=a===void 0?withChannelAudience(trace.setSpan(ROOT_CONTEXT,trace.wrapSpanContext(o)),r?.channelAudience):context.active(),c=resolveForwardedTraceSeed(contextStorage.getStore()?.get(SessionTraceSeedKey)),l=c?.decision??r?.decision,u=l===void 0?void 0:applyLiveDeliveryAudienceCeiling(l,normalizeChannelAudience(r?.channelAudience),c?.forwardedTracePolicy,e.environment),d={emit:!!(o.traceFlags&1),recordInputs:u?.action===`record`&&u.recordInputs,recordOutputs:e.recordOutputs===!0&&u?.action===`record`&&u.recordOutputs},f={identity:eveTurnIdentity({...t,turnId:t.turnId??``}),parent:o,context:s,capture:d,phase:t.phase,slot:t.slot,storeId:t.storeId,describe(e){let t=e;return{recordCount:t.recordCount,records:t.outputRecords}}},p=e.tracing.memory;return t.operationName===`search_memory`?await p.search(f,n):await p.write(f,n)}}}export{createAgentMemoryInstrumentation};
@@ -2,7 +2,7 @@ import type { AgentTraceStateStore } from "#tracing/eve/agent-trace-state.js";
2
2
  import type { TraceCapturePolicy } from "#tracing/eve/otel-declaration.js";
3
3
  import type { InstrumentationContextRunner, InstrumentationProviderDefinition, InstrumentationSessionStartedEvent, InstrumentationTraceSeed, InstrumentationTurnStartedEvent } from "#instrumentation/lifecycle.js";
4
4
  import type { ConversationEnvironment } from "#shared/conversation-context.js";
5
- import type { AgentSpanIdGenerator, AgentTelemetry } from "#compiled/@eve/tracing/index.js";
5
+ import type { AgentSpanIdGenerator, AgentTelemetry } from "#compiled/@vercel/agent-runs/index.js";
6
6
  export interface AgentOtelInstrumentationInput {
7
7
  /** Span output for eve's agent spans; its `ids` make turns durable across workers. */
8
8
  readonly telemetry: AgentTelemetry;
@@ -1,7 +1,7 @@
1
1
  import { type Context, type SpanContext } from "#compiled/@opentelemetry/api/index.js";
2
2
  import type { InstrumentationAttemptScope, InstrumentationExecutionOperation, InstrumentationToolCallStartedEvent, InstrumentationToolCallTerminalEvent } from "#instrumentation/lifecycle.js";
3
3
  import type { AgentActionTraceState, AgentTraceStateStore } from "#tracing/eve/agent-trace-state.js";
4
- import type { AgentTracing, AttemptOperation, CaptureDecision, ToolOperation } from "#compiled/@eve/tracing/index.js";
4
+ import type { AgentRun, AttemptOperation, CaptureDecision, ToolOperation } from "#compiled/@vercel/agent-runs/index.js";
5
5
  export interface AgentToolContext {
6
6
  readonly context: Context;
7
7
  readonly spanContext: SpanContext;
@@ -10,7 +10,7 @@ type ToolExecution = Extract<InstrumentationExecutionOperation, {
10
10
  type: "tool.call";
11
11
  }>;
12
12
  /** Finds an open tool call in its turn's trace tree, in this or a later process. */
13
- export declare function resumeTool(tracing: AgentTracing, state: AgentActionTraceState): Promise<ToolOperation | undefined>;
13
+ export declare function resumeTool(tracing: AgentRun, state: AgentActionTraceState): Promise<ToolOperation | undefined>;
14
14
  /**
15
15
  * One `execute_tool` span per call. eve's tool loop reports the durable
16
16
  * dispatch through `tool.call.*` events; the SDK reports the run through the
@@ -18,7 +18,7 @@ export declare function resumeTool(tracing: AgentTracing, state: AgentActionTrac
18
18
  * without a dispatch closes under its step when the step ends.
19
19
  */
20
20
  export declare function createAgentToolInstrumentation(input: {
21
- readonly tracing: AgentTracing;
21
+ readonly tracing: AgentRun;
22
22
  readonly attemptFor: (scope: InstrumentationAttemptScope) => Promise<AttemptOperation | undefined>;
23
23
  readonly stepFor: (scope: InstrumentationAttemptScope) => AttemptOperation | undefined;
24
24
  readonly recordInputs: boolean;
@@ -1 +1 @@
1
- import{createContextKey}from"#compiled/@opentelemetry/api/index.js";import{activeTraceOperation}from"#compiled/@eve/tracing/otel.js";const AGENT_TRACE_KEY=createContextKey(`eve.agent.trace`);function isAgentTraceContext(e){if(typeof e!=`object`||!e)return!1;if(activeTraceOperation(e)!==void 0)return!0;let t=Reflect.get(e,`getValue`);return typeof t==`function`&&Reflect.apply(t,e,[AGENT_TRACE_KEY])===!0}function markAgentTraceContext(e){return e.setValue(AGENT_TRACE_KEY,!0)}export{isAgentTraceContext,markAgentTraceContext};
1
+ import{createContextKey}from"#compiled/@opentelemetry/api/index.js";import{activeTraceOperation}from"#compiled/@vercel/agent-runs/otel.js";const AGENT_TRACE_KEY=createContextKey(`eve.agent.trace`);function isAgentTraceContext(e){if(typeof e!=`object`||!e)return!1;if(activeTraceOperation(e)!==void 0)return!0;let t=Reflect.get(e,`getValue`);return typeof t==`function`&&Reflect.apply(t,e,[AGENT_TRACE_KEY])===!0}function markAgentTraceContext(e){return e.setValue(AGENT_TRACE_KEY,!0)}export{isAgentTraceContext,markAgentTraceContext};
@@ -2,7 +2,7 @@ import type { SpanContext } from "#compiled/@opentelemetry/api/index.js";
2
2
  import type { InstrumentationParentLineage, InstrumentationPrincipalSummary } from "#instrumentation/lifecycle.js";
3
3
  import type { ChannelAudience } from "#shared/channel-audience.js";
4
4
  import type { InstrumentationDecision } from "#shared/instrumentation-decision.js";
5
- import type { TraceSnapshot } from "#compiled/@eve/tracing/index.js";
5
+ import type { TraceSnapshot } from "#compiled/@vercel/agent-runs/index.js";
6
6
  export interface AgentSessionTraceState {
7
7
  readonly traceSessionId: string;
8
8
  readonly channelAudience?: ChannelAudience;
@@ -1 +1 @@
1
- import{createLogger,logError}from"#internal/logging.js";import{contextStorage}from"#context/container.js";import{SessionIdKey}from"#context/keys.js";import{BundleKey}from"#runtime/sessions/runtime-context-keys.js";import{formatTraceparent}from"#protocol/traceparent.js";import{ContextAgentTraceStateStore}from"#tracing/eve/agent-trace-context-store.js";import{resolveTracePolicy}from"#shared/trace-policy.js";import{ROOT_CONTEXT,context,trace}from"#compiled/@opentelemetry/api/index.js";import{markAgentTraceContext}from"#tracing/eve/agent-trace-context.js";import{activeTraceOperation,truncateTelemetryText,withErrorContent}from"#compiled/@eve/tracing/otel.js";import{otelTelemetry}from"#compiled/@eve/tracing/index.js";import{readInstrumentationSessionContext}from"#instrumentation/session-context.js";import{getInstrumentationRuntime}from"#instrumentation/runtime-global.js";import{withChannelAudience}from"#tracing/eve/channel-audience-context.js";import{eveOutputMapping}from"#tracing/eve/profile.js";const log=createLogger(`connection.events`);function connectionEventTraceContext(e){if(typeof e!=`object`||!e)return;let{traceId:t,spanId:n,traceFlags:r}=e;if(typeof t!=`string`||typeof n!=`string`||r!==0&&r!==1)return;let i={traceId:t,spanId:n,traceFlags:r};return formatTraceparent(i)===void 0?void 0:i}function connectionEventAttributes(e){let t={};for(let[n,r]of Object.entries({"agent.connection.name":e.connectionName,"agent.run.id":e.sessionId,"connect.subscription.id":e.subscriptionId,"connect.delivery.id":e.deliveryId,"eve.connection.event.binding.id":e.bindingId}))r!==void 0&&(t[n]=truncateTelemetryText(r,256));return t}function connectionEventError(e){let t=Error(`Connection event operation failed`);if(e instanceof Error&&[`Error`,`TypeError`,`RangeError`,`SyntaxError`,`AbortError`,`TimeoutError`,`MCPClientError`].includes(e.name)&&(t.name=e.name),typeof e!=`object`||!e)return t;let n=e,r=n.code,i=n.statusCode??n.status,a=typeof r==`number`&&Number.isFinite(r)||typeof r==`string`&&[`invalid_delivery`,`verification_unavailable`,`configuration_error`,`ETIMEDOUT`,`ECONNRESET`,`ECONNREFUSED`,`ENOTFOUND`,`EAI_AGAIN`].includes(r)?r:void 0;return a!==void 0&&Object.assign(t,{code:a}),typeof i==`number`&&Number.isInteger(i)&&i>=100&&i<=599&&Object.assign(t,{statusCode:i}),t}async function withConnectionEventSpan(e,t){return contextStorage.run(e.ctx,async()=>{let n=getInstrumentationRuntime(),r=otelTelemetry({tracerName:`eve.connection.events`,mapping:eveOutputMapping()}),i=n?.otelSettings,a=e.ctx.require(SessionIdKey),o=connectionEventAttributes({...e,sessionId:a}),run=async n=>{try{return await t(n)}catch(t){throw logError(log,`connection event operation failed`,connectionEventError(t),{...o,operation:e.operation}),t}};if(i===void 0)return r.suppressed(()=>run());let s=new ContextAgentTraceStateStore().get(`session`,a),c=readInstrumentationSessionContext(e.ctx),l=c.traceSeed?.decision??s?.decision??resolveTracePolicy(i.tracePolicy,{...c.conversation,agentName:e.ctx.require(BundleKey).resolvedAgent.config?.name??`eve`}),u=activeTraceOperation(),d=connectionEventTraceContext(e.requestTraceContext)??u?.reference??s?.context;if(l.action===`drop`||u?.capture.emit===!1||c.traceSeed!==void 0&&!(c.traceSeed.traceFlags&1)||s!==void 0&&!(s.context.traceFlags&1)||d!==void 0&&!(d.traceFlags&1))return r.suppressed(()=>run());let f=d===void 0?context.active():trace.setSpan(ROOT_CONTEXT,trace.wrapSpanContext(d)),p=markAgentTraceContext(withErrorContent(withChannelAudience(f,c.audience),!1)),m=`agent.connection.event.${e.operation}`,h=r.startSpan({type:`step`,operationId:m,name:m,kind:e.operation.startsWith(`on`)?`CONSUMER`:`INTERNAL`,attributes:{...o,"operation.name":m,"resource.name":m}},{context:p});try{let t=await r.run({type:`step`,reference:h.reference,capture:{emit:!0,recordInputs:!1,recordOutputs:!1}},()=>run(connectionEventTraceContext(h.reference)),p);if([`subscribe`,`get`,`unsubscribe`].includes(e.operation)&&typeof t==`object`&&t){let e=t;typeof e.id==`string`&&h.setAttribute(`connect.subscription.id`,truncateTelemetryText(e.id,256)),typeof e.status==`string`&&[`pending`,`active`,`needs_auth`,`stopped`,`expired`,`failed`].includes(e.status)&&h.setAttribute(`connect.subscription.status`,e.status)}return h.setAttribute(`eve.connection.event.outcome`,`completed`),h.setStatus(`OK`),t}catch(e){throw h.setAttribute(`eve.connection.event.outcome`,`failed`),h.fail(void 0,`connection_event_error`),e}finally{h.end(),await n.forceFlush().catch(()=>log.warn(`flushing connection event traces failed`))}})}export{connectionEventAttributes,connectionEventError,connectionEventTraceContext,withConnectionEventSpan};
1
+ import{createLogger,logError}from"#internal/logging.js";import{contextStorage}from"#context/container.js";import{SessionIdKey}from"#context/keys.js";import{BundleKey}from"#runtime/sessions/runtime-context-keys.js";import{formatTraceparent}from"#protocol/traceparent.js";import{ContextAgentTraceStateStore}from"#tracing/eve/agent-trace-context-store.js";import{resolveTracePolicy}from"#shared/trace-policy.js";import{ROOT_CONTEXT,context,trace}from"#compiled/@opentelemetry/api/index.js";import{markAgentTraceContext}from"#tracing/eve/agent-trace-context.js";import{activeTraceOperation,truncateTelemetryText,withErrorContent}from"#compiled/@vercel/agent-runs/otel.js";import{otelTelemetry}from"#compiled/@vercel/agent-runs/index.js";import{readInstrumentationSessionContext}from"#instrumentation/session-context.js";import{getInstrumentationRuntime}from"#instrumentation/runtime-global.js";import{withChannelAudience}from"#tracing/eve/channel-audience-context.js";import{eveOutputMapping}from"#tracing/eve/profile.js";const log=createLogger(`connection.events`);function connectionEventTraceContext(e){if(typeof e!=`object`||!e)return;let{traceId:t,spanId:n,traceFlags:r}=e;if(typeof t!=`string`||typeof n!=`string`||r!==0&&r!==1)return;let i={traceId:t,spanId:n,traceFlags:r};return formatTraceparent(i)===void 0?void 0:i}function connectionEventAttributes(e){let t={};for(let[n,r]of Object.entries({"agent.connection.name":e.connectionName,"agent.run.id":e.sessionId,"connect.subscription.id":e.subscriptionId,"connect.delivery.id":e.deliveryId,"eve.connection.event.binding.id":e.bindingId}))r!==void 0&&(t[n]=truncateTelemetryText(r,256));return t}function connectionEventError(e){let t=Error(`Connection event operation failed`);if(e instanceof Error&&[`Error`,`TypeError`,`RangeError`,`SyntaxError`,`AbortError`,`TimeoutError`,`MCPClientError`].includes(e.name)&&(t.name=e.name),typeof e!=`object`||!e)return t;let n=e,r=n.code,i=n.statusCode??n.status,a=typeof r==`number`&&Number.isFinite(r)||typeof r==`string`&&[`invalid_delivery`,`verification_unavailable`,`configuration_error`,`ETIMEDOUT`,`ECONNRESET`,`ECONNREFUSED`,`ENOTFOUND`,`EAI_AGAIN`].includes(r)?r:void 0;return a!==void 0&&Object.assign(t,{code:a}),typeof i==`number`&&Number.isInteger(i)&&i>=100&&i<=599&&Object.assign(t,{statusCode:i}),t}async function withConnectionEventSpan(e,t){return contextStorage.run(e.ctx,async()=>{let n=getInstrumentationRuntime(),r=otelTelemetry({tracerName:`eve.connection.events`,mapping:eveOutputMapping()}),i=n?.otelSettings,a=e.ctx.require(SessionIdKey),o=connectionEventAttributes({...e,sessionId:a}),run=async n=>{try{return await t(n)}catch(t){throw logError(log,`connection event operation failed`,connectionEventError(t),{...o,operation:e.operation}),t}};if(i===void 0)return r.suppressed(()=>run());let s=new ContextAgentTraceStateStore().get(`session`,a),c=readInstrumentationSessionContext(e.ctx),l=c.traceSeed?.decision??s?.decision??resolveTracePolicy(i.tracePolicy,{...c.conversation,agentName:e.ctx.require(BundleKey).resolvedAgent.config?.name??`eve`}),u=activeTraceOperation(),d=connectionEventTraceContext(e.requestTraceContext)??u?.reference??s?.context;if(l.action===`drop`||u?.capture.emit===!1||c.traceSeed!==void 0&&!(c.traceSeed.traceFlags&1)||s!==void 0&&!(s.context.traceFlags&1)||d!==void 0&&!(d.traceFlags&1))return r.suppressed(()=>run());let f=d===void 0?context.active():trace.setSpan(ROOT_CONTEXT,trace.wrapSpanContext(d)),p=markAgentTraceContext(withErrorContent(withChannelAudience(f,c.audience),!1)),m=`agent.connection.event.${e.operation}`,h=r.startSpan({type:`step`,operationId:m,name:m,kind:e.operation.startsWith(`on`)?`CONSUMER`:`INTERNAL`,attributes:{...o,"operation.name":m,"resource.name":m}},{context:p});try{let t=await r.run({type:`step`,reference:h.reference,capture:{emit:!0,recordInputs:!1,recordOutputs:!1}},()=>run(connectionEventTraceContext(h.reference)),p);if([`subscribe`,`get`,`unsubscribe`].includes(e.operation)&&typeof t==`object`&&t){let e=t;typeof e.id==`string`&&h.setAttribute(`connect.subscription.id`,truncateTelemetryText(e.id,256)),typeof e.status==`string`&&[`pending`,`active`,`needs_auth`,`stopped`,`expired`,`failed`].includes(e.status)&&h.setAttribute(`connect.subscription.status`,e.status)}return h.setAttribute(`eve.connection.event.outcome`,`completed`),h.setStatus(`OK`),t}catch(e){throw h.setAttribute(`eve.connection.event.outcome`,`failed`),h.fail(void 0,`connection_event_error`),e}finally{h.end(),await n.forceFlush().catch(()=>log.warn(`flushing connection event traces failed`))}})}export{connectionEventAttributes,connectionEventError,connectionEventTraceContext,withConnectionEventSpan};
@@ -1 +1 @@
1
- import{normalizeChannelAudience}from"#shared/channel-audience.js";import{withoutDeclinedContent}from"#compiled/@eve/tracing/otel.js";import{hasConversationRelease}from"#tracing/local/traces.js";import{channelAudienceFromContext}from"#tracing/eve/channel-audience-context.js";import{normalizeSpanExportPolicies}from"#tracing/eve/span-export-policy.js";function contentFilteringProcessor(e,t){let n=normalizeSpanExportPolicies(t);if(n.length===0)return e;let r=e;for(let e of n.toReversed())r=policyFilteringProcessor(r,e);return r}function policyFilteringProcessor(e,t){let n=new WeakMap,r=new WeakSet,i={forceFlush:()=>e.forceFlush(),onEnd:i=>{if(typeof i!=`object`||!i)return;let a=facadeFor(i,t,n);if(r.has(i)||!a.exported){r.delete(i),n.delete(i);return}a.refresh();try{e.onEnd(a.value)}finally{n.delete(i)}},onStart:(i,a)=>{if(typeof i!=`object`||!i)return;let o=facadeFor(i,t,n,channelAudienceFromContext(a));if(!o.exported){r.add(i);return}e.onStart(o.value,a)},shutdown:()=>e.shutdown()};return hasConversationRelease(e)?{...i,releaseConversation:t=>e.releaseConversation(t)}:i}function facadeFor(e,t,n,r){let i=n.get(e);if(i!==void 0)return i;let a=spanExportContext(e,r),o=spanExportDecision(a,t),s={recordInputs:!o.redactInputs,recordOutputs:!o.redactOutputs},c={},l=[],u={},d=Object.create(Reflect.getPrototypeOf(e)),f=new Map,refresh=()=>{refreshAttributes(c,e,s,a,t),refreshEvents(l,e,s),refreshStatus(u,e,s)},p,readOriginal=t=>{let n=Reflect.get(e,t,e);if(typeof n!=`function`||t===`constructor`)return n;let r=f.get(t);if(r!==void 0)return r;let created=(...t)=>{let r=Reflect.apply(n,e,t);return refresh(),r===e?p:r};return f.set(t,created),created};Object.defineProperty(d,"attributes",{configurable:!0,enumerable:!0,value:c}),Object.defineProperty(d,"events",{configurable:!0,enumerable:!0,value:l}),Object.defineProperty(d,"status",{configurable:!0,enumerable:!0,value:u});for(let t of Reflect.ownKeys(e)){if(t===`attributes`||t===`events`||t===`status`)continue;let n=Reflect.getOwnPropertyDescriptor(e,t);Object.defineProperty(d,t,{configurable:!0,enumerable:n?.enumerable??!1,get:()=>readOriginal(t)})}p=new Proxy(d,{get:(e,t,n)=>Object.hasOwn(e,t)?Reflect.get(e,t,n):readOriginal(t)});let m={context:a,exported:o.exported,refresh,value:p};return m.refresh(),n.set(e,m),m}function refreshAttributes(e,t,n,r,i){for(let t of Object.keys(e))delete e[t];let a=t.attributes;if(typeof a!=`object`||!a)return;let o=withoutDeclinedContent(a,n)??a;for(let[t,n]of Object.entries(o)){let a=attributeDecision(i,{key:t,span:r,value:n});typeof a==`object`&&a&&(`emit`in a&&`replace`in a||(`replace`in a&&a.replace===!0?a.value!==void 0&&(e[t]=a.value):`emit`in a&&a.emit===!0&&(e[t]=n)))}}function spanExportContext(e,t=`unknown`){let n=e.attributes,r=typeof n==`object`&&n?n:{},i=[r[`agent.channel.audience`],r[`ai.settings.context.eve.channel.audience`]].filter(e=>e!==void 0).map(normalizeChannelAudience),a=i.length>0&&i.every(e=>e===i[0])?i[0]:i.length>0?`unknown`:t,o=e.spanContext?.(),s=typeof o==`object`&&o?o:{},c=e.name;return{attributes:r,audience:a,name:typeof c==`string`?c:``,spanId:typeof s.spanId==`string`?s.spanId:``,traceId:typeof s.traceId==`string`?s.traceId:``}}function spanExportDecision(e,t){let n;try{n=t.span?.(e)??{emit:!0}}catch{return{exported:!1,redactInputs:!1,redactOutputs:!1}}if(typeof n!=`object`||!n)return{exported:!1,redactInputs:!1,redactOutputs:!1};if(`emit`in n)return`redact`in n?{exported:!1,redactInputs:!1,redactOutputs:!1}:{exported:typeof n.emit==`boolean`&&n.emit,redactInputs:!1,redactOutputs:!1};if(n.redact!==!0)return{exported:!1,redactInputs:!1,redactOutputs:!1};let r=n.inputs===!0,i=n.outputs===!0;return!r&&!i?{exported:!1,redactInputs:!1,redactOutputs:!1}:{exported:!0,redactInputs:r,redactOutputs:i}}function attributeDecision(e,t){if(e?.attribute===void 0)return{emit:!0};try{return e.attribute(t)}catch{return{emit:!1}}}function refreshEvents(e,t,n){e.length=0;let r=t.events;if(Array.isArray(r)){if(n.recordOutputs){e.push(...r);return}for(let t of r){if(typeof t!=`object`||!t)continue;let n=t;n.name!==`exception`&&e.push({...n,attributes:void 0})}}}function refreshStatus(e,t,n){for(let t of Object.keys(e))delete e[t];let r=t.status;if(typeof r!=`object`||!r)return;let i=r;i.code!==void 0&&(e.code=i.code),n.recordOutputs&&i.message!==void 0&&(e.message=i.message)}export{contentFilteringProcessor};
1
+ import{normalizeChannelAudience}from"#shared/channel-audience.js";import{withoutDeclinedContent}from"#compiled/@vercel/agent-runs/otel.js";import{hasConversationRelease}from"#tracing/local/traces.js";import{channelAudienceFromContext}from"#tracing/eve/channel-audience-context.js";import{normalizeSpanExportPolicies}from"#tracing/eve/span-export-policy.js";function contentFilteringProcessor(e,t){let n=normalizeSpanExportPolicies(t);if(n.length===0)return e;let r=e;for(let e of n.toReversed())r=policyFilteringProcessor(r,e);return r}function policyFilteringProcessor(e,t){let n=new WeakMap,r=new WeakSet,i={forceFlush:()=>e.forceFlush(),onEnd:i=>{if(typeof i!=`object`||!i)return;let a=facadeFor(i,t,n);if(r.has(i)||!a.exported){r.delete(i),n.delete(i);return}a.refresh();try{e.onEnd(a.value)}finally{n.delete(i)}},onStart:(i,a)=>{if(typeof i!=`object`||!i)return;let o=facadeFor(i,t,n,channelAudienceFromContext(a));if(!o.exported){r.add(i);return}e.onStart(o.value,a)},shutdown:()=>e.shutdown()};return hasConversationRelease(e)?{...i,releaseConversation:t=>e.releaseConversation(t)}:i}function facadeFor(e,t,n,r){let i=n.get(e);if(i!==void 0)return i;let a=spanExportContext(e,r),o=spanExportDecision(a,t),s={recordInputs:!o.redactInputs,recordOutputs:!o.redactOutputs},c={},l=[],u={},d=Object.create(Reflect.getPrototypeOf(e)),f=new Map,refresh=()=>{refreshAttributes(c,e,s,a,t),refreshEvents(l,e,s),refreshStatus(u,e,s)},p,readOriginal=t=>{let n=Reflect.get(e,t,e);if(typeof n!=`function`||t===`constructor`)return n;let r=f.get(t);if(r!==void 0)return r;let created=(...t)=>{let r=Reflect.apply(n,e,t);return refresh(),r===e?p:r};return f.set(t,created),created};Object.defineProperty(d,"attributes",{configurable:!0,enumerable:!0,value:c}),Object.defineProperty(d,"events",{configurable:!0,enumerable:!0,value:l}),Object.defineProperty(d,"status",{configurable:!0,enumerable:!0,value:u});for(let t of Reflect.ownKeys(e)){if(t===`attributes`||t===`events`||t===`status`)continue;let n=Reflect.getOwnPropertyDescriptor(e,t);Object.defineProperty(d,t,{configurable:!0,enumerable:n?.enumerable??!1,get:()=>readOriginal(t)})}p=new Proxy(d,{get:(e,t,n)=>Object.hasOwn(e,t)?Reflect.get(e,t,n):readOriginal(t)});let m={context:a,exported:o.exported,refresh,value:p};return m.refresh(),n.set(e,m),m}function refreshAttributes(e,t,n,r,i){for(let t of Object.keys(e))delete e[t];let a=t.attributes;if(typeof a!=`object`||!a)return;let o=withoutDeclinedContent(a,n)??a;for(let[t,n]of Object.entries(o)){let a=attributeDecision(i,{key:t,span:r,value:n});typeof a==`object`&&a&&(`emit`in a&&`replace`in a||(`replace`in a&&a.replace===!0?a.value!==void 0&&(e[t]=a.value):`emit`in a&&a.emit===!0&&(e[t]=n)))}}function spanExportContext(e,t=`unknown`){let n=e.attributes,r=typeof n==`object`&&n?n:{},i=[r[`agent.channel.audience`],r[`ai.settings.context.eve.channel.audience`]].filter(e=>e!==void 0).map(normalizeChannelAudience),a=i.length>0&&i.every(e=>e===i[0])?i[0]:i.length>0?`unknown`:t,o=e.spanContext?.(),s=typeof o==`object`&&o?o:{},c=e.name;return{attributes:r,audience:a,name:typeof c==`string`?c:``,spanId:typeof s.spanId==`string`?s.spanId:``,traceId:typeof s.traceId==`string`?s.traceId:``}}function spanExportDecision(e,t){let n;try{n=t.span?.(e)??{emit:!0}}catch{return{exported:!1,redactInputs:!1,redactOutputs:!1}}if(typeof n!=`object`||!n)return{exported:!1,redactInputs:!1,redactOutputs:!1};if(`emit`in n)return`redact`in n?{exported:!1,redactInputs:!1,redactOutputs:!1}:{exported:typeof n.emit==`boolean`&&n.emit,redactInputs:!1,redactOutputs:!1};if(n.redact!==!0)return{exported:!1,redactInputs:!1,redactOutputs:!1};let r=n.inputs===!0,i=n.outputs===!0;return!r&&!i?{exported:!1,redactInputs:!1,redactOutputs:!1}:{exported:!0,redactInputs:r,redactOutputs:i}}function attributeDecision(e,t){if(e?.attribute===void 0)return{emit:!0};try{return e.attribute(t)}catch{return{emit:!1}}}function refreshEvents(e,t,n){e.length=0;let r=t.events;if(Array.isArray(r)){if(n.recordOutputs){e.push(...r);return}for(let t of r){if(typeof t!=`object`||!t)continue;let n=t;n.name!==`exception`&&e.push({...n,attributes:void 0})}}}function refreshStatus(e,t,n){for(let t of Object.keys(e))delete e[t];let r=t.status;if(typeof r!=`object`||!r)return;let i=r;i.code!==void 0&&(e.code=i.code),n.recordOutputs&&i.message!==void 0&&(e.message=i.message)}export{contentFilteringProcessor};
@@ -1 +1 @@
1
- import{readConversationBaggage}from"#tracing/eve/conversation-context.js";import{resolveConversationId}from"#shared/conversation-identity.js";import{intersectInstrumentationDecisions}from"#shared/instrumentation-decision.js";import{createAgentDelegationTransport}from"#compiled/@eve/tracing/delegation.js";const transport=createAgentDelegationTransport(),agentDelegation={fetch:transport.fetch,resume(e,t){let{context:n}=e,r=n.trace.parentTraceContext;if(r===void 0)return t();let i=r.decision;return transport.resume({caller:r,conversationId:n.trace.conversationId??resolveConversationId(n.parent.rootSessionId),parentRunId:n.parent.sessionId,parentCallId:n.parent.callId,agentName:e.agentName,capture:{emit:r.traceFlags===1&&i?.action!==`drop`,recordInputs:i?.action===`record`&&i.recordInputs,recordOutputs:i?.action===`record`&&i.recordOutputs}},t)},receive(e,t){return transport.receive(e.headers,t=>e.delegated&&e.trusted&&e.parent!==void 0&&t.parentRunId===e.parent.sessionId&&t.parentCallId===e.parent.callId&&e.callerTrace?.traceId===t.caller.traceId&&e.callerTrace.spanId===t.caller.spanId,n=>{let r=e.parentTraceContext,i=n?.capture.emit?{action:`record`,recordInputs:n.capture.recordInputs,recordOutputs:n.capture.recordOutputs}:{action:`drop`},a=n===void 0||r===void 0?r:{...r,decision:r.decision===void 0?i:intersectInstrumentationDecisions(r.decision,i),traceFlags:n.capture.emit?r.traceFlags:0};return t({conversationId:e.delegated?n?.conversationId??readConversationBaggage(e.headers.get(`baggage`)):void 0,parentTraceContext:a})})}};export{agentDelegation};
1
+ import{readConversationBaggage}from"#tracing/eve/conversation-context.js";import{resolveConversationId}from"#shared/conversation-identity.js";import{intersectInstrumentationDecisions}from"#shared/instrumentation-decision.js";import{createAgentDelegationTransport}from"#compiled/@vercel/agent-runs/delegation.js";const transport=createAgentDelegationTransport(),agentDelegation={fetch:transport.fetch,resume(e,t){let{context:n}=e,r=n.trace.parentTraceContext;if(r===void 0)return t();let i=r.decision;return transport.resume({caller:r,conversationId:n.trace.conversationId??resolveConversationId(n.parent.rootSessionId),parentRunId:n.parent.sessionId,parentCallId:n.parent.callId,agentName:e.agentName,capture:{emit:r.traceFlags===1&&i?.action!==`drop`,recordInputs:i?.action===`record`&&i.recordInputs,recordOutputs:i?.action===`record`&&i.recordOutputs}},t)},receive(e,t){return transport.receive(e.headers,t=>e.delegated&&e.trusted&&e.parent!==void 0&&t.parentRunId===e.parent.sessionId&&t.parentCallId===e.parent.callId&&e.callerTrace?.traceId===t.caller.traceId&&e.callerTrace.spanId===t.caller.spanId,n=>{let r=e.parentTraceContext,i=n?.capture.emit?{action:`record`,recordInputs:n.capture.recordInputs,recordOutputs:n.capture.recordOutputs}:{action:`drop`},a=n===void 0||r===void 0?r:{...r,decision:r.decision===void 0?i:intersectInstrumentationDecisions(r.decision,i),traceFlags:n.capture.emit?r.traceFlags:0};return t({conversationId:e.delegated?n?.conversationId??readConversationBaggage(e.headers.get(`baggage`)):void 0,parentTraceContext:a})})}};export{agentDelegation};
@@ -1,4 +1,4 @@
1
- import type { Attributes } from "#compiled/@eve/tracing/index.js";
1
+ import type { Attributes } from "#compiled/@vercel/agent-runs/index.js";
2
2
  export declare function createGatewayTraceContextHeaders(): Record<string, string> | undefined;
3
3
  /** Converts Gateway response metadata to cost data. */
4
4
  export declare function gatewayCostAttributes(input: {