eve 0.83.2 → 0.83.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/dist/src/chunks/{use-eve-agent-ZY7NQ2VW.js → use-eve-agent-BE2_zd5q.js} +17 -12
  3. package/dist/src/chunks/{use-eve-agent-DnbG9c7c.js → use-eve-agent-e8a5vcFO.js} +17 -12
  4. package/dist/src/client/optimistic-message-submissions.d.ts +2 -3
  5. package/dist/src/client/optimistic-message-submissions.js +1 -1
  6. package/dist/src/compiled/.vendor-stamp.json +1 -1
  7. package/dist/src/execution/cancelled-model-call-batch.js +1 -1
  8. package/dist/src/execution/catalog/connection-auth.js +1 -1
  9. package/dist/src/execution/catalog/rank.js +1 -1
  10. package/dist/src/execution/dynamic-workflow/tool.js +1 -1
  11. package/dist/src/execution/legacy-session/prepare-step.js +1 -1
  12. package/dist/src/execution/session/handoff-steps.d.ts +1 -0
  13. package/dist/src/execution/session/handoff-steps.js +1 -1
  14. package/dist/src/execution/session/handoff.d.ts +1 -0
  15. package/dist/src/execution/session/handoff.js +1 -1
  16. package/dist/src/execution/session/program.js +1 -1
  17. package/dist/src/execution/session/turn-step.js +1 -1
  18. package/dist/src/execution/tools/agent-router-workflow.js +1 -1
  19. package/dist/src/execution/web-fetch/html.js +3 -4
  20. package/dist/src/harness/compaction/engine.js +2 -2
  21. package/dist/src/harness/compaction/over-limit-error.d.ts +7 -0
  22. package/dist/src/harness/compaction/over-limit-error.js +1 -0
  23. package/dist/src/harness/compaction/prompt.js +1 -1
  24. package/dist/src/harness/compaction/step.d.ts +9 -0
  25. package/dist/src/harness/compaction/step.js +1 -1
  26. package/dist/src/harness/emission.d.ts +8 -3
  27. package/dist/src/harness/emission.js +1 -1
  28. package/dist/src/harness/model-call/call.d.ts +6 -2
  29. package/dist/src/harness/model-call/call.js +1 -1
  30. package/dist/src/harness/model-call/failure.d.ts +7 -0
  31. package/dist/src/harness/model-call/failure.js +1 -1
  32. package/dist/src/harness/model-call/run.js +1 -1
  33. package/dist/src/harness/model-call/usage.js +1 -1
  34. package/dist/src/harness/session-machine/current.d.ts +8 -0
  35. package/dist/src/harness/session-machine/current.js +1 -1
  36. package/dist/src/internal/application/stamped-package-version.js +1 -1
  37. package/dist/src/internal/authored-asset-import-plugin.d.ts +8 -7
  38. package/dist/src/internal/authored-asset-import-plugin.js +1 -1
  39. package/dist/src/internal/nitro/dev-client-address.d.ts +12 -0
  40. package/dist/src/internal/nitro/dev-client-address.js +1 -1
  41. package/dist/src/internal/nitro/routes/channel-request-instrumentation.d.ts +6 -3
  42. package/dist/src/internal/nitro/routes/channel-request-instrumentation.js +1 -1
  43. package/dist/src/public/channels/auth.d.ts +14 -0
  44. package/dist/src/public/channels/auth.js +1 -1
  45. package/dist/src/public/channels/chat-sdk/chatSdkChannel.d.ts +6 -1
  46. package/dist/src/public/channels/chat-sdk/chatSdkChannel.js +1 -1
  47. package/dist/src/public/channels/slack/reply-delivery.d.ts +1 -7
  48. package/dist/src/public/channels/slack/reply-delivery.js +1 -1
  49. package/dist/src/public/channels/slack/slackChannel.d.ts +2 -6
  50. package/dist/src/public/channels/slack/slackChannel.js +1 -1
  51. package/dist/src/public/channels/undelivered-reply.d.ts +30 -0
  52. package/dist/src/public/channels/undelivered-reply.js +1 -0
  53. package/dist/src/runtime/connections/mcp-client.d.ts +5 -2
  54. package/dist/src/runtime/connections/mcp-client.js +1 -1
  55. package/dist/src/runtime/connections/openapi-client.js +1 -1
  56. package/dist/src/runtime/connections/openapi-operations.d.ts +4 -0
  57. package/dist/src/runtime/connections/openapi-operations.js +1 -1
  58. package/dist/src/runtime/connections/openapi-schema.d.ts +19 -14
  59. package/dist/src/runtime/connections/openapi-schema.js +1 -1
  60. package/dist/src/runtime/local-dev-capability.d.ts +2 -2
  61. package/dist/src/runtime/local-dev-capability.js +1 -1
  62. package/dist/src/runtime/subagents/workflow.js +1 -1
  63. package/dist/src/setup/scaffold/create/project.js +1 -1
  64. package/dist/src/shared/connection-types.d.ts +5 -0
  65. package/dist/src/svelte/index.js +1 -1
  66. package/dist/src/svelte/use-eve-agent.js +1 -1
  67. package/dist/src/tools/provided/ask-question-workflow.js +1 -1
  68. package/dist/src/tools/provided/sleep-workflow.js +1 -1
  69. package/dist/src/tools/schema.d.ts +2 -0
  70. package/dist/src/tools/schema.js +1 -1
  71. package/dist/src/tools/signature.js +1 -1
  72. package/dist/src/vue/index.js +1 -1
  73. package/dist/src/vue/use-eve-agent.js +1 -1
  74. package/docs/channels/chat-sdk.mdx +1 -1
  75. package/docs/channels/slack.mdx +1 -1
  76. package/docs/concepts/default-harness.md +1 -1
  77. package/docs/concepts/sessions-runs-and-streaming.md +1 -1
  78. package/docs/connections/openapi.mdx +1 -1
  79. package/docs/guides/auth-and-route-protection.md +4 -0
  80. package/docs/reference/cli.md +3 -1
  81. package/docs/reference/typescript-api.md +3 -1
  82. package/docs/tools/tasks.md +2 -2
  83. package/package.json +6 -2
@@ -19,6 +19,7 @@ import { type LoadThreadContextMessagesOptions } from "#public/channels/slack/th
19
19
  import { type SlackSessionOperations } from "#public/channels/slack/session-operations.js";
20
20
  import { type UploadPolicyInput } from "#public/channels/upload-policy.js";
21
21
  import { type SlackWebhookVerifier } from "#public/channels/slack/verify.js";
22
+ import { type UndeliveredReplyState } from "#public/channels/undelivered-reply.js";
22
23
  import { type Channel } from "#public/definitions/channel.js";
23
24
  import { type ChannelAudience } from "#shared/channel-audience.js";
24
25
  export type { SlackRespondOptions, SlackSendOptions, SlackSessionOperations, } from "#public/channels/slack/session-operations.js";
@@ -101,7 +102,7 @@ export interface SlackPendingApprovalCard {
101
102
  readonly messageBlocks: readonly unknown[];
102
103
  readonly messageTs: string;
103
104
  }
104
- export interface SlackChannelState {
105
+ export interface SlackChannelState extends UndeliveredReplyState {
105
106
  /** Audience classification captured before the session is dispatched. */
106
107
  audience?: ChannelAudience;
107
108
  /** Slack channel id seeded by the inbound mention. */
@@ -162,11 +163,6 @@ export interface SlackChannelState {
162
163
  * `authorization.required` and approval events.
163
164
  */
164
165
  slackUsersByPrincipal?: Record<string, string>;
165
- /**
166
- * Error id of a final reply that never reached Slack. The next delivered
167
- * message tells the model the reply was not seen, then clears it.
168
- */
169
- undeliveredReplyErrorId?: string | null;
170
166
  /**
171
167
  * Whether eve has posted in this thread. Once it has, deleting the root
172
168
  * leaves a tombstone that keeps the thread, so the final reply skips the
@@ -1 +1 @@
1
- import{markEventHandled}from"./utils.js";import{attachInputText}from"#internal/input-text.js";import{createLogger,logError}from"#internal/logging.js";import{normalizeChannelAudience}from"#shared/channel-audience.js";import{setChannelBuildMetadata}from"#channel/compiled-channel.js";import{defaultDeliverResult}from"#channel/adapter.js";import{POST,defineChannel}from"#public/definitions/channel.js";import{mergeUploadPolicy}from"#public/channels/upload-policy.js";import{maxBytesOf}from"#internal/attachments/limited-read.js";import{resolveSlackTransportOptions}from"#public/channels/slack/transport.js";import{buildSlackAuthContext,slackUserIdFromAuthContext}from"#public/channels/slack/auth.js";import{buildSlackBinding,buildSlackWorkspaceHandle,fetchSlackThreadWindow,slackContinuationToken}from"#public/channels/slack/api.js";import{parseMessageEvent,parseSlackEventEnvelope,slackEventBotUserId,slackEventInstallationTeamId,slackEventReceivingBotUserId,slackMessageFromWebhookPayload}from"#public/channels/slack/inbound.js";import{defaultInputRequestedHandler}from"#public/channels/slack/approval-cards.js";import{withFinalReplyDelivery,withUndeliveredReplyNote}from"#public/channels/slack/reply-delivery.js";import{defaultEvents,defaultOnMessage,defaultReceived}from"#public/channels/slack/defaults.js";import{composeSlackRenderers}from"#public/channels/slack/renderers.js";import{loadThreadContextMessages}from"#public/channels/slack/thread.js";import{parseSlackWebhookBody}from"#compiled/@chat-adapter/slack/webhook.js";import{bindSlackSessionOperations,withSlackResponder}from"#public/channels/slack/session-operations.js";import{buildSlackTurnMessage,collectInboundFileParts,createSlackFetchFile}from"#public/channels/slack/attachments.js";import{renderDefaultSlackTaskCard,withTaskCards}from"#public/channels/slack/task-card.js";import{formatSlackInboundMessage,formatSlackThreadContext,slackThreadSessionHistory}from"#public/channels/slack/model-context.js";import{isPrivateSlackConversation}from"#public/channels/slack/privacy.js";import{SLACK_CHANNEL_DEFAULT_ROUTE}from"#public/channels/slack/constants.js";import{defineSlackAppManifest}from"#public/channels/slack/app-manifest.js";import{handleInteractionPost}from"#public/channels/slack/interactions.js";import{verifySlackRequest as verifySlackRequest$1}from"#public/channels/slack/verify.js";const log=createLogger(`slack.channel`);function rebuildSlackContext(e,t,n,r){let{thread:i,slack:a}=buildSlackBinding({api:n,botToken:r?.botToken,channelId:e.channelId??``,threadTs:e.threadTs??``,installationTeamId:e.installationTeamId??void 0,teamId:e.teamId??void 0,onThreadTsChanged(n){e.threadTs=n,e.channelId&&t.continuation?.alias(slackContinuationToken(e.channelId,n))},onPosted(){e.postedInThread=!0}});return{thread:i,slack:a,state:e}}function slackChannel(e={}){let t=resolveSlackTransportOptions(e.api),n=mergeUploadPolicy(e.uploadPolicy),r=createSlackFetchFile({api:t,botToken:e.credentials?.botToken,maxBytes:maxBytesOf(n)}),i=e.onInputResponse??defaultOnInputResponse,a=composeSlackRenderers(e.renderers??[],{events:{...defaultEvents,"input.requested":defaultInputRequestedHandler(e.approvalChannel)},received:defaultReceived,taskCard:renderDefaultSlackTaskCard}),o=a.events[`turn.started`],s=withTaskCards({...a.events,"message.completed":withFinalReplyDelivery(a.events[`message.completed`]),async"turn.started"(e,t,n){let r=slackUserIdFromAuthContext(n.session.auth.current);r!==void 0&&(t.state.triggeringUserId=r),await o?.(e,t,n)}},a.taskCard),c=new Set,l=defineChannel({kindHint:`slack`,turnPolicy:e.turnPolicy,uploadPolicy:e.uploadPolicy,state:{channelId:null,threadTs:null,teamId:null,installationTeamId:null,triggeringUserId:null,triggeringMessageTs:null,pendingToolCallMessage:null,pendingAuthMessageTs:{},pendingApprovalCards:{},slackUsersByPrincipal:{}},fetchFile:r,metadata(e){return{channelId:e.channelId,teamId:e.teamId,threadTs:e.threadTs,triggeringUserId:e.triggeringUserId??null}},audience:({state:e})=>e.audience??`unknown`,context(n,r){return rebuildSlackContext(n,r,t,e.credentials)},deliver(e,t){return recordSlackPrincipal(t.state,t.session.auth.current,e),defaultDeliverResult(withUndeliveredReplyNote(t.state,e))},routes:[POST(e.route??SLACK_CHANNEL_DEFAULT_ROUTE,async(r,o)=>{let{waitUntil:s}=o,{from:l,resolveSession:u}=o,d=await verifyInbound(r,e.credentials);return d===null?new Response(`unauthorized`,{status:401}):shouldDropSlackHttpTimeoutRetry(r.headers)?new Response(`ok`):(r.headers.get(`content-type`)??``).includes(`application/x-www-form-urlencoded`)?handleInteractionPost(d,{from:l,resolveSession:u,waitUntil:s},{api:t,config:e,onInputResponse:i}):handleEventPost({api:t,body:d,from:l,resolveSession:u,waitUntil:s,config:e,received:a.received,uploadPolicy:n,handledEvents:c,headers:r.headers})})],receive(n,{from:r}){return receiveOnSlack(n,{from:r,api:t,credentials:e.credentials})},events:s}),u=e.credentials,d=defineSlackAppManifest({botName:e.botName});return setChannelBuildMetadata(l,e=>({externalCredentials:u?.vercelConnect,manifest:d.build(e)})),l}function defaultOnInputResponse(e){return{auth:e.defaultAuth}}async function receiveOnSlack(e,t){let n=e.target,r=n.channelId;if(!r||typeof r!=`string`)throw Error(`slackChannel().receive requires target.channelId.`);let i=typeof n.threadTs==`string`?n.threadTs:``,a=typeof n.installationTeamId==`string`?n.installationTeamId:t.installationTeamId,o=n.initialMessage;if(o&&i.length>0)throw Error("slackChannel().receive: `threadTs` and `initialMessage` are mutually exclusive.");let s=i;if(o){let{thread:e}=buildSlackBinding({api:t.api,botToken:t.credentials?.botToken,channelId:r,threadTs:``,installationTeamId:a,teamId:t.teamId}),n={card:o.card};o.fallbackText!==void 0&&(n.fallbackText=o.fallbackText),s=(await e.post(n)).id}let c=s||crypto.randomUUID(),l=n.audience===void 0?void 0:normalizeChannelAudience(n.audience),u={channelId:r,installationTeamId:a??null,threadTs:s||null,teamId:t.teamId??null,triggeringUserId:t.triggeringUserId??null};return l!==void 0&&(u.audience=l),t.from(slackContinuationToken(r,c)).send(e.message,{auth:e.auth,history:e.history,state:u,title:e.title})}function shouldDropSlackHttpTimeoutRetry(e){return Number(e.get(`x-slack-retry-num`)??`0`)>=1&&e.get(`x-slack-retry-reason`)===`http_timeout`}async function handleEventPost(e){let{config:t}=e,n,r;try{n=parseSlackWebhookBody(e.body,{headers:e.headers}),r=parseSlackEventEnvelope(e.body)}catch(e){return log.warn(`inbound webhook body is not valid JSON`,{error:e}),new Response(`ok`)}if(n.kind===`url_verification`)return new Response(n.challenge,{status:200,headers:{"content-type":`text/plain`}});if(r===null)return new Response(`ok`);let i=typeof r.api_app_id==`string`?r.api_app_id:void 0,a=slackEventBotUserId(r),o=slackEventReceivingBotUserId(r),s=slackEventInstallationTeamId(r),dispatch=null,c=null,dispatchMessage=(n,r,c)=>()=>dispatchSlackMessage({api:e.api,appId:i,botUserId:a,receivingBotUserId:o,from:e.from,resolveSession:e.resolveSession,credentials:t.credentials,handler:c,installationTeamId:s,kind:n,message:r,received:e.received,resolvesTypedInput:t.onInputResponse===void 0&&t.approvalChannel===void 0,threadContext:t.threadContext,uploadPolicy:e.uploadPolicy});if(n.kind===`app_mention`||n.kind===`direct_message`){let e=n.kind,r=slackMessageFromWebhookPayload(n,s);if(r!==null&&!isSelfAuthoredSlackMessage({appId:i,botUserId:a},r)){let n=(e===`app_mention`?t.onAppMention:t.onDirectMessage)??t.onMessage;n===void 0?c=dispatchMessage(e,r,defaultOnMessage):dispatch=dispatchMessage(e,r,n)}}let l=t.onMessage;if(dispatch===null&&l!==void 0){let e=parseMessageEvent(r);e!==null&&!isSelfAuthoredSlackMessage({appId:i,botUserId:a},e)&&(a===void 0||!e.text.includes(`<@${a}`))&&(dispatch=dispatchMessage(`channel_message`,e,l))}let u=t.onEvent;if(dispatch===null&&u!==void 0&&(dispatch=()=>dispatchSlackEvent({api:e.api,from:e.from,resolveSession:e.resolveSession,credentials:t.credentials,envelope:r,handler:u,installationTeamId:s})),dispatch??=c,dispatch===null)return new Response(`ok`);let d=r.event_id;if(d){if(e.handledEvents.has(d))return log.warn(`received a duplicate event`,{event_id:d,event_time:r.event_time,retry_num:n.retry?.num??`(null)`,retry_reason:n.retry?.reason??`(null)`}),new Response(`ok`);markEventHandled(d,e.handledEvents)}return e.waitUntil(dispatch()),new Response(`ok`)}function isSelfAuthoredSlackMessage(e,t){return e.botUserId!==void 0&&t.author?.userId===e.botUserId||e.appId!==void 0&&t.raw.app_id===e.appId}async function dispatchSlackMessage(e){let t=slackContinuationToken(e.message.channelId,e.message.threadTs),{thread:n,slack:r}=buildSlackBinding({api:e.api,appId:e.appId,botToken:e.credentials?.botToken,botUserId:e.botUserId,channelId:e.message.channelId,threadTs:e.message.threadTs,threadHasReplies:e.message.threadTs!==e.message.ts,installationTeamId:e.installationTeamId,teamId:e.message.teamId}),i=e.message.author,a={channelId:e.message.channelId,installationTeamId:e.installationTeamId??null,teamId:e.message.teamId??null,threadTs:e.message.threadTs,triggeringMessageTs:e.message.ts,triggeringUserId:i?.userId??null},o=bindSlackSessionOperations({address:t,defaultAuth:i===void 0?null:buildSlackAuthContext({channelId:e.message.channelId,fullName:i.fullName,installationTeamId:e.installationTeamId,isBot:i.isBot,teamId:e.message.teamId,threadTs:e.message.threadTs,userId:i.userId,userName:i.userName}),from:e.from,resolveSession:e.resolveSession,state:a}),s,isDMOrPrivateChannel=()=>s??=isPrivateSlackConversation({channelId:e.message.channelId,raw:e.message.raw,request:r.request}),c=e.kind===`app_mention`||e.botUserId!==void 0&&e.message.text.includes(`<@${e.botUserId}`),l={...o,isBotMentioned:()=>c,isDMOrPrivateChannel,isSubscribed:async()=>await o.resolveSession()!==void 0,slack:r,thread:n},u=e.kind===`channel_message`?void 0:acknowledgeMessage(e.received,e.message,{slack:r,thread:n}),d;try{d=await e.handler(l,e.message)}catch(t){logError(log,`${e.kind} handler failed`,t,{channelId:e.message.channelId})}if(d==null){u!==void 0&&(await u,await n.startTyping());return}await(u??acknowledgeMessage(e.received,e.message,{slack:r,thread:n}));let f=await isDMOrPrivateChannel();a.audience=e.kind===`direct_message`||f?`private`:`public`,await deliverSlackMessage({botUserId:e.receivingBotUserId,credentials:e.credentials,kind:e.kind,isPrivateConversation:f,isMentioned:c,message:e.message,resolvesTypedInput:e.resolvesTypedInput,result:d,sessionOperations:o,thread:n,threadContext:e.threadContext,uploadPolicy:e.uploadPolicy})}async function acknowledgeMessage(e,t,n){try{await e(t,n)}catch(e){logError(log,`received renderer failed`,e,{channelId:t.channelId})}}async function dispatchSlackEvent(e){let t=e.envelope.event.team_id,n=typeof t==`string`?t:typeof e.envelope.team_id==`string`?e.envelope.team_id:void 0,r=[],sourceFor=t=>e.from(slackContinuationToken(t.channelId,t.threadTs)),i={cancel:({target:e,turnId:t})=>sourceFor(e).cancel({turnId:t}),clear:({target:e})=>sourceFor(e).clear(),compact:({target:e})=>sourceFor(e).compact(),envelope:e.envelope,reset:({reason:e,target:t})=>sourceFor(t).reset({reason:e}),resolveSession:({target:t})=>e.resolveSession(slackContinuationToken(t.channelId,t.threadTs)),respond:(t,{auth:n,target:r})=>sourceFor(r).respond(t,{auth:n,state:withSlackResponder(void 0,typeof e.envelope.event.user==`string`?e.envelope.event.user:void 0)}),send:(t,{auth:r,history:i,target:a,title:o})=>receiveOnSlack({auth:r,history:i,message:t,target:a,title:o},{from:e.from,api:e.api,credentials:e.credentials,installationTeamId:e.installationTeamId,teamId:n,...typeof e.envelope.event.user==`string`?{triggeringUserId:e.envelope.event.user}:{}}),slack:buildSlackWorkspaceHandle({api:e.api,botToken:e.credentials?.botToken,installationTeamId:e.installationTeamId,teamId:n}),waitUntil(e){r.push(e)}};try{await e.handler(i,e.envelope.event)}catch(t){logError(log,`event handler failed`,t,{eventId:e.envelope.event_id,eventType:e.envelope.event.type})}await Promise.allSettled(r)}async function verifyInbound(e,t){try{return await verifySlackRequest$1(e,{signingSecret:t?.signingSecret??(t?.webhookVerifier?void 0:process.env.SLACK_SIGNING_SECRET),webhookVerifier:t?.webhookVerifier})}catch(e){return log.warn(`slack inbound verification failed`,{error:e}),null}}async function deliverSlackMessage(e){let{message:t,thread:n}=e;try{let r=e.threadContext===void 0?[]:await loadThreadContextMessages(n,t,e.threadContext),i=r.length>0&&e.result.history===void 0&&await e.sessionOperations.resolveSession()===void 0,a=i?void 0:formatSlackThreadContext(r),o=e.result.history??(i?slackThreadSessionHistory(r):void 0),s=await collectInboundFileParts({botUserId:e.botUserId,fetchThreadWindow:(e,t)=>fetchSlackThreadWindow(n,e,t),isMentioned:e.kind===`app_mention`,mention:t,thread:n,policy:e.uploadPolicy}),c={botUserId:e.botUserId,channelId:t.channelId,fullName:t.author?.fullName,isMentioned:e.isMentioned,teamId:t.teamId,threadTs:t.threadTs,userId:t.author?.userId??``,userName:t.author?.userName},l=formatSlackInboundMessage(c,t),u=buildSlackTurnMessage(a===void 0?l:`${a}\n\n${l}`,s),d=e.result.context??[],f=e.isPrivateConversation?`Private message`:e.result.title??t.markdown,p=e.resolvesTypedInput?slackTypedText(t.text,e.botUserId):``,m=attachInputText({auth:e.result.auth,title:f,...d.length>0&&{context:d},...o!==void 0&&{history:o}},s.length===0?p:void 0);await e.sessionOperations.send(u,m)}catch(n){logError(log,`${e.kind} delivery failed`,n,{channelId:t.channelId})}}function slackTypedText(e,t){return t===void 0?e:e.replace(RegExp(`<@${t}(?:\\|[^>]*)?>`,`gu`),``).trim()}function recordSlackPrincipal(e,t,n){if(t===null)return;let r=n.state?.triggeringUserId,i=slackUserIdFromAuthContext(t)??(typeof r==`string`?r:void 0);i!==void 0&&(e.slackUsersByPrincipal={...e.slackUsersByPrincipal,[t.principalId]:i})}export{slackChannel};
1
+ import{markEventHandled}from"./utils.js";import{attachInputText}from"#internal/input-text.js";import{createLogger,logError}from"#internal/logging.js";import{normalizeChannelAudience}from"#shared/channel-audience.js";import{setChannelBuildMetadata}from"#channel/compiled-channel.js";import{defaultDeliverResult}from"#channel/adapter.js";import{POST,defineChannel}from"#public/definitions/channel.js";import{mergeUploadPolicy}from"#public/channels/upload-policy.js";import{maxBytesOf}from"#internal/attachments/limited-read.js";import{withUndeliveredReplyNote}from"#public/channels/undelivered-reply.js";import{resolveSlackTransportOptions}from"#public/channels/slack/transport.js";import{buildSlackAuthContext,slackUserIdFromAuthContext}from"#public/channels/slack/auth.js";import{buildSlackBinding,buildSlackWorkspaceHandle,fetchSlackThreadWindow,slackContinuationToken}from"#public/channels/slack/api.js";import{parseMessageEvent,parseSlackEventEnvelope,slackEventBotUserId,slackEventInstallationTeamId,slackEventReceivingBotUserId,slackMessageFromWebhookPayload}from"#public/channels/slack/inbound.js";import{defaultInputRequestedHandler}from"#public/channels/slack/approval-cards.js";import{withFinalReplyDelivery}from"#public/channels/slack/reply-delivery.js";import{defaultEvents,defaultOnMessage,defaultReceived}from"#public/channels/slack/defaults.js";import{composeSlackRenderers}from"#public/channels/slack/renderers.js";import{loadThreadContextMessages}from"#public/channels/slack/thread.js";import{parseSlackWebhookBody}from"#compiled/@chat-adapter/slack/webhook.js";import{bindSlackSessionOperations,withSlackResponder}from"#public/channels/slack/session-operations.js";import{buildSlackTurnMessage,collectInboundFileParts,createSlackFetchFile}from"#public/channels/slack/attachments.js";import{renderDefaultSlackTaskCard,withTaskCards}from"#public/channels/slack/task-card.js";import{formatSlackInboundMessage,formatSlackThreadContext,slackThreadSessionHistory}from"#public/channels/slack/model-context.js";import{isPrivateSlackConversation}from"#public/channels/slack/privacy.js";import{SLACK_CHANNEL_DEFAULT_ROUTE}from"#public/channels/slack/constants.js";import{defineSlackAppManifest}from"#public/channels/slack/app-manifest.js";import{handleInteractionPost}from"#public/channels/slack/interactions.js";import{verifySlackRequest as verifySlackRequest$1}from"#public/channels/slack/verify.js";const log=createLogger(`slack.channel`);function rebuildSlackContext(e,t,n,r){let{thread:i,slack:a}=buildSlackBinding({api:n,botToken:r?.botToken,channelId:e.channelId??``,threadTs:e.threadTs??``,installationTeamId:e.installationTeamId??void 0,teamId:e.teamId??void 0,onThreadTsChanged(n){e.threadTs=n,e.channelId&&t.continuation?.alias(slackContinuationToken(e.channelId,n))},onPosted(){e.postedInThread=!0}});return{thread:i,slack:a,state:e}}function slackChannel(e={}){let t=resolveSlackTransportOptions(e.api),n=mergeUploadPolicy(e.uploadPolicy),r=createSlackFetchFile({api:t,botToken:e.credentials?.botToken,maxBytes:maxBytesOf(n)}),i=e.onInputResponse??defaultOnInputResponse,a=composeSlackRenderers(e.renderers??[],{events:{...defaultEvents,"input.requested":defaultInputRequestedHandler(e.approvalChannel)},received:defaultReceived,taskCard:renderDefaultSlackTaskCard}),o=a.events[`turn.started`],s=withTaskCards({...a.events,"message.completed":withFinalReplyDelivery(a.events[`message.completed`]),async"turn.started"(e,t,n){let r=slackUserIdFromAuthContext(n.session.auth.current);r!==void 0&&(t.state.triggeringUserId=r),await o?.(e,t,n)}},a.taskCard),c=new Set,l=defineChannel({kindHint:`slack`,turnPolicy:e.turnPolicy,uploadPolicy:e.uploadPolicy,state:{channelId:null,threadTs:null,teamId:null,installationTeamId:null,triggeringUserId:null,triggeringMessageTs:null,pendingToolCallMessage:null,pendingAuthMessageTs:{},pendingApprovalCards:{},slackUsersByPrincipal:{}},fetchFile:r,metadata(e){return{channelId:e.channelId,teamId:e.teamId,threadTs:e.threadTs,triggeringUserId:e.triggeringUserId??null}},audience:({state:e})=>e.audience??`unknown`,context(n,r){return rebuildSlackContext(n,r,t,e.credentials)},deliver(e,t){return recordSlackPrincipal(t.state,t.session.auth.current,e),defaultDeliverResult(withUndeliveredReplyNote(t.state,e,`Slack`))},routes:[POST(e.route??SLACK_CHANNEL_DEFAULT_ROUTE,async(r,o)=>{let{waitUntil:s}=o,{from:l,resolveSession:u}=o,d=await verifyInbound(r,e.credentials);return d===null?new Response(`unauthorized`,{status:401}):shouldDropSlackHttpTimeoutRetry(r.headers)?new Response(`ok`):(r.headers.get(`content-type`)??``).includes(`application/x-www-form-urlencoded`)?handleInteractionPost(d,{from:l,resolveSession:u,waitUntil:s},{api:t,config:e,onInputResponse:i}):handleEventPost({api:t,body:d,from:l,resolveSession:u,waitUntil:s,config:e,received:a.received,uploadPolicy:n,handledEvents:c,headers:r.headers})})],receive(n,{from:r}){return receiveOnSlack(n,{from:r,api:t,credentials:e.credentials})},events:s}),u=e.credentials,d=defineSlackAppManifest({botName:e.botName});return setChannelBuildMetadata(l,e=>({externalCredentials:u?.vercelConnect,manifest:d.build(e)})),l}function defaultOnInputResponse(e){return{auth:e.defaultAuth}}async function receiveOnSlack(e,t){let n=e.target,r=n.channelId;if(!r||typeof r!=`string`)throw Error(`slackChannel().receive requires target.channelId.`);let i=typeof n.threadTs==`string`?n.threadTs:``,a=typeof n.installationTeamId==`string`?n.installationTeamId:t.installationTeamId,o=n.initialMessage;if(o&&i.length>0)throw Error("slackChannel().receive: `threadTs` and `initialMessage` are mutually exclusive.");let s=i;if(o){let{thread:e}=buildSlackBinding({api:t.api,botToken:t.credentials?.botToken,channelId:r,threadTs:``,installationTeamId:a,teamId:t.teamId}),n={card:o.card};o.fallbackText!==void 0&&(n.fallbackText=o.fallbackText),s=(await e.post(n)).id}let c=s||crypto.randomUUID(),l=n.audience===void 0?void 0:normalizeChannelAudience(n.audience),u={channelId:r,installationTeamId:a??null,threadTs:s||null,teamId:t.teamId??null,triggeringUserId:t.triggeringUserId??null};return l!==void 0&&(u.audience=l),t.from(slackContinuationToken(r,c)).send(e.message,{auth:e.auth,history:e.history,state:u,title:e.title})}function shouldDropSlackHttpTimeoutRetry(e){return Number(e.get(`x-slack-retry-num`)??`0`)>=1&&e.get(`x-slack-retry-reason`)===`http_timeout`}async function handleEventPost(e){let{config:t}=e,n,r;try{n=parseSlackWebhookBody(e.body,{headers:e.headers}),r=parseSlackEventEnvelope(e.body)}catch(e){return log.warn(`inbound webhook body is not valid JSON`,{error:e}),new Response(`ok`)}if(n.kind===`url_verification`)return new Response(n.challenge,{status:200,headers:{"content-type":`text/plain`}});if(r===null)return new Response(`ok`);let i=typeof r.api_app_id==`string`?r.api_app_id:void 0,a=slackEventBotUserId(r),o=slackEventReceivingBotUserId(r),s=slackEventInstallationTeamId(r),dispatch=null,c=null,dispatchMessage=(n,r,c)=>()=>dispatchSlackMessage({api:e.api,appId:i,botUserId:a,receivingBotUserId:o,from:e.from,resolveSession:e.resolveSession,credentials:t.credentials,handler:c,installationTeamId:s,kind:n,message:r,received:e.received,resolvesTypedInput:t.onInputResponse===void 0&&t.approvalChannel===void 0,threadContext:t.threadContext,uploadPolicy:e.uploadPolicy});if(n.kind===`app_mention`||n.kind===`direct_message`){let e=n.kind,r=slackMessageFromWebhookPayload(n,s);if(r!==null&&!isSelfAuthoredSlackMessage({appId:i,botUserId:a},r)){let n=(e===`app_mention`?t.onAppMention:t.onDirectMessage)??t.onMessage;n===void 0?c=dispatchMessage(e,r,defaultOnMessage):dispatch=dispatchMessage(e,r,n)}}let l=t.onMessage;if(dispatch===null&&l!==void 0){let e=parseMessageEvent(r);e!==null&&!isSelfAuthoredSlackMessage({appId:i,botUserId:a},e)&&(a===void 0||!e.text.includes(`<@${a}`))&&(dispatch=dispatchMessage(`channel_message`,e,l))}let u=t.onEvent;if(dispatch===null&&u!==void 0&&(dispatch=()=>dispatchSlackEvent({api:e.api,from:e.from,resolveSession:e.resolveSession,credentials:t.credentials,envelope:r,handler:u,installationTeamId:s})),dispatch??=c,dispatch===null)return new Response(`ok`);let d=r.event_id;if(d){if(e.handledEvents.has(d))return log.warn(`received a duplicate event`,{event_id:d,event_time:r.event_time,retry_num:n.retry?.num??`(null)`,retry_reason:n.retry?.reason??`(null)`}),new Response(`ok`);markEventHandled(d,e.handledEvents)}return e.waitUntil(dispatch()),new Response(`ok`)}function isSelfAuthoredSlackMessage(e,t){return e.botUserId!==void 0&&t.author?.userId===e.botUserId||e.appId!==void 0&&t.raw.app_id===e.appId}async function dispatchSlackMessage(e){let t=slackContinuationToken(e.message.channelId,e.message.threadTs),{thread:n,slack:r}=buildSlackBinding({api:e.api,appId:e.appId,botToken:e.credentials?.botToken,botUserId:e.botUserId,channelId:e.message.channelId,threadTs:e.message.threadTs,threadHasReplies:e.message.threadTs!==e.message.ts,installationTeamId:e.installationTeamId,teamId:e.message.teamId}),i=e.message.author,a={channelId:e.message.channelId,installationTeamId:e.installationTeamId??null,teamId:e.message.teamId??null,threadTs:e.message.threadTs,triggeringMessageTs:e.message.ts,triggeringUserId:i?.userId??null},o=bindSlackSessionOperations({address:t,defaultAuth:i===void 0?null:buildSlackAuthContext({channelId:e.message.channelId,fullName:i.fullName,installationTeamId:e.installationTeamId,isBot:i.isBot,teamId:e.message.teamId,threadTs:e.message.threadTs,userId:i.userId,userName:i.userName}),from:e.from,resolveSession:e.resolveSession,state:a}),s,isDMOrPrivateChannel=()=>s??=isPrivateSlackConversation({channelId:e.message.channelId,raw:e.message.raw,request:r.request}),c=e.kind===`app_mention`||e.botUserId!==void 0&&e.message.text.includes(`<@${e.botUserId}`),l={...o,isBotMentioned:()=>c,isDMOrPrivateChannel,isSubscribed:async()=>await o.resolveSession()!==void 0,slack:r,thread:n},u=e.kind===`channel_message`?void 0:acknowledgeMessage(e.received,e.message,{slack:r,thread:n}),d;try{d=await e.handler(l,e.message)}catch(t){logError(log,`${e.kind} handler failed`,t,{channelId:e.message.channelId})}if(d==null){u!==void 0&&(await u,await n.startTyping());return}await(u??acknowledgeMessage(e.received,e.message,{slack:r,thread:n}));let f=await isDMOrPrivateChannel();a.audience=e.kind===`direct_message`||f?`private`:`public`,await deliverSlackMessage({botUserId:e.receivingBotUserId,credentials:e.credentials,kind:e.kind,isPrivateConversation:f,isMentioned:c,message:e.message,resolvesTypedInput:e.resolvesTypedInput,result:d,sessionOperations:o,thread:n,threadContext:e.threadContext,uploadPolicy:e.uploadPolicy})}async function acknowledgeMessage(e,t,n){try{await e(t,n)}catch(e){logError(log,`received renderer failed`,e,{channelId:t.channelId})}}async function dispatchSlackEvent(e){let t=e.envelope.event.team_id,n=typeof t==`string`?t:typeof e.envelope.team_id==`string`?e.envelope.team_id:void 0,r=[],sourceFor=t=>e.from(slackContinuationToken(t.channelId,t.threadTs)),i={cancel:({target:e,turnId:t})=>sourceFor(e).cancel({turnId:t}),clear:({target:e})=>sourceFor(e).clear(),compact:({target:e})=>sourceFor(e).compact(),envelope:e.envelope,reset:({reason:e,target:t})=>sourceFor(t).reset({reason:e}),resolveSession:({target:t})=>e.resolveSession(slackContinuationToken(t.channelId,t.threadTs)),respond:(t,{auth:n,target:r})=>sourceFor(r).respond(t,{auth:n,state:withSlackResponder(void 0,typeof e.envelope.event.user==`string`?e.envelope.event.user:void 0)}),send:(t,{auth:r,history:i,target:a,title:o})=>receiveOnSlack({auth:r,history:i,message:t,target:a,title:o},{from:e.from,api:e.api,credentials:e.credentials,installationTeamId:e.installationTeamId,teamId:n,...typeof e.envelope.event.user==`string`?{triggeringUserId:e.envelope.event.user}:{}}),slack:buildSlackWorkspaceHandle({api:e.api,botToken:e.credentials?.botToken,installationTeamId:e.installationTeamId,teamId:n}),waitUntil(e){r.push(e)}};try{await e.handler(i,e.envelope.event)}catch(t){logError(log,`event handler failed`,t,{eventId:e.envelope.event_id,eventType:e.envelope.event.type})}await Promise.allSettled(r)}async function verifyInbound(e,t){try{return await verifySlackRequest$1(e,{signingSecret:t?.signingSecret??(t?.webhookVerifier?void 0:process.env.SLACK_SIGNING_SECRET),webhookVerifier:t?.webhookVerifier})}catch(e){return log.warn(`slack inbound verification failed`,{error:e}),null}}async function deliverSlackMessage(e){let{message:t,thread:n}=e;try{let r=e.threadContext===void 0?[]:await loadThreadContextMessages(n,t,e.threadContext),i=r.length>0&&e.result.history===void 0&&await e.sessionOperations.resolveSession()===void 0,a=i?void 0:formatSlackThreadContext(r),o=e.result.history??(i?slackThreadSessionHistory(r):void 0),s=await collectInboundFileParts({botUserId:e.botUserId,fetchThreadWindow:(e,t)=>fetchSlackThreadWindow(n,e,t),isMentioned:e.kind===`app_mention`,mention:t,thread:n,policy:e.uploadPolicy}),c={botUserId:e.botUserId,channelId:t.channelId,fullName:t.author?.fullName,isMentioned:e.isMentioned,teamId:t.teamId,threadTs:t.threadTs,userId:t.author?.userId??``,userName:t.author?.userName},l=formatSlackInboundMessage(c,t),u=buildSlackTurnMessage(a===void 0?l:`${a}\n\n${l}`,s),d=e.result.context??[],f=e.isPrivateConversation?`Private message`:e.result.title??t.markdown,p=e.resolvesTypedInput?slackTypedText(t.text,e.botUserId):``,m=attachInputText({auth:e.result.auth,title:f,...d.length>0&&{context:d},...o!==void 0&&{history:o}},s.length===0?p:void 0);await e.sessionOperations.send(u,m)}catch(n){logError(log,`${e.kind} delivery failed`,n,{channelId:t.channelId})}}function slackTypedText(e,t){return t===void 0?e:e.replace(RegExp(`<@${t}(?:\\|[^>]*)?>`,`gu`),``).trim()}function recordSlackPrincipal(e,t,n){if(t===null)return;let r=n.state?.triggeringUserId,i=slackUserIdFromAuthContext(t)??(typeof r==`string`?r:void 0);i!==void 0&&(e.slackUsersByPrincipal={...e.slackUsersByPrincipal,[t.principalId]:i})}export{slackChannel};
@@ -0,0 +1,30 @@
1
+ import type { DeliverPayload } from "#channel/types.js";
2
+ import { type Logger } from "#internal/logging.js";
3
+ /** Channel state that remembers a final reply the user never saw. */
4
+ export interface UndeliveredReplyState {
5
+ /**
6
+ * Error id of a final reply that never reached the user. The next delivered
7
+ * message tells the model the reply was not seen, then clears it.
8
+ */
9
+ undeliveredReplyErrorId?: string | null;
10
+ }
11
+ /** Where a channel's final reply failed, and how to post a notice there. */
12
+ export interface UndeliveredReplySurface {
13
+ readonly log: Logger;
14
+ /** The surface as the user and the model know it, e.g. `"Slack"`. */
15
+ readonly name: string;
16
+ readonly post: (notice: string) => Promise<unknown>;
17
+ readonly state: UndeliveredReplyState;
18
+ }
19
+ /**
20
+ * Records a final reply that failed to reach the user: logs `error` at error
21
+ * level, remembers its error id for {@link withUndeliveredReplyNote}, and
22
+ * posts a notice that names the id without repeating the reply. A failed
23
+ * notice is logged, not thrown.
24
+ */
25
+ export declare function reportUndeliveredReply(surface: UndeliveredReplySurface, turnId: string, error: unknown): Promise<void>;
26
+ /**
27
+ * Tells the model, ahead of the next message, that its previous reply never
28
+ * reached `surfaceName`, so it does not assume the user read that reply.
29
+ */
30
+ export declare function withUndeliveredReplyNote<T extends DeliverPayload>(state: UndeliveredReplyState, payload: T, surfaceName: string): T;
@@ -0,0 +1 @@
1
+ import{logError}from"#internal/logging.js";async function reportUndeliveredReply(e,t,n){let r=logError(e.log,`final reply was not delivered to ${e.name}`,n,{turnId:t});e.state.undeliveredReplyErrorId=r;try{await e.post(`I finished, but couldn't deliver my answer in ${e.name} (error id \`${r}\`). Please ask me to resend it.`)}catch(n){logError(e.log,`undelivered reply notice failed`,n,{errorId:r,turnId:t})}}function withUndeliveredReplyNote(e,t,n){let r=e.undeliveredReplyErrorId;if(!r||t.message===void 0)return t;e.undeliveredReplyErrorId=null;let i=[`Your previous reply was not delivered to ${n} (error id ${r}).`,`The user has not seen it. Do not assume they read it; send the answer again if they ask for it.`].join(` `);return{...t,context:[i,...t.context??[]]}}export{reportUndeliveredReply,withUndeliveredReplyNote};
@@ -69,9 +69,12 @@ export declare const MCP_WWW_AUTHENTICATE_META_KEY = "mcp/www_authenticate";
69
69
  export declare function isMcpAuthChallengeResult(result: unknown): boolean;
70
70
  export declare function readHttpStatus(error: unknown): number | undefined;
71
71
  /**
72
- * Returns `true` when a tool name passes the configured filter.
72
+ * Returns `true` when a tool passes the configured filter. A tool may be known
73
+ * by more than one name, such as an OpenAPI tool's name and the `operationId`
74
+ * it was derived from; `allow` admits it when any name is listed, and `block`
75
+ * hides it when any name is listed.
73
76
  */
74
- export declare function passesToolFilter(toolName: string, filter: Readonly<ToolFilterDefinition> | undefined): boolean;
77
+ export declare function passesToolFilter(names: readonly string[], filter: Readonly<ToolFilterDefinition> | undefined): boolean;
75
78
  /**
76
79
  * Merges `authorization` (Bearer token) and `headers` into one
77
80
  * flat `Record<string, string>` for the transport layer.
@@ -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 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
+ 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?e.some(e=>t.allow.includes(e)):!e.some(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 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{response:d,location:f}=await fetchWithinOrigin(l,{method:e.method.toUpperCase(),headers:a,body:u,signal:r?.abortSignal},this.#n.connectionName),p={status:d.status,statusText:d.statusText,body:await readResponseBody(d)};return f!==void 0&&(p.location=f),p}};const REDIRECT_STATUSES=new Set([301,302,303,307,308]);async function fetchWithinOrigin(e,t,n){let r=e,i=t;for(let t=0;;t++){let a=await fetch(r,{...i,redirect:`manual`}),o=a.headers.get(`location`);if(!REDIRECT_STATUSES.has(a.status)||o===null)return{response:a};let s=URL.parse(o,r.href);if(s===null)return{response:a};if(s.origin!==e.origin)return{response:a,location:s.href};if(await a.body?.cancel(),t>=10)throw Error(`OpenAPI connection "${n}" stopped after 10 redirects from "${e.origin}${e.pathname}", last to "${s.pathname}". The API may be redirecting in a loop.`);r=s,i=redirectedRequest(i,a.status)}}function redirectedRequest(e,t){if(!(t===303&&e.method!==`GET`&&e.method!==`HEAD`||(t===301||t===302)&&e.method===`POST`))return e;let n=Object.fromEntries(Object.entries(e.headers).filter(([e])=>e.toLowerCase()!==`content-type`));return{...e,method:`GET`,headers:n,body:void 0}}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,declaredOperationId,operationDescription,operationName,uniqueName}from"#runtime/connections/openapi-operations.js";import{buildInputSchema,createSchemaConverter,deref,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.#p(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.#s(),t=this.#o(e),n=this.#c(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){this.#a(e.toolName,t);continue}i.set(e.toolName,e),r.push({description:e.description,inputSchema:t,name:e.toolName,...e.operationId!==void 0&&{operationId:e.operationId}})}return{metadata:r,operations:i,baseUrl:t}}#a(e,t){log.warn(`omitting OpenAPI operation with an invalid input schema`,{connectionName:this.#n.connectionName,error:t,toolName:e})}#o(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#s(){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}#c(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],{convert:d,defs:f}=createSchemaConverter(e),p,m;try{p=this.#l(e,u,d),m=this.#u(e,s.requestBody,u,d)}catch(e){this.#a(c,e);continue}n.push({toolName:c,operationId:declaredOperationId(s),method:o,pathTemplate:i,description:operationDescription(s),parameters:p,requestBody:m,inputSchema:buildInputSchema(p,m,f),security:resolveSecurity(e,s)})}}return n}#l(e,t,n){let r=[];for(let i of t){let t=isObject(i)?deref(e,i):i;if(!isObject(t))continue;let a=t.in;if(a!==`path`&&a!==`query`&&a!==`header`&&a!==`cookie`||typeof t.name!=`string`)continue;let o=this.#d(t,n);r.push({name:t.name,location:a,required:t.required===!0||a===`path`,schema:o,description:typeof t.description==`string`?t.description:void 0})}return r}#u(e,t,n,r){if(isObject(t)){let n=deref(e,t);if(isObject(n)&&isObject(n.content)){let e=n.content,t=`application/json`in e?`application/json`:Object.keys(e)[0];if(t!==void 0){let i=e[t],a=isObject(i)&&isObject(i.schema)?r(i.schema):{};return{required:n.required===!0,contentType:t,schema:a}}}}return this.#f(e,n,r)}#d(e,t){if(isObject(e.schema))return t(e.schema);let n={};for(let t of SWAGGER_PARAMETER_SCHEMA_KEYS)e[t]!==void 0&&(n[t]=e[t]);return t(n)}#f(e,t,n){for(let r of t){let t=isObject(r)?deref(e,r):r;if(!isObject(t)||t.in!==`body`)continue;let i=isObject(t.schema)?n(t.schema):{};return{required:t.required===!0,contentType:`application/json`,schema:i}}}async#p(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{response:d,location:f}=await fetchWithinOrigin(l,{method:e.method.toUpperCase(),headers:a,body:u,signal:r?.abortSignal},this.#n.connectionName),p={status:d.status,statusText:d.statusText,body:await readResponseBody(d)};return f!==void 0&&(p.location=f),p}};const REDIRECT_STATUSES=new Set([301,302,303,307,308]);async function fetchWithinOrigin(e,t,n){let r=e,i=t;for(let t=0;;t++){let a=await fetch(r,{...i,redirect:`manual`}),o=a.headers.get(`location`);if(!REDIRECT_STATUSES.has(a.status)||o===null)return{response:a};let s=URL.parse(o,r.href);if(s===null)return{response:a};if(s.origin!==e.origin)return{response:a,location:s.href};if(await a.body?.cancel(),t>=10)throw Error(`OpenAPI connection "${n}" stopped after 10 redirects from "${e.origin}${e.pathname}", last to "${s.pathname}". The API may be redirecting in a loop.`);r=s,i=redirectedRequest(i,a.status)}}function redirectedRequest(e,t){if(!(t===303&&e.method!==`GET`&&e.method!==`HEAD`||(t===301||t===302)&&e.method===`POST`))return e;let n=Object.fromEntries(Object.entries(e.headers).filter(([e])=>e.toLowerCase()!==`content-type`));return{...e,method:`GET`,headers:n,body:void 0}}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};
@@ -6,6 +6,8 @@ export type HttpMethod = (typeof HTTP_METHODS)[number];
6
6
  /** Internal descriptor for one resolved OpenAPI operation. */
7
7
  export interface OpenApiOperation {
8
8
  readonly toolName: string;
9
+ /** The document's `operationId`, when the operation declares one. */
10
+ readonly operationId: string | undefined;
9
11
  readonly method: HttpMethod;
10
12
  readonly pathTemplate: string;
11
13
  readonly description: string;
@@ -24,6 +26,8 @@ export interface OpenApiOperation {
24
26
  * without an `operationId` get a deterministic `<method>_<path>` name.
25
27
  */
26
28
  export declare function operationName(operation: Record<string, unknown>, method: HttpMethod, pathTemplate: string): string;
29
+ /** The operation's `operationId`, when it declares a non-empty one. */
30
+ export declare function declaredOperationId(operation: Record<string, unknown>): string | undefined;
27
31
  /** Disambiguates a tool name against names already used in the same connection. */
28
32
  export declare function uniqueName(name: string, used: Set<string>): string;
29
33
  /** Picks a human description for an operation, preferring `summary` over `description`. */
@@ -1 +1 @@
1
- const HTTP_METHODS=[`get`,`put`,`post`,`delete`,`patch`,`head`,`options`];function operationName(e,t,n){if(typeof e.operationId==`string`&&e.operationId.length>0){let t=sanitizeToolName(e.operationId);if(t.length>0)return t}return sanitizeToolName(`${t}_${n.replace(/[{}]/g,``).replace(/[^a-zA-Z0-9]+/g,`_`).replace(/^_+|_+$/g,``)}`)}function sanitizeToolName(e){return e.replace(/[^a-zA-Z0-9_-]+/g,`_`).replace(/^[_-]+|[_-]+$/g,``).slice(0,64)}function uniqueName(e,t){let n=e,r=2;for(;t.has(n);){let t=`_${r}`;n=`${e.slice(0,64-t.length)}${t}`,r+=1}return t.add(n),n}function operationDescription(e){return typeof e.summary==`string`&&e.summary.length>0?e.summary:typeof e.description==`string`?e.description:``}export{HTTP_METHODS,operationDescription,operationName,uniqueName};
1
+ const HTTP_METHODS=[`get`,`put`,`post`,`delete`,`patch`,`head`,`options`];function operationName(e,t,n){let r=declaredOperationId(e);if(r!==void 0){let e=sanitizeToolName(r);if(e.length>0)return e}return sanitizeToolName(`${t}_${n.replace(/[{}]/g,``).replace(/[^a-zA-Z0-9]+/g,`_`).replace(/^_+|_+$/g,``)}`)}function declaredOperationId(e){return typeof e.operationId==`string`&&e.operationId.length>0?e.operationId:void 0}function sanitizeToolName(e){return e.replace(/[^a-zA-Z0-9_-]+/g,`_`).replace(/^[_-]+|[_-]+$/g,``).slice(0,64)}function uniqueName(e,t){let n=e,r=2;for(;t.has(n);){let t=`_${r}`;n=`${e.slice(0,64-t.length)}${t}`,r+=1}return t.add(n),n}function operationDescription(e){return typeof e.summary==`string`&&e.summary.length>0?e.summary:typeof e.description==`string`?e.description:``}export{HTTP_METHODS,declaredOperationId,operationDescription,operationName,uniqueName};
@@ -15,25 +15,30 @@ export interface OpenApiRequestBody {
15
15
  /**
16
16
  * Builds the combined JSON Schema the model fills in: each path, query,
17
17
  * and header parameter becomes a top-level property; the request body
18
- * (when present) is nested under `body`.
18
+ * (when present) is nested under `body`. The component schemas they refer
19
+ * to sit under `$defs`.
19
20
  */
20
- export declare function buildInputSchema(parameters: readonly OpenApiParameter[], requestBody: OpenApiRequestBody | undefined): Record<string, unknown>;
21
+ export declare function buildInputSchema(parameters: readonly OpenApiParameter[], requestBody: OpenApiRequestBody | undefined, defs: Readonly<Record<string, unknown>>): Record<string, unknown>;
21
22
  /** Resolves a single `$ref` node one hop; returns the node unchanged otherwise. */
22
23
  export declare function deref(document: Record<string, unknown>, node: Record<string, unknown>): unknown;
24
+ /** Converts one operation's schemas, collecting what they refer to. */
25
+ export interface SchemaConverter {
26
+ /**
27
+ * Converts an OpenAPI schema to JSON Schema draft 2020-12. Each local
28
+ * `$ref` points into {@link defs}, which gets the converted target once.
29
+ */
30
+ readonly convert: (schema: unknown) => unknown;
31
+ /** The converted `$ref` targets, keyed by the names `convert` points at. */
32
+ readonly defs: Readonly<Record<string, unknown>>;
33
+ }
23
34
  /**
24
- * Deeply resolves local `$ref` pointers in a JSON Schema, truncating
25
- * `$ref` cycles and over-deep nesting so the result stays finite and
26
- * serializable.
35
+ * Creates a converter for one operation's input schema.
27
36
  *
28
- * Truncation only ever happens at an **object** node — which is always a
29
- * schema position — by replacing it with an empty schema (`{}`). Scalars
30
- * (`type` strings, `required` entries, `enum` values) pass through
31
- * unchanged and arrays are always preserved as arrays, so array-valued
32
- * keywords like `oneOf`/`anyOf`/`allOf` and `type: [..., "null"]` keep
33
- * their shape. This keeps the output valid JSON Schema (draft 2020-12)
34
- * for strict model providers, while the depth bound prevents recursive
35
- * specs (e.g. Notion blocks) from expanding without limit.
37
+ * `$ref`s stay references instead of being copied in place, so a schema
38
+ * shared by many properties, or one that refers to itself (Notion blocks),
39
+ * costs its size once. Copying them in place would grow exponentially and
40
+ * need a depth limit that cuts valid deep schemas off.
36
41
  */
37
- export declare function derefSchema(document: Record<string, unknown>, node: unknown, depth?: number, seen?: ReadonlySet<string>): unknown;
42
+ export declare function createSchemaConverter(document: Record<string, unknown>): SchemaConverter;
38
43
  /** Narrows `unknown` to a readonly array, used pervasively when duck-typing spec nodes. */
39
44
  export declare function isArray(value: unknown): value is readonly unknown[];
@@ -1 +1 @@
1
- import{isObject}from"#shared/guards.js";function buildInputSchema(e,t){let n={},r=[];for(let t of e)n[t.name]=t.description===void 0?t.schema:{...t.schema,description:t.description},t.required&&r.push(t.name);t!==void 0&&(n.body=t.schema,t.required&&r.push(`body`));let i={type:`object`,properties:n};return r.length>0&&(i.required=r),i}function deref(e,t){return typeof t.$ref==`string`?resolveRef(e,t.$ref)??{}:t}function derefSchema(e,t,n=0,r=new Set){if(isArray(t))return t.map(t=>derefSchema(e,t,n+1,r));if(!isObject(t))return t;if(n>12)return{};if(typeof t.$ref==`string`){if(r.has(t.$ref))return{};let i=resolveRef(e,t.$ref);return i===void 0?{}:derefSchema(e,i,n+1,new Set([...r,t.$ref]))}let i={};for(let[a,o]of Object.entries(t))i[a]=a==="default"||a===`example`?o:(a===`properties`||a===`patternProperties`||a===`$defs`||a===`definitions`)&&isObject(o)?Object.fromEntries(Object.entries(o).map(([t,i])=>[t,derefSchema(e,i,n+2,r)])):derefSchema(e,o,n+1,r);return normalizeSchemaType(i),normalizeNullable(i),normalizeSchemaAnnotations(i),i}const VALID_JSON_SCHEMA_TYPES=new Set([`string`,`number`,`integer`,`boolean`,`object`,`array`,`null`]);function normalizeSchemaType(e){let t=e.type;if(typeof t==`string`&&!VALID_JSON_SCHEMA_TYPES.has(t))delete e.type;else if(isArray(t)){let n=t.filter(e=>typeof e==`string`&&VALID_JSON_SCHEMA_TYPES.has(e));n.length===0?delete e.type:e.type=n}}function normalizeNullable(e){if(!(`nullable`in e))return;let t=e.nullable===!0;if(delete e.nullable,!t)return;let n=e.type;typeof n==`string`?n!==`null`&&(e.type=[n,`null`]):isArray(n)?n.includes(`null`)||(e.type=[...n,`null`]):isArray(e.enum)&&!e.enum.includes(null)&&(e.enum=[...e.enum,null])}function normalizeSchemaAnnotations(e){let t=e.type;if(typeof t==`string`||isArray(t))for(let n of[`default`,`example`])n in e&&!matchesSchemaType(e[n],t)&&delete e[n]}function matchesSchemaType(e,t){return(typeof t==`string`?[t]:t).some(t=>{switch(t){case`string`:return typeof e==`string`;case`number`:return typeof e==`number`&&Number.isFinite(e);case`integer`:return typeof e==`number`&&Number.isInteger(e);case`boolean`:return typeof e==`boolean`;case`object`:return isObject(e);case`array`:return isArray(e);case`null`:return e===null;default:return!1}})}function resolveRef(e,t){if(!t.startsWith(`#/`))return;let n=t.slice(2).split(`/`).map(e=>e.replace(/~1/g,`/`).replace(/~0/g,`~`)),r=e;for(let e of n){if(!isObject(r))return;r=r[e]}return r}function isArray(e){return Array.isArray(e)}export{buildInputSchema,deref,derefSchema,isArray};
1
+ import{isObject}from"#shared/guards.js";function buildInputSchema(e,t,n){let r={},i=[];for(let t of e)r[t.name]=t.description===void 0?t.schema:{...t.schema,description:t.description},t.required&&i.push(t.name);t!==void 0&&(r.body=t.schema,t.required&&i.push(`body`));let a={type:`object`,properties:r};return i.length>0&&(a.required=i),Object.keys(n).length>0&&(a.$defs=n),a}function deref(e,t){return typeof t.$ref==`string`?resolveRef(e,t.$ref)??{}:t}const SCHEMA_MAP_KEYWORDS=new Set([`properties`,`patternProperties`,`$defs`,`definitions`]),BASE_URI_KEYWORDS=new Set([`$id`,`$anchor`,`$dynamicAnchor`,`$schema`]);function createSchemaConverter(e){let t={},n=new Map,r=[],define=i=>{if(n.has(i))return n.get(i);let a=resolveRef(e,i),o=a===void 0?void 0:uniqueKey(i,t);return n.set(i,o),o!==void 0&&(t[o]={},isAliasCycle(e,i)||r.push([o,a])),o},walk=e=>{if(isArray(e))return e.map(walk);if(!isObject(e))return e;if(typeof e.$ref==`string`){let t=define(e.$ref);return t===void 0?{}:{$ref:`#/$defs/${t}`}}let t={};for(let[n,r]of Object.entries(e))n==="default"||n===`example`?t[n]=r:SCHEMA_MAP_KEYWORDS.has(n)&&isObject(r)?t[n]=Object.fromEntries(Object.entries(r).map(([e,t])=>[e,walk(t)])):BASE_URI_KEYWORDS.has(n)||(t[n]=walk(r));return normalizeSchemaType(t),normalizeNullable(t),normalizeSchemaAnnotations(t),t};return{convert:e=>{let n=walk(e);for(let e=r.pop();e!==void 0;e=r.pop())t[e[0]]=walk(e[1]);return n},defs:t}}function isAliasCycle(e,t){let n=new Set;for(let r=t;typeof r==`string`;){if(n.has(r))return!0;n.add(r);let t=resolveRef(e,r);r=isObject(t)?t.$ref:void 0}return!1}function uniqueKey(e,t){let n=(e.slice(e.lastIndexOf(`/`)+1)||`schema`).replace(/[^\w.-]/g,`_`),r=n;for(let e=2;Object.hasOwn(t,r)||r===`__proto__`;e+=1)r=`${n}_${e}`;return r}const VALID_JSON_SCHEMA_TYPES=new Set([`string`,`number`,`integer`,`boolean`,`object`,`array`,`null`]);function normalizeSchemaType(e){let t=e.type;if(typeof t==`string`&&!VALID_JSON_SCHEMA_TYPES.has(t))delete e.type;else if(isArray(t)){let n=t.filter(e=>typeof e==`string`&&VALID_JSON_SCHEMA_TYPES.has(e));n.length===0?delete e.type:e.type=n}}function normalizeNullable(e){if(!(`nullable`in e))return;let t=e.nullable===!0;if(delete e.nullable,!t)return;let n=e.type;typeof n==`string`?n!==`null`&&(e.type=[n,`null`]):isArray(n)?n.includes(`null`)||(e.type=[...n,`null`]):isArray(e.enum)&&!e.enum.includes(null)&&(e.enum=[...e.enum,null])}function normalizeSchemaAnnotations(e){let t=e.type;if(typeof t==`string`||isArray(t))for(let n of[`default`,`example`])n in e&&!matchesSchemaType(e[n],t)&&delete e[n]}function matchesSchemaType(e,t){return(typeof t==`string`?[t]:t).some(t=>{switch(t){case`string`:return typeof e==`string`;case`number`:return typeof e==`number`&&Number.isFinite(e);case`integer`:return typeof e==`number`&&Number.isInteger(e);case`boolean`:return typeof e==`boolean`;case`object`:return isObject(e);case`array`:return isArray(e);case`null`:return e===null;default:return!1}})}function resolveRef(e,t){if(!t.startsWith(`#/`))return;let n=t.slice(2).split(`/`).map(e=>e.replace(/~1/g,`/`).replace(/~0/g,`~`)),r=e;for(let e of n){if(!isObject(r))return;r=r[e]}return r}function isArray(e){return Array.isArray(e)}export{buildInputSchema,createSchemaConverter,deref,isArray};
@@ -39,8 +39,8 @@ export declare function installLocalDevCapabilityEnvironment(input: {
39
39
  readonly serverUrl: string;
40
40
  }): () => void;
41
41
  /**
42
- * Seeds the inherited dev-TUI hint only when the dev host signed a loopback
43
- * peer address. Client-supplied address headers cannot create that hint.
42
+ * Seeds the inherited dev-TUI hint only when the dev host signed a peer
43
+ * address on this machine. Client-supplied address headers cannot create that hint.
44
44
  */
45
45
  export declare function withLocalDevRequestScope<T>(request: Request, callback: () => Promise<T>): Promise<T>;
46
46
  /**
@@ -1 +1 @@
1
- import{randomUUID}from"node:crypto";import{ContextContainer,contextStorage}from"#context/container.js";import{isLoopbackHostname}from"#shared/network-address.js";import{resumeDevelopmentRuntimeArtifacts,suspendDevelopmentRuntimeArtifacts}from"#services/dev-client/runtime-artifacts.js";import{DEVELOPMENT_WORKFLOW_SECRET_ENV}from"#internal/workflow/development-world-protocol.js";import{DEVELOPMENT_CLIENT_ADDRESS_SIGNATURE_HEADER,isTrustedDevelopmentClientAddress,readTrustedDevelopmentClientAddress}from"#internal/nitro/dev-client-address.js";const LOCAL_DEV_APP_ROOT_ENV=`EVE_DEV_APP_ROOT`,LOCAL_DEV_CONTROL_URL_ENV=`EVE_DEV_CONTROL_URL`,LOCAL_DEV_INTERACTIVE_CLIENT_HEADER=`x-eve-dev-interactive-client`;function installLocalDevCapabilityEnvironment(e){let t=process.env[LOCAL_DEV_APP_ROOT_ENV],n=process.env[LOCAL_DEV_CONTROL_URL_ENV];return process.env[LOCAL_DEV_APP_ROOT_ENV]=e.appRoot,process.env[LOCAL_DEV_CONTROL_URL_ENV]=new URL(e.serverUrl).origin,()=>{restore(LOCAL_DEV_APP_ROOT_ENV,t),restore(LOCAL_DEV_CONTROL_URL_ENV,n)}}async function withLocalDevRequestScope(e,t){let n=process.env[DEVELOPMENT_WORKFLOW_SECRET_ENV],r=readTrustedDevelopmentClientAddress(e.headers,n),i=e.headers.get(DEVELOPMENT_CLIENT_ADDRESS_SIGNATURE_HEADER);return r===void 0||i===null||!isLoopbackHostname(r)?await contextStorage.run(new ContextContainer({localDevRequest:void 0}),t):await contextStorage.run(new ContextContainer({localDevRequest:{address:r,interactiveClient:e.headers.get(LOCAL_DEV_INTERACTIVE_CLIENT_HEADER)===`1`,signature:i}}),t)}function getLocalDevCapability(e=process.env){let t=e[LOCAL_DEV_APP_ROOT_ENV],n=e[LOCAL_DEV_CONTROL_URL_ENV];if(t===void 0||t===``||n===void 0||n===``)return;let r=contextStorage.getStore()?.localDevRequest;return{appRoot:t,interactiveClient:r!==void 0&&typeof r.address==`string`&&typeof r.signature==`string`&&typeof r.interactiveClient==`boolean`&&isLoopbackHostname(r.address)&&isTrustedDevelopmentClientAddress(r.address,r.signature,process.env[DEVELOPMENT_WORKFLOW_SECRET_ENV])?r.interactiveClient:!1,async withSuspendedSource(e){let t=randomUUID();if(!await suspendDevelopmentRuntimeArtifacts({leaseId:t,serverUrl:n}))throw Error(`Could not pause the eve development server. Its authored-source watcher must be suspended before the authored tree is modified.`);let r;try{r={ok:!0,value:await e()}}catch(e){r={error:e,ok:!1}}if(await resumeDevelopmentRuntimeArtifacts({leaseId:t,serverUrl:n})===void 0&&await resumeDevelopmentRuntimeArtifacts({leaseId:t,serverUrl:n})===void 0)throw Error(`Could not resume the eve development server after modifying the authored tree. Restart eve dev before making further source changes.`,r.ok?void 0:{cause:r.error});if(!r.ok)throw r.error;return r.value}}}function restore(e,t){t===void 0?delete process.env[e]:process.env[e]=t}export{LOCAL_DEV_INTERACTIVE_CLIENT_HEADER,getLocalDevCapability,installLocalDevCapabilityEnvironment,withLocalDevRequestScope};
1
+ import{randomUUID}from"node:crypto";import{ContextContainer,contextStorage}from"#context/container.js";import{resumeDevelopmentRuntimeArtifacts,suspendDevelopmentRuntimeArtifacts}from"#services/dev-client/runtime-artifacts.js";import{DEVELOPMENT_WORKFLOW_SECRET_ENV}from"#internal/workflow/development-world-protocol.js";import{DEVELOPMENT_CLIENT_ADDRESS_SIGNATURE_HEADER,isLocalMachineAddress,isTrustedDevelopmentClientAddress,readTrustedDevelopmentClientAddress}from"#internal/nitro/dev-client-address.js";const LOCAL_DEV_APP_ROOT_ENV=`EVE_DEV_APP_ROOT`,LOCAL_DEV_CONTROL_URL_ENV=`EVE_DEV_CONTROL_URL`,LOCAL_DEV_INTERACTIVE_CLIENT_HEADER=`x-eve-dev-interactive-client`;function installLocalDevCapabilityEnvironment(e){let t=process.env[LOCAL_DEV_APP_ROOT_ENV],n=process.env[LOCAL_DEV_CONTROL_URL_ENV];return process.env[LOCAL_DEV_APP_ROOT_ENV]=e.appRoot,process.env[LOCAL_DEV_CONTROL_URL_ENV]=new URL(e.serverUrl).origin,()=>{restore(LOCAL_DEV_APP_ROOT_ENV,t),restore(LOCAL_DEV_CONTROL_URL_ENV,n)}}async function withLocalDevRequestScope(e,t){let n=process.env[DEVELOPMENT_WORKFLOW_SECRET_ENV],r=readTrustedDevelopmentClientAddress(e.headers,n),i=e.headers.get(DEVELOPMENT_CLIENT_ADDRESS_SIGNATURE_HEADER);return r===void 0||i===null||!isLocalMachineAddress(r)?await contextStorage.run(new ContextContainer({localDevRequest:void 0}),t):await contextStorage.run(new ContextContainer({localDevRequest:{address:r,interactiveClient:e.headers.get(LOCAL_DEV_INTERACTIVE_CLIENT_HEADER)===`1`,signature:i}}),t)}function getLocalDevCapability(e=process.env){let t=e[LOCAL_DEV_APP_ROOT_ENV],n=e[LOCAL_DEV_CONTROL_URL_ENV];if(t===void 0||t===``||n===void 0||n===``)return;let r=contextStorage.getStore()?.localDevRequest;return{appRoot:t,interactiveClient:r!==void 0&&typeof r.address==`string`&&typeof r.signature==`string`&&typeof r.interactiveClient==`boolean`&&isLocalMachineAddress(r.address)&&isTrustedDevelopmentClientAddress(r.address,r.signature,process.env[DEVELOPMENT_WORKFLOW_SECRET_ENV])?r.interactiveClient:!1,async withSuspendedSource(e){let t=randomUUID();if(!await suspendDevelopmentRuntimeArtifacts({leaseId:t,serverUrl:n}))throw Error(`Could not pause the eve development server. Its authored-source watcher must be suspended before the authored tree is modified.`);let r;try{r={ok:!0,value:await e()}}catch(e){r={error:e,ok:!1}}if(await resumeDevelopmentRuntimeArtifacts({leaseId:t,serverUrl:n})===void 0&&await resumeDevelopmentRuntimeArtifacts({leaseId:t,serverUrl:n})===void 0)throw Error(`Could not resume the eve development server after modifying the authored tree. Restart eve dev before making further source changes.`,r.ok?void 0:{cause:r.error});if(!r.ok)throw r.error;return r.value}}}function restore(e,t){t===void 0?delete process.env[e]:process.env[e]=t}export{LOCAL_DEV_INTERACTIVE_CLIENT_HEADER,getLocalDevCapability,installLocalDevCapabilityEnvironment,withLocalDevRequestScope};
@@ -1 +1 @@
1
- async function agentToolServeWorkflow(e,t){"use workflow";let n=t.agent(t.toolName),r=sendToAgent(n,await e()),i=e();for(;;){let a=await nextCallOrResult(i,r);if(a.kind===`call`){r=await forwardCall(n,r,a.call),i=e();continue}if(!r.signal.aborted){if(a.result.status===`failed`)throw Error(`The agent's turn failed: ${a.result.error?.message??`no reason given`}\nThis task has ended; to retry, call ${t.toolName} without taskId.`);let o=e();if(o!==i){r=sendToAgent(n,await i),i=o;continue}t.reply(a.result.message??``)}r=sendToAgent(n,await i),i=e()}}async function agentWithModelServeWorkflow(e,t){"use workflow";let n=await e(),r=n.input.model.trim();if(r===``)throw TypeError(`agent model must not be empty.`);let i=t.agent(`agent`,{model:r}),a=sendToModelAgent(i,n,r),o=e();for(;;){let n=await nextModelCallOrResult(o,a);if(n.kind===`call`){a=await forwardModelCall(i,a,n.call,r),o=e();continue}if(!a.signal.aborted){if(n.result.status===`failed`)throw Error(`The agent's turn failed: ${n.result.error?.message??`no reason given`}\nThis task has ended; to retry, call ${t.toolName} without taskId.`);let s=e();if(s!==o){a=sendToModelAgent(i,await o,r),o=s;continue}t.reply(n.result.message??``)}a=sendToModelAgent(i,await o,r),o=e()}}function sendToAgent(e,t){return{result:e.send(t.input.message,{signal:t.abortSignal}).then(e=>e.result()),signal:t.abortSignal}}function sendToModelAgent(e,t,n){if(t.input.model!==n)throw Error(`An agent task keeps the model it started with. This task has ended; start a new task to use another model.`);return{result:e.send(t.input.message,{signal:t.abortSignal}).then(e=>e.result()),signal:t.abortSignal}}async function nextCallOrResult(e,t){return await Promise.race([t.result.then(e=>({kind:`result`,result:e})),e.then(e=>({call:e,kind:`call`}))])}async function nextModelCallOrResult(e,t){return await Promise.race([t.result.then(e=>({kind:`result`,result:e})),e.then(e=>({call:e,kind:`call`}))])}async function forwardCall(e,t,n){return t.signal.aborted&&await t.result.catch(()=>void 0),sendToAgent(e,n)}async function forwardModelCall(e,t,n,r){return t.signal.aborted&&await t.result.catch(()=>void 0),sendToModelAgent(e,n,r)}agentToolServeWorkflow.workflowId=`workflow//eve//agentToolServeWorkflow`,agentWithModelServeWorkflow.workflowId=`workflow//eve@0.83.2//agentWithModelServeWorkflow`;export{agentToolServeWorkflow,agentWithModelServeWorkflow};
1
+ async function agentToolServeWorkflow(e,t){"use workflow";let n=t.agent(t.toolName),r=sendToAgent(n,await e()),i=e();for(;;){let a=await nextCallOrResult(i,r);if(a.kind===`call`){r=await forwardCall(n,r,a.call),i=e();continue}if(!r.signal.aborted){if(a.result.status===`failed`)throw Error(`The agent's turn failed: ${a.result.error?.message??`no reason given`}\nThis task has ended; to retry, call ${t.toolName} without taskId.`);let o=e();if(o!==i){r=sendToAgent(n,await i),i=o;continue}t.reply(a.result.message??``)}r=sendToAgent(n,await i),i=e()}}async function agentWithModelServeWorkflow(e,t){"use workflow";let n=await e(),r=n.input.model.trim();if(r===``)throw TypeError(`agent model must not be empty.`);let i=t.agent(`agent`,{model:r}),a=sendToModelAgent(i,n,r),o=e();for(;;){let n=await nextModelCallOrResult(o,a);if(n.kind===`call`){a=await forwardModelCall(i,a,n.call,r),o=e();continue}if(!a.signal.aborted){if(n.result.status===`failed`)throw Error(`The agent's turn failed: ${n.result.error?.message??`no reason given`}\nThis task has ended; to retry, call ${t.toolName} without taskId.`);let s=e();if(s!==o){a=sendToModelAgent(i,await o,r),o=s;continue}t.reply(n.result.message??``)}a=sendToModelAgent(i,await o,r),o=e()}}function sendToAgent(e,t){return{result:e.send(t.input.message,{signal:t.abortSignal}).then(e=>e.result()),signal:t.abortSignal}}function sendToModelAgent(e,t,n){if(t.input.model!==n)throw Error(`An agent task keeps the model it started with. This task has ended; start a new task to use another model.`);return{result:e.send(t.input.message,{signal:t.abortSignal}).then(e=>e.result()),signal:t.abortSignal}}async function nextCallOrResult(e,t){return await Promise.race([t.result.then(e=>({kind:`result`,result:e})),e.then(e=>({call:e,kind:`call`}))])}async function nextModelCallOrResult(e,t){return await Promise.race([t.result.then(e=>({kind:`result`,result:e})),e.then(e=>({call:e,kind:`call`}))])}async function forwardCall(e,t,n){return t.signal.aborted&&await t.result.catch(()=>void 0),sendToAgent(e,n)}async function forwardModelCall(e,t,n,r){return t.signal.aborted&&await t.result.catch(()=>void 0),sendToModelAgent(e,n,r)}agentToolServeWorkflow.workflowId=`workflow//eve//agentToolServeWorkflow`,agentWithModelServeWorkflow.workflowId=`workflow//eve@0.83.3//agentWithModelServeWorkflow`;export{agentToolServeWorkflow,agentWithModelServeWorkflow};
@@ -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.83.2`,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.83.3`,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__",
@@ -396,6 +396,11 @@ export interface ConnectionToolMetadata {
396
396
  readonly description: string;
397
397
  readonly inputSchema: Record<string, unknown>;
398
398
  readonly name: string;
399
+ /**
400
+ * The OpenAPI `operationId` the tool was generated from. The tool name is a
401
+ * sanitized form of it, so connection filters match both.
402
+ */
403
+ readonly operationId?: string;
399
404
  readonly outputSchema?: Record<string, unknown>;
400
405
  }
401
406
  /** Per-call options for {@link ConnectionClient.executeTool}. */
@@ -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-ZY7NQ2VW.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-BE2_zd5q.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-ZY7NQ2VW.js";
1
+ import { t as useEveAgent } from "../chunks/use-eve-agent-BE2_zd5q.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.83.2//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.83.3//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.83.2//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.83.3//executeSleepTool`;export{executeSleepTool};
@@ -104,3 +104,5 @@ export declare const UNSPECIFIED_INPUT_SCHEMA: ToolSchema;
104
104
  */
105
105
  export declare function toModelSchema(schema: FlexibleSchema, direction: SchemaDirection): FlexibleSchema;
106
106
  export declare function toModelSchema(schema: FlexibleSchema | undefined, direction: SchemaDirection): FlexibleSchema | undefined;
107
+ /** Yields a subschema, then each local `$ref` target it chains through. */
108
+ export declare function followRefs(root: JsonObject, schema: unknown): Generator<Record<string, unknown>>;
@@ -1 +1 @@
1
- import{TypeValidationError,asSchema,jsonSchema}from"ai";import{isObject}from"#shared/guards.js";import{toErrorMessage}from"#shared/errors.js";import{parseJsonObject}from"#shared/json.js";import{emitJsonSchema,getStandardSchemaProperties,readJsonSchemaEmitter,serializeOutputSchema}from"#tools/schema-emission.js";import{Validator}from"#compiled/@cfworker/json-schema/index.js";function toInputSchema(e){return toSchema(e,`input`)}function toOutputSchema(e){return toSchema(e,`output`)}function serializeInputSchema(e){return serializeSchema(e,`input`)}function serializeModelInputSchema(e){let t=toSchema(e,`input`);return t==null?t:toModelJsonSchema(t,`input`)}function isToolSchema(e){let t=getStandardSchemaProperties(e);if(t===void 0)return!1;let n=t.jsonSchema;return typeof t.validate==`function`&&typeof n==`object`&&!!n&&typeof n.input==`function`&&typeof n.output==`function`}function defineJsonSchema(e,t){let emit=()=>structuredClone(e),n={"~standard":{version:1,vendor:`eve`,validate:createJsonSchemaValidator(e,t),jsonSchema:{input:emit,output:emit}}};return plainJsonSchemas.add(n),n}const plainJsonSchemas=new WeakSet;function refineJsonSchema(e,t){let n=defineJsonSchema(e),r={"~standard":{...n[`~standard`],validate:async e=>{let r=await n[`~standard`].validate(e);return r.issues===void 0?await t(r.value):r}}};return plainJsonSchemas.add(r),r}function withOptionalStringProperty(e,t){let emit=()=>addOptionalStringProperty(serializeInputSchema(e),t),n={"~standard":{version:1,vendor:`eve`,validate:n=>validateWithProperty(e,t.name,n),jsonSchema:{input:emit,output:emit}}};return plainJsonSchemas.has(e)&&plainJsonSchemas.add(n),n}function addOptionalStringProperty(e,t){let n=isObject(e.properties)?e.properties:{};return{...e,type:e.type??`object`,properties:{...n,[t.name]:{description:t.description,type:`string`}}}}async function validateWithProperty(e,t,n){if(!isObject(n)||!(t in n))return await e[`~standard`].validate(n);let{[t]:r,...i}=n;if(typeof r!=`string`)return{issues:[{message:`Expected "${t}" to be a string.`,path:[t]}]};let a=await e[`~standard`].validate(i);return a.issues!==void 0||!isObject(a.value)?a:{value:{...a.value,[t]:r}}}const UNSPECIFIED_INPUT_SCHEMA=defineJsonSchema({});function toModelSchema(e,t){if(e===void 0||typeof e==`function`||!(`~standard`in e))return e;let n=e;return jsonSchema(()=>toModelJsonSchema(n,t),{validate:async e=>{let t=await n[`~standard`].validate(e);return t.issues===void 0?{success:!0,value:t.value}:{success:!1,error:new TypeValidationError({value:e,cause:t.issues})}}})}function toModelJsonSchema(e,t){let n=serializeSchema(e,t);return plainJsonSchemas.has(e)?n:closeObjectSchemas(n)}function closeObjectSchemas(e){if(!isObject(e))return e;let t={...e},{type:n}=t;(n===`object`||Array.isArray(n)&&n.includes(`object`))&&(t.additionalProperties=isObject(t.additionalProperties)?closeObjectSchemas(t.additionalProperties):!1,isObject(t.properties)&&(t.properties=mapValues(t.properties,closeObjectSchemas))),Array.isArray(t.items)?t.items=t.items.map(closeObjectSchemas):isObject(t.items)&&(t.items=closeObjectSchemas(t.items));for(let e of[`allOf`,`anyOf`,`oneOf`]){let n=t[e];Array.isArray(n)&&(t[e]=n.map(closeObjectSchemas))}return isObject(t.definitions)&&(t.definitions=mapValues(t.definitions,closeObjectSchemas)),t}function mapValues(e,t){return Object.fromEntries(Object.entries(e).map(([e,n])=>[e,t(n)]))}function toSchema(e,t){return e==null||isToolSchema(e)?e:defineJsonSchema(toJsonObject(e,t))}function serializeSchema(e,t){return e==null?e:toJsonObject(e,t)}function toJsonObject(e,t){if(t===`input`&&isLegacyZodSchema(e)){let t=asSchema(e),{$schema:n,...r}=parseJsonObject(t.jsonSchema);return r}return emitJsonSchema(e,t)}function isLegacyZodSchema(e){let t=getStandardSchemaProperties(e);return t!==void 0&&t.vendor===`zod`&&readJsonSchemaEmitter(t,`input`)===void 0}function createJsonSchemaValidator(e,t){let n,r=!1,passThrough=(e,t)=>(r||(r=!0,console.warn(`[eve] Tool schema cannot validate values locally; passing them through unvalidated: ${t}`)),{value:e});return r=>{if(n===void 0){let t=buildValidator(e);if(typeof t==`string`)return n=null,passThrough(r,t);n=t}if(n===null)return{value:r};let i;try{i=n.validate(r)}catch(e){return r===void 0?{issues:[{message:`Expected a JSON value.`}]}:passThrough(r,toErrorMessage(e))}if(!i.valid)return{issues:toIssues(i.errors)};let a=applyDefaults(e,e,r),o=t?.(a);return o===void 0?{value:a}:{issues:[{message:o}]}}}function applyDefaults(e,t,n){let r=n;for(let n of followRefs(e,t)){let{items:t,properties:i}=n;if(isObject(r)&&isObject(i))r=fillProperties(e,i,r);else if(Array.isArray(r)&&isObject(t)){let n=r,i=n.map(n=>applyDefaults(e,t,n));i.some((e,t)=>e!==n[t])&&(r=i)}}return r}function fillProperties(e,t,n){let r=n;for(let[i,a]of Object.entries(t)){let t=Object.hasOwn(n,i)?n[i]:void 0,o=t===void 0?findDefault(e,a):applyDefaults(e,a,t);o!==t&&(r===n&&(r={...n}),r[i]=o)}return r}function findDefault(e,t){for(let n of followRefs(e,t))if(`default`in n)return structuredClone(n.default)}function*followRefs(e,t){let n=new Set,r=t;for(;isObject(r)&&!n.has(r);)n.add(r),yield r,r=resolveLocalRef(e,r.$ref)}function resolveLocalRef(e,t){if(typeof t!=`string`||t!==`#`&&!t.startsWith(`#/`))return;let n=e;for(let e of decodePointer(t)){if(typeof n!=`object`||!n||!Object.hasOwn(n,e))return;n=n[e]}return n}function buildValidator(e){try{let t=structuredClone(e);return prepareForValidation(t)??new Validator(t,`2020-12`,!1)}catch(e){return toErrorMessage(e)}}const JSON_TYPES=new Set([`array`,`boolean`,`integer`,`null`,`number`,`object`,`string`]),EXCLUSIVE_BOUNDS=[[`exclusiveMinimum`,`minimum`],[`exclusiveMaximum`,`maximum`]],SUBSCHEMA_KEYWORDS=[`additionalItems`,`additionalProperties`,`contains`,`else`,`if`,`not`,`propertyNames`,`then`,`unevaluatedItems`,`unevaluatedProperties`],SUBSCHEMA_LIST_KEYWORDS=[`allOf`,`anyOf`,`oneOf`,`prefixItems`],SUBSCHEMA_MAP_KEYWORDS=[`$defs`,`definitions`,`dependencies`,`dependentSchemas`,`patternProperties`,`properties`];function prepareForValidation(e){if(typeof e==`boolean`)return;if(typeof e!=`object`||!e||Array.isArray(e))return`a subschema is neither an object nor a boolean`;let t=e;delete t.format;for(let[e,n]of EXCLUSIVE_BOUNDS)typeof t[e]==`boolean`&&(t[e]&&typeof t[n]==`number`?(t[e]=t[n],delete t[n]):delete t[e]);let{enum:n,pattern:r,required:i,type:a}=t;if(a!==void 0&&!(Array.isArray(a)?a.every(isJsonType):isJsonType(a)))return`unsupported type ${JSON.stringify(a)}`;if(n!==void 0&&!Array.isArray(n))return"`enum` is not an array";if(i!==void 0&&!(Array.isArray(i)&&i.every(e=>typeof e==`string`)))return"`required` is not an array of strings";if(r!==void 0&&!isRegExpSource(r))return`invalid pattern ${JSON.stringify(r)}`;for(let e of SUBSCHEMA_KEYWORDS)if(e in t){let n=prepareForValidation(t[e]);if(n!==void 0)return n}let o=t.items;for(let e of Array.isArray(o)?o:o===void 0?[]:[o]){let t=prepareForValidation(e);if(t!==void 0)return t}for(let e of SUBSCHEMA_LIST_KEYWORDS){let n=t[e];if(n!==void 0){if(!Array.isArray(n))return`\`${e}\` is not an array`;for(let e of n){let t=prepareForValidation(e);if(t!==void 0)return t}}}for(let e of SUBSCHEMA_MAP_KEYWORDS){let n=t[e];if(n!==void 0){if(typeof n!=`object`||!n||Array.isArray(n))return`\`${e}\` is not an object`;for(let[t,r]of Object.entries(n)){if(e===`patternProperties`&&!isRegExpSource(t))return`invalid pattern ${JSON.stringify(t)}`;if(e===`dependencies`&&Array.isArray(r))continue;let n=prepareForValidation(r);if(n!==void 0)return n}}}}function isJsonType(e){return typeof e==`string`&&JSON_TYPES.has(e)}function isRegExpSource(e){if(typeof e!=`string`)return!1;try{return new RegExp(e,`u`),!0}catch{return!1}}const CLOSED_OBJECT_KEYWORD=/\/(?:additional|unevaluated)Properties$/;function toIssues(e){let t=[];for(let n=0;n<e.length;n++){let r=e[n],i=e[n+1];if(CLOSED_OBJECT_KEYWORD.test(r.keywordLocation)&&i?.keyword===`false`){let e=decodePointer(i.instanceLocation).at(-1);t.push({keyword:`false`,location:i.instanceLocation,message:`Unrecognized key: ${JSON.stringify(e)}`,object:r.instanceLocation}),n++}else t.push({keyword:r.keyword,location:r.instanceLocation,message:r.error})}let n=t.filter(e=>e.object===void 0||!t.some(t=>t.object===void 0&&(t.location===e.location||t.location.startsWith(`${e.location}/`))));return n.filter((e,t)=>{let r=n[t+1];return r===void 0?!0:r.location.startsWith(`${e.location}/`)?!1:e.keyword!==`$ref`||r.location!==e.location}).map(({location:e,message:t,object:n})=>{let r=decodePointer(n??e);return r.length===0?{message:t}:{message:t,path:r}})}function decodePointer(e){return e.split(`/`).slice(1).map(e=>{let t=e;try{t=decodeURIComponent(e)}catch{}return t.replaceAll(`~1`,`/`).replaceAll(`~0`,`~`)})}export{UNSPECIFIED_INPUT_SCHEMA,defineJsonSchema,isToolSchema,refineJsonSchema,serializeInputSchema,serializeModelInputSchema,serializeOutputSchema,toInputSchema,toModelSchema,toOutputSchema,withOptionalStringProperty};
1
+ import{TypeValidationError,asSchema,jsonSchema}from"ai";import{isObject}from"#shared/guards.js";import{toErrorMessage}from"#shared/errors.js";import{parseJsonObject}from"#shared/json.js";import{emitJsonSchema,getStandardSchemaProperties,readJsonSchemaEmitter,serializeOutputSchema}from"#tools/schema-emission.js";import{Validator}from"#compiled/@cfworker/json-schema/index.js";function toInputSchema(e){return toSchema(e,`input`)}function toOutputSchema(e){return toSchema(e,`output`)}function serializeInputSchema(e){return serializeSchema(e,`input`)}function serializeModelInputSchema(e){let t=toSchema(e,`input`);return t==null?t:toModelJsonSchema(t,`input`)}function isToolSchema(e){let t=getStandardSchemaProperties(e);if(t===void 0)return!1;let n=t.jsonSchema;return typeof t.validate==`function`&&typeof n==`object`&&!!n&&typeof n.input==`function`&&typeof n.output==`function`}function defineJsonSchema(e,t){let emit=()=>structuredClone(e),n={"~standard":{version:1,vendor:`eve`,validate:createJsonSchemaValidator(e,t),jsonSchema:{input:emit,output:emit}}};return plainJsonSchemas.add(n),n}const plainJsonSchemas=new WeakSet;function refineJsonSchema(e,t){let n=defineJsonSchema(e),r={"~standard":{...n[`~standard`],validate:async e=>{let r=await n[`~standard`].validate(e);return r.issues===void 0?await t(r.value):r}}};return plainJsonSchemas.add(r),r}function withOptionalStringProperty(e,t){let emit=()=>addOptionalStringProperty(serializeInputSchema(e),t),n={"~standard":{version:1,vendor:`eve`,validate:n=>validateWithProperty(e,t.name,n),jsonSchema:{input:emit,output:emit}}};return plainJsonSchemas.has(e)&&plainJsonSchemas.add(n),n}function addOptionalStringProperty(e,t){let n=isObject(e.properties)?e.properties:{};return{...e,type:e.type??`object`,properties:{...n,[t.name]:{description:t.description,type:`string`}}}}async function validateWithProperty(e,t,n){if(!isObject(n)||!(t in n))return await e[`~standard`].validate(n);let{[t]:r,...i}=n;if(typeof r!=`string`)return{issues:[{message:`Expected "${t}" to be a string.`,path:[t]}]};let a=await e[`~standard`].validate(i);return a.issues!==void 0||!isObject(a.value)?a:{value:{...a.value,[t]:r}}}const UNSPECIFIED_INPUT_SCHEMA=defineJsonSchema({});function toModelSchema(e,t){if(e===void 0||typeof e==`function`||!(`~standard`in e))return e;let n=e;return jsonSchema(()=>toModelJsonSchema(n,t),{validate:async e=>{let t=await n[`~standard`].validate(e);return t.issues===void 0?{success:!0,value:t.value}:{success:!1,error:new TypeValidationError({value:e,cause:t.issues})}}})}function toModelJsonSchema(e,t){let n=serializeSchema(e,t);return plainJsonSchemas.has(e)?n:closeObjectSchemas(n)}function closeObjectSchemas(e){if(!isObject(e))return e;let t={...e},{type:n}=t;(n===`object`||Array.isArray(n)&&n.includes(`object`))&&(t.additionalProperties=isObject(t.additionalProperties)?closeObjectSchemas(t.additionalProperties):!1,isObject(t.properties)&&(t.properties=mapValues(t.properties,closeObjectSchemas))),Array.isArray(t.items)?t.items=t.items.map(closeObjectSchemas):isObject(t.items)&&(t.items=closeObjectSchemas(t.items));for(let e of[`allOf`,`anyOf`,`oneOf`]){let n=t[e];Array.isArray(n)&&(t[e]=n.map(closeObjectSchemas))}return isObject(t.definitions)&&(t.definitions=mapValues(t.definitions,closeObjectSchemas)),t}function mapValues(e,t){return Object.fromEntries(Object.entries(e).map(([e,n])=>[e,t(n)]))}function toSchema(e,t){return e==null||isToolSchema(e)?e:defineJsonSchema(toJsonObject(e,t))}function serializeSchema(e,t){return e==null?e:toJsonObject(e,t)}function toJsonObject(e,t){if(t===`input`&&isLegacyZodSchema(e)){let t=asSchema(e),{$schema:n,...r}=parseJsonObject(t.jsonSchema);return r}return emitJsonSchema(e,t)}function isLegacyZodSchema(e){let t=getStandardSchemaProperties(e);return t!==void 0&&t.vendor===`zod`&&readJsonSchemaEmitter(t,`input`)===void 0}function createJsonSchemaValidator(e,t){let n,r=!1,passThrough=(e,t)=>(r||(r=!0,console.warn(`[eve] Tool schema cannot validate values locally; passing them through unvalidated: ${t}`)),{value:e});return r=>{if(n===void 0){let t=buildValidator(e);if(typeof t==`string`)return n=null,passThrough(r,t);n=t}if(n===null)return{value:r};let i;try{i=n.validate(r)}catch(e){return r===void 0?{issues:[{message:`Expected a JSON value.`}]}:passThrough(r,toErrorMessage(e))}if(!i.valid)return{issues:toIssues(i.errors)};let a=applyDefaults(e,e,r),o=t?.(a);return o===void 0?{value:a}:{issues:[{message:o}]}}}function applyDefaults(e,t,n){let r=n;for(let n of followRefs(e,t)){let{items:t,properties:i}=n;if(isObject(r)&&isObject(i))r=fillProperties(e,i,r);else if(Array.isArray(r)&&isObject(t)){let n=r,i=n.map(n=>applyDefaults(e,t,n));i.some((e,t)=>e!==n[t])&&(r=i)}}return r}function fillProperties(e,t,n){let r=n;for(let[i,a]of Object.entries(t)){let t=Object.hasOwn(n,i)?n[i]:void 0,o=t===void 0?findDefault(e,a):applyDefaults(e,a,t);o!==t&&(r===n&&(r={...n}),r[i]=o)}return r}function findDefault(e,t){for(let n of followRefs(e,t))if(`default`in n)return structuredClone(n.default)}function*followRefs(e,t){let n=new Set,r=t;for(;isObject(r)&&!n.has(r);)n.add(r),yield r,r=resolveLocalRef(e,r.$ref)}function resolveLocalRef(e,t){if(typeof t!=`string`||t!==`#`&&!t.startsWith(`#/`))return;let n=e;for(let e of decodePointer(t)){if(typeof n!=`object`||!n||!Object.hasOwn(n,e))return;n=n[e]}return n}function buildValidator(e){try{let t=structuredClone(e);return prepareForValidation(t)??new Validator(t,`2020-12`,!1)}catch(e){return toErrorMessage(e)}}const JSON_TYPES=new Set([`array`,`boolean`,`integer`,`null`,`number`,`object`,`string`]),EXCLUSIVE_BOUNDS=[[`exclusiveMinimum`,`minimum`],[`exclusiveMaximum`,`maximum`]],SUBSCHEMA_KEYWORDS=[`additionalItems`,`additionalProperties`,`contains`,`else`,`if`,`not`,`propertyNames`,`then`,`unevaluatedItems`,`unevaluatedProperties`],SUBSCHEMA_LIST_KEYWORDS=[`allOf`,`anyOf`,`oneOf`,`prefixItems`],SUBSCHEMA_MAP_KEYWORDS=[`$defs`,`definitions`,`dependencies`,`dependentSchemas`,`patternProperties`,`properties`];function prepareForValidation(e){if(typeof e==`boolean`)return;if(typeof e!=`object`||!e||Array.isArray(e))return`a subschema is neither an object nor a boolean`;let t=e;delete t.format;for(let[e,n]of EXCLUSIVE_BOUNDS)typeof t[e]==`boolean`&&(t[e]&&typeof t[n]==`number`?(t[e]=t[n],delete t[n]):delete t[e]);let{enum:n,pattern:r,required:i,type:a}=t;if(a!==void 0&&!(Array.isArray(a)?a.every(isJsonType):isJsonType(a)))return`unsupported type ${JSON.stringify(a)}`;if(n!==void 0&&!Array.isArray(n))return"`enum` is not an array";if(i!==void 0&&!(Array.isArray(i)&&i.every(e=>typeof e==`string`)))return"`required` is not an array of strings";if(r!==void 0&&!isRegExpSource(r))return`invalid pattern ${JSON.stringify(r)}`;for(let e of SUBSCHEMA_KEYWORDS)if(e in t){let n=prepareForValidation(t[e]);if(n!==void 0)return n}let o=t.items;for(let e of Array.isArray(o)?o:o===void 0?[]:[o]){let t=prepareForValidation(e);if(t!==void 0)return t}for(let e of SUBSCHEMA_LIST_KEYWORDS){let n=t[e];if(n!==void 0){if(!Array.isArray(n))return`\`${e}\` is not an array`;for(let e of n){let t=prepareForValidation(e);if(t!==void 0)return t}}}for(let e of SUBSCHEMA_MAP_KEYWORDS){let n=t[e];if(n!==void 0){if(typeof n!=`object`||!n||Array.isArray(n))return`\`${e}\` is not an object`;for(let[t,r]of Object.entries(n)){if(e===`patternProperties`&&!isRegExpSource(t))return`invalid pattern ${JSON.stringify(t)}`;if(e===`dependencies`&&Array.isArray(r))continue;let n=prepareForValidation(r);if(n!==void 0)return n}}}}function isJsonType(e){return typeof e==`string`&&JSON_TYPES.has(e)}function isRegExpSource(e){if(typeof e!=`string`)return!1;try{return new RegExp(e,`u`),!0}catch{return!1}}const CLOSED_OBJECT_KEYWORD=/\/(?:additional|unevaluated)Properties$/;function toIssues(e){let t=[];for(let n=0;n<e.length;n++){let r=e[n],i=e[n+1];if(CLOSED_OBJECT_KEYWORD.test(r.keywordLocation)&&i?.keyword===`false`){let e=decodePointer(i.instanceLocation).at(-1);t.push({keyword:`false`,location:i.instanceLocation,message:`Unrecognized key: ${JSON.stringify(e)}`,object:r.instanceLocation}),n++}else t.push({keyword:r.keyword,location:r.instanceLocation,message:r.error})}let n=t.filter(e=>e.object===void 0||!t.some(t=>t.object===void 0&&(t.location===e.location||t.location.startsWith(`${e.location}/`))));return n.filter((e,t)=>{let r=n[t+1];return r===void 0?!0:r.location.startsWith(`${e.location}/`)?!1:e.keyword!==`$ref`||r.location!==e.location}).map(({location:e,message:t,object:n})=>{let r=decodePointer(n??e);return r.length===0?{message:t}:{message:t,path:r}})}function decodePointer(e){return e.split(`/`).slice(1).map(e=>{let t=e;try{t=decodeURIComponent(e)}catch{}return t.replaceAll(`~1`,`/`).replaceAll(`~0`,`~`)})}export{UNSPECIFIED_INPUT_SCHEMA,defineJsonSchema,followRefs,isToolSchema,refineJsonSchema,serializeInputSchema,serializeModelInputSchema,serializeOutputSchema,toInputSchema,toModelSchema,toOutputSchema,withOptionalStringProperty};
@@ -1 +1 @@
1
- import{isObject}from"#shared/guards.js";const MAX_SIGNATURE_LENGTH=4e3,CONSTRAINT_KEYS=[`format`,`pattern`,`minimum`,`maximum`,`exclusiveMinimum`,`exclusiveMaximum`,`minLength`,`maxLength`,`minItems`,`maxItems`,`default`],IDENTIFIER=/^[A-Za-z_$][\w$]*$/u;function renderToolSignature(e){let t=renderSignature(e,!0);if(t.length<=MAX_SIGNATURE_LENGTH)return t;let n=renderSignature(e,!1);return n.length>MAX_SIGNATURE_LENGTH?`${n.slice(0,3997)}...`:n}function renderSignature(e,t){let render=e=>renderType(e,{budget:{remaining:1e3},depth:0,descriptions:t,refs:new Set,root:e}),n=e.inputSchema===void 0?`{}`:render(e.inputSchema),r=e.outputSchema===void 0?`unknown`:render(e.outputSchema);return`${e.name}(input: ${n}): Promise<${r}>`}function renderType(e,t){if(e===!0||!isObject(e)||t.depth>6||t.budget.remaining<=0)return`unknown`;if(--t.budget.remaining,typeof e.$ref==`string`){let n=resolveRef(e.$ref,t);return n===void 0?`unknown`:renderType(n,{...t,refs:new Set([...t.refs,e.$ref])})}if(`const`in e)return literal(e.const);if(Array.isArray(e.enum))return union(e.enum.map(literal));let n=Array.isArray(e.anyOf)?e.anyOf:Array.isArray(e.oneOf)?e.oneOf:void 0;if(n!==void 0)return union(n.map(e=>renderType(e,next(t))));if(Array.isArray(e.allOf))return e.allOf.map(e=>wrap(renderType(e,next(t)))).join(` & `);let r=(Array.isArray(e.type)?e.type:[e.type]).filter(e=>typeof e==`string`).map(n=>renderPrimitive(n,e,t));return r.length>0?union(r):isObject(e.properties)||e.additionalProperties!==void 0?renderObject(e,t):e.items===void 0?`unknown`:renderPrimitive(`array`,e,t)}function renderPrimitive(e,t,n){switch(e){case`string`:return`string`;case`number`:case`integer`:return`number`;case`boolean`:return`boolean`;case`null`:return`null`;case`array`:return`${wrap(renderType(t.items,next(n)))}[]`;case`object`:return renderObject(t,n);default:return`unknown`}}function renderObject(e,t){let n=isObject(e.properties)?e.properties:{},r=new Set(Array.isArray(e.required)?e.required.filter(e=>typeof e==`string`):[]),i=Object.entries(n).map(([e,n])=>{let i=IDENTIFIER.test(e)?e:JSON.stringify(e),a=r.has(e)?``:`?`,o=isObject(n)?propertyComment(n,t.descriptions):``;return`${i}${a}: ${renderType(n,next(t))}${o}`}),a=e.additionalProperties;return isObject(a)&&i.push(`[key: string]: ${renderType(a,next(t))}`),i.length===0?a===!1?`{}`:`Record<string, unknown>`:`{ ${i.join(`; `)} }`}function propertyComment(e,t){let n=[],r=t&&typeof e.description==`string`?e.description.replaceAll(/\s+/gu,` `).replace(/[\s.;,:]+$/u,``).trim():``;r.length>0&&n.push(truncate(r));for(let t of CONSTRAINT_KEYS)e[t]!==void 0&&n.push(`${t}: ${JSON.stringify(e[t])}`);return n.length===0?``:` /* ${n.join(`; `).replaceAll(`*/`,`* /`)} */`}function resolveRef(e,t){if(t.refs.has(e)||!e.startsWith(`#`))return;let n=t.root;for(let t of e.slice(1).split(`/`).filter(Boolean)){if(!isObject(n))return;n=n[t.replaceAll(`~1`,`/`).replaceAll(`~0`,`~`)]}return n}function next(e){return{...e,depth:e.depth+1}}function literal(e){return e===void 0?`undefined`:JSON.stringify(e)}function union(e){let t=[...new Set(e)];return t.length===0?`never`:t.join(` | `)}function wrap(e){return e.includes(` | `)||e.includes(` & `)?`(${e})`:e}function truncate(e){return e.length>120?`${e.slice(0,117)}...`:e}export{renderToolSignature};
1
+ import{isObject}from"#shared/guards.js";const MAX_SIGNATURE_LENGTH=4e3,CONSTRAINT_KEYS=[`format`,`pattern`,`minimum`,`maximum`,`exclusiveMinimum`,`exclusiveMaximum`,`minLength`,`maxLength`,`minItems`,`maxItems`,`default`],IDENTIFIER=/^[A-Za-z_$][\w$]*$/u;function renderToolSignature(e){let t=renderSignature(e,!0);if(t.length<=MAX_SIGNATURE_LENGTH)return t;let n=renderSignature(e,!1);return n.length>MAX_SIGNATURE_LENGTH?`${n.slice(0,3997)}...`:n}function renderSignature(e,t){let render=e=>renderType(e,{budget:{remaining:1e3},depth:0,descriptions:t,refs:new Set,root:e}),n=e.inputSchema===void 0?`{}`:render(e.inputSchema),r=e.outputSchema===void 0?`unknown`:render(e.outputSchema);return`${e.name}(input: ${n}): Promise<${r}>`}function renderType(e,t){if(e===!0||!isObject(e)||t.depth>6||t.budget.remaining<=0)return`unknown`;if(--t.budget.remaining,typeof e.$ref==`string`){let n=resolveRef(e.$ref,t);return n===void 0?`unknown`:renderType(n,{...t,refs:new Set([...t.refs,e.$ref])})}if(`const`in e)return literal(e.const);if(Array.isArray(e.enum))return union(e.enum.map(literal));let n=Array.isArray(e.anyOf)?e.anyOf:Array.isArray(e.oneOf)?e.oneOf:void 0;if(n!==void 0)return union(n.map(e=>renderType(e,next(t))));if(Array.isArray(e.allOf))return e.allOf.map(e=>wrap(renderType(e,next(t)))).join(` & `);let r=(Array.isArray(e.type)?e.type:[e.type]).filter(e=>typeof e==`string`).map(n=>renderPrimitive(n,e,t));return r.length>0?union(r):isObject(e.properties)||e.additionalProperties!==void 0?renderObject(e,t):e.items===void 0?`unknown`:renderPrimitive(`array`,e,t)}function renderPrimitive(e,t,n){switch(e){case`string`:return`string`;case`number`:case`integer`:return`number`;case`boolean`:return`boolean`;case`null`:return`null`;case`array`:return`${wrap(renderType(t.items,next(n)))}[]`;case`object`:return renderObject(t,n);default:return`unknown`}}function renderObject(e,t){let n=isObject(e.properties)?e.properties:{},r=new Set(Array.isArray(e.required)?e.required.filter(e=>typeof e==`string`):[]),i=Object.entries(n).map(([e,n])=>{let i=IDENTIFIER.test(e)?e:JSON.stringify(e),a=r.has(e)?``:`?`,o=isObject(n)?propertyComment(n,t):``;return`${i}${a}: ${renderType(n,next(t))}${o}`}),a=e.additionalProperties;return isObject(a)&&i.push(`[key: string]: ${renderType(a,next(t))}`),i.length===0?a===!1?`{}`:`Record<string, unknown>`:`{ ${i.join(`; `)} }`}function propertyComment(e,t){let n=describedSchema(e,t),r=[],i=t.descriptions&&typeof n.description==`string`?n.description.replaceAll(/\s+/gu,` `).replace(/[\s.;,:]+$/u,``).trim():``;i.length>0&&r.push(truncate(i));for(let e of CONSTRAINT_KEYS)n[e]!==void 0&&r.push(`${e}: ${JSON.stringify(n[e])}`);return r.length===0?``:` /* ${r.join(`; `).replaceAll(`*/`,`* /`)} */`}function describedSchema(e,t){let n=e,r=new Set(t.refs);for(let e=n.$ref;typeof e==`string`&&!r.has(e);e=n.$ref){r.add(e);let i=resolveRef(e,t);if(!isObject(i))break;let{$ref:a,...o}=n;n={...i,...o}}return n}function resolveRef(e,t){if(t.refs.has(e)||!e.startsWith(`#`))return;let n=t.root;for(let t of e.slice(1).split(`/`).filter(Boolean)){if(!isObject(n))return;n=n[t.replaceAll(`~1`,`/`).replaceAll(`~0`,`~`)]}return n}function next(e){return{...e,depth:e.depth+1}}function literal(e){return e===void 0?`undefined`:JSON.stringify(e)}function union(e){let t=[...new Set(e)];return t.length===0?`never`:t.join(` | `)}function wrap(e){return e.includes(` | `)||e.includes(` & `)?`(${e})`:e}function truncate(e){return e.length>120?`${e.slice(0,117)}...`:e}export{renderToolSignature};
@@ -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-DnbG9c7c.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-e8a5vcFO.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-DnbG9c7c.js";
1
+ import { t as useEveAgent } from "../chunks/use-eve-agent-e8a5vcFO.js";
2
2
 
3
3
  export { useEveAgent };
@@ -145,7 +145,7 @@ This policy controls overlapping eve turns. Chat SDK's separate `concurrency` op
145
145
 
146
146
  The default handlers post the agent's reply back to the thread — no `events` override required. Completed assistant messages are posted as markdown (`{ markdown: … }`) so adapters render rich text and email HTML rather than a raw string.
147
147
 
148
- Streaming is on by default: the channel posts an initial message and edits it as tokens arrive (`message.appended`), throttled by `streamingEditIntervalMs` (default `1000`). Set `streaming: false` for surfaces that deliver one message per turn or can't edit sent messages — email and WhatsApp, for example — so the reply posts once on completion instead of editing:
148
+ Streaming is on by default: the channel posts an initial message and edits it as tokens arrive (`message.appended`), throttled by `streamingEditIntervalMs` (default `1000`). On completion it edits the message once more to show the full reply, skipping that edit when the message already shows it. The streamed message is the reply, so the channel never posts the reply a second time: when the final edit fails, it logs the error, posts a short notice with the error id, and tells the model on the next message that the user hasn't seen its reply. Set `streaming: false` for surfaces that deliver one message per turn or can't edit sent messages — email and WhatsApp, for example — so the reply posts once on completion instead of editing:
149
149
 
150
150
  ```ts
151
151
  chatSdkChannel({
@@ -440,7 +440,7 @@ When a final reply still doesn't reach Slack, because the upload fails, Slack re
440
440
 
441
441
  This applies to the turn's final reply only. A failed status update, tool-call narration, or other event is logged and skipped. Delivery failures don't trigger a model retry.
442
442
 
443
- When the model replies while its tasks keep working, that reply posts like any other, and the reply after the results posts as another message. A schedule's session posts only the final reply.
443
+ When the model replies while its tasks keep working, including text it writes before `eve__task_wait` in the same step, that reply posts like any other, and the reply after the results posts as another message. A schedule's session posts only the final reply.
444
444
 
445
445
  Outbound text preserves bare `@` tokens as literal text. To mention a user, embed Slack's `<@USER_ID>` syntax directly or use `channel.thread.mentionUser(userId)`.
446
446
 
@@ -7,7 +7,7 @@ The default harness is eve's built-in agent loop. It manages model calls, compac
7
7
 
8
8
  ## Compaction
9
9
 
10
- The harness keeps a long session from overflowing the model's context window. Before comparing the conversation with `thresholdPercent` (`0.9` by default), it adds the estimated fixed envelope of the checkpoint prompt used for compaction. It then summarizes the older turns and keeps going. The prompt asks the compaction model to distinguish completed progress and decisions from remaining work and to retain the constraints, preferences, data, and references needed to continue. When eve compacts again, it passes the previous checkpoint separately and without the transcript's per-message truncation, then replaces it with the updated checkpoint. The summary uses the active turn model unless you override it. Tune when and how it kicks in under [`compaction`](../agent-config#compaction) in `agent.ts`:
10
+ The harness keeps a long session from overflowing the model's context window. Before comparing the conversation with `thresholdPercent` (`0.9` by default), it adds the estimated fixed envelope of the checkpoint prompt used for compaction. It then summarizes the older turns and keeps going. The prompt asks the compaction model to distinguish completed progress and decisions from remaining work and to retain the constraints, preferences, data, and references needed to continue. When eve compacts again, it passes the previous checkpoint separately and without the transcript's per-message truncation, then replaces it with the updated checkpoint. The summary uses the active turn model unless you override it. After compacting, the harness keeps the most recent messages word for word next to the summary, up to 20,000 tokens (or half of the threshold, if that is smaller), with tool results shortened to 2,000 characters. The current user message is always part of that, so when it alone is larger than the budget the harness keeps only its start and its end, with a note where the middle was cut, and summarizes the cut-out middle with the older turns. If a compaction cannot bring the history under the threshold, the session fails with an error instead of compacting again, and the step is not retried: start a new session or send a smaller message. Tune when and how it kicks in under [`compaction`](../agent-config#compaction) in `agent.ts`:
11
11
 
12
12
  ```ts title="agent/agent.ts"
13
13
  export default defineAgent({
@@ -126,7 +126,7 @@ A call the model makes through [`eve__tool` or `eve__skill`](/docs/concepts/buil
126
126
 
127
127
  Note: consider the privacy, confidentiality, and user-experience implications for displaying, storing, or transmitting reasoning events in your application.
128
128
 
129
- `message.completed` can fire more than once in a turn: the agent often emits interim assistant text before a tool call. To tell tool-call narration from a terminal reply, check `message.completed.data.finishReason`. `step.completed.data.finishReason` mirrors the step outcome, and each step's usage lives on `step.completed`. `session.waiting`, `session.failed`, `session.completed`, and `turn.waiting` carry `data.usage`: the session's running total of its own model calls plus what the agents it delegated to spent. `costUsd` is absent when no model call reported a cost, and compaction calls are not counted.
129
+ `message.completed` can fire more than once in a turn: the agent often emits interim assistant text before a tool call. To tell tool-call narration from a terminal reply, check `message.completed.data.finishReason`. `step.completed.data.finishReason` mirrors the step outcome, and each step's usage lives on `step.completed`. `session.waiting`, `session.failed`, `session.completed`, and `turn.waiting` carry `data.usage`: the session's running total of its own model calls plus what the agents it delegated to spent. The total includes compaction summary calls, which no `step.completed` reports. `costUsd` is absent when no model call reported a cost.
130
130
 
131
131
  A delegated subagent publishes progress on its own child-session stream. When a subagent tool call or a workflow tool's `ctx.agent` opens a session, the parent emits `agent.started` with the call's `callId` and `turnId`, its `taskId` when the call runs as a task, the child's `sessionId`, and a `streamPath` that a client follows with `session.agent(started).stream()`. A subagent tool call is a [task](#task-events) whose `task.started` has `kind: "agent"`: its `task.started` and `task.settled` carry the call, and `task.settled.data.output` is the child's reply. A call that fails before the child session opens has no `agent.started`. A settled call does not end the child session; later calls with the same `taskId` reach it.
132
132