eve 0.13.7 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (183) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/dist/src/channel/routes.d.ts +5 -0
  3. package/dist/src/channel/send.js +1 -1
  4. package/dist/src/channel/types.d.ts +5 -0
  5. package/dist/src/compiled/.vendor-stamp.json +12 -8
  6. package/dist/src/compiled/@ai-sdk/anthropic/index.d.ts +2 -2
  7. package/dist/src/compiled/@ai-sdk/anthropic/index.js +2 -2
  8. package/dist/src/compiled/@ai-sdk/google/index.d.ts +25 -3
  9. package/dist/src/compiled/@ai-sdk/google/index.js +6 -6
  10. package/dist/src/compiled/@ai-sdk/mcp/index.d.ts +647 -30
  11. package/dist/src/compiled/@ai-sdk/mcp/index.js +1 -1
  12. package/dist/src/compiled/@ai-sdk/openai/index.d.ts +8 -2
  13. package/dist/src/compiled/@ai-sdk/openai/index.js +2 -2
  14. package/dist/src/compiled/@ai-sdk/otel/index.d.ts +165 -28
  15. package/dist/src/compiled/@ai-sdk/otel/index.js +3 -3
  16. package/dist/src/compiled/@ai-sdk/provider/index.d.ts +10 -2
  17. package/dist/src/compiled/@ai-sdk/provider-utils/index.d.ts +2362 -0
  18. package/dist/src/compiled/@ai-sdk/provider-utils/index.js +1 -0
  19. package/dist/src/compiled/@workflow/serde/LICENSE.md +3 -0
  20. package/dist/src/compiled/@workflow/serde/index.d.ts +30 -0
  21. package/dist/src/compiled/@workflow/serde/index.js +1 -0
  22. package/dist/src/compiled/_chunks/workflow/{dist-C9PV_vnE.js → dist-D7CzPkf8.js} +1 -1
  23. package/dist/src/compiled/eventsource-parser/stream/LICENSE +21 -0
  24. package/dist/src/compiled/eventsource-parser/stream/index.d.ts +121 -0
  25. package/dist/src/compiled/eventsource-parser/stream/index.js +1 -0
  26. package/dist/src/compiled/experimental-ai-sdk-code-mode/approval-continuation.d.ts +7 -7
  27. package/dist/src/compiled/experimental-ai-sdk-code-mode/continuation-capability.d.ts +15 -4
  28. package/dist/src/compiled/experimental-ai-sdk-code-mode/index.d.ts +1 -1
  29. package/dist/src/compiled/experimental-ai-sdk-code-mode/index.js +15 -15
  30. package/dist/src/compiled/experimental-ai-sdk-code-mode/interrupt-continuation.d.ts +5 -5
  31. package/dist/src/compiled/experimental-ai-sdk-code-mode/runtime/protocol.d.ts +13 -2
  32. package/dist/src/compiled/experimental-ai-sdk-code-mode/types.d.ts +26 -0
  33. package/dist/src/compiled/json-schema/LICENSE +21 -0
  34. package/dist/src/compiled/json-schema/index.d.ts +749 -0
  35. package/dist/src/compiled/json-schema/index.js +1 -0
  36. package/dist/src/compiler/manifest.js +1 -1
  37. package/dist/src/compiler/normalize-agent-config.js +1 -1
  38. package/dist/src/context/build-dynamic-tools.js +1 -1
  39. package/dist/src/context/dynamic-tool-lifecycle.js +1 -1
  40. package/dist/src/context/keys.d.ts +1 -1
  41. package/dist/src/execution/create-session-step.d.ts +0 -17
  42. package/dist/src/execution/create-session-step.js +1 -1
  43. package/dist/src/execution/dispatch-runtime-actions-step.js +1 -1
  44. package/dist/src/execution/dispatch-workflow-runtime-actions-step.d.ts +12 -0
  45. package/dist/src/execution/dispatch-workflow-runtime-actions-step.js +1 -0
  46. package/dist/src/execution/eve-workflow-attributes.d.ts +1 -1
  47. package/dist/src/execution/next-driver-action.d.ts +1 -1
  48. package/dist/src/execution/node-step.js +1 -1
  49. package/dist/src/execution/sandbox/prewarm.js +1 -1
  50. package/dist/src/execution/session.js +3 -3
  51. package/dist/src/execution/turn-workflow.js +1 -1
  52. package/dist/src/execution/workflow-entry.js +1 -1
  53. package/dist/src/execution/workflow-runtime.d.ts +2 -3
  54. package/dist/src/execution/workflow-runtime.js +1 -1
  55. package/dist/src/execution/workflow-steps.d.ts +1 -1
  56. package/dist/src/execution/workflow-steps.js +1 -1
  57. package/dist/src/harness/action-result-helpers.d.ts +2 -2
  58. package/dist/src/harness/emission.js +1 -1
  59. package/dist/src/harness/execute-tool.d.ts +2 -2
  60. package/dist/src/harness/input-extraction.js +1 -1
  61. package/dist/src/harness/tool-loop.js +1 -1
  62. package/dist/src/harness/tools.d.ts +4 -6
  63. package/dist/src/harness/tools.js +1 -1
  64. package/dist/src/harness/types.d.ts +4 -10
  65. package/dist/src/harness/workflow-continuation-security.d.ts +4 -0
  66. package/dist/src/harness/workflow-continuation-security.js +1 -0
  67. package/dist/src/harness/workflow-interrupt-state.d.ts +14 -0
  68. package/dist/src/harness/workflow-interrupt-state.js +1 -0
  69. package/dist/src/harness/workflow-lifecycle.d.ts +13 -0
  70. package/dist/src/harness/workflow-lifecycle.js +1 -0
  71. package/dist/src/harness/workflow-runtime-action-state.d.ts +9 -0
  72. package/dist/src/harness/workflow-runtime-action-state.js +1 -0
  73. package/dist/src/harness/workflow-sandbox.d.ts +22 -0
  74. package/dist/src/harness/workflow-sandbox.js +2 -0
  75. package/dist/src/harness/workflow-tool-description.d.ts +2 -2
  76. package/dist/src/harness/workflow-tool-description.js +16 -4
  77. package/dist/src/internal/application/package.js +1 -1
  78. package/dist/src/internal/authored-definition/connection.js +1 -1
  79. package/dist/src/internal/authored-definition/core.js +1 -1
  80. package/dist/src/internal/authored-definition/schema-backed.js +1 -1
  81. package/dist/src/internal/nitro/host/create-application-nitro.js +1 -1
  82. package/dist/src/internal/nitro/host/workflow-sandbox-runtime-plugin.d.ts +1 -0
  83. package/dist/src/internal/nitro/host/workflow-sandbox-runtime-plugin.js +1 -0
  84. package/dist/src/internal/nitro/routes/agent-info/build-agent-info-response-from-manifest.js +1 -1
  85. package/dist/src/internal/nitro/routes/agent-info/build-agent-info-response.js +1 -1
  86. package/dist/src/internal/workflow/runtime.d.ts +1 -0
  87. package/dist/src/public/channels/slack/attachments.js +1 -1
  88. package/dist/src/public/channels/slack/auth.d.ts +2 -0
  89. package/dist/src/public/channels/slack/auth.js +1 -1
  90. package/dist/src/public/channels/slack/defaults.js +2 -2
  91. package/dist/src/public/channels/slack/inbound.d.ts +4 -11
  92. package/dist/src/public/channels/slack/inbound.js +1 -2
  93. package/dist/src/public/channels/slack/model-context.d.ts +28 -0
  94. package/dist/src/public/channels/slack/model-context.js +3 -0
  95. package/dist/src/public/channels/slack/slackChannel.d.ts +8 -0
  96. package/dist/src/public/channels/slack/slackChannel.js +1 -1
  97. package/dist/src/public/connections/index.d.ts +1 -1
  98. package/dist/src/public/definitions/agent.d.ts +1 -1
  99. package/dist/src/public/definitions/approval.d.ts +40 -0
  100. package/dist/src/public/definitions/approval.js +1 -0
  101. package/dist/src/public/definitions/connections/mcp.d.ts +11 -9
  102. package/dist/src/public/definitions/connections/mcp.js +1 -1
  103. package/dist/src/public/definitions/connections/openapi.d.ts +9 -7
  104. package/dist/src/public/definitions/connections/openapi.js +1 -1
  105. package/dist/src/public/definitions/tool.d.ts +7 -20
  106. package/dist/src/public/index.d.ts +1 -1
  107. package/dist/src/public/tools/approval/approval-helpers.d.ts +7 -7
  108. package/dist/src/public/tools/approval/approval-helpers.js +1 -1
  109. package/dist/src/public/tools/approval/index.d.ts +1 -1
  110. package/dist/src/public/tools/index.d.ts +2 -1
  111. package/dist/src/public/tools/internal.js +1 -1
  112. package/dist/src/runtime/agent/bootstrap.d.ts +1 -0
  113. package/dist/src/runtime/agent/bootstrap.js +1 -1
  114. package/dist/src/runtime/agent/mock-model-adapter.js +2 -3
  115. package/dist/src/runtime/attributes/emit.d.ts +2 -43
  116. package/dist/src/runtime/attributes/emit.js +1 -1
  117. package/dist/src/runtime/attributes/normalize.d.ts +17 -0
  118. package/dist/src/runtime/attributes/normalize.js +1 -0
  119. package/dist/src/runtime/connections/mcp-client.d.ts +3 -3
  120. package/dist/src/runtime/connections/mcp-client.js +1 -1
  121. package/dist/src/runtime/connections/registry.d.ts +2 -2
  122. package/dist/src/runtime/connections/resolve-authorization.d.ts +11 -0
  123. package/dist/src/runtime/connections/resolve-authorization.js +1 -0
  124. package/dist/src/runtime/connections/types.d.ts +27 -11
  125. package/dist/src/runtime/framework-tools/connection-search-dynamic.js +1 -1
  126. package/dist/src/runtime/resolve-agent-graph.js +1 -1
  127. package/dist/src/runtime/resolve-agent.js +1 -1
  128. package/dist/src/runtime/resolve-connection.js +1 -1
  129. package/dist/src/runtime/resolve-tool.d.ts +1 -1
  130. package/dist/src/runtime/resolve-tool.js +1 -1
  131. package/dist/src/runtime/sessions/compiled-agent-cache.js +1 -1
  132. package/dist/src/runtime/types.d.ts +8 -7
  133. package/dist/src/setup/primitives/pm/pnpm.js +6 -5
  134. package/dist/src/setup/scaffold/create/add-to-project.js +1 -1
  135. package/dist/src/setup/scaffold/create/project.js +2 -2
  136. package/dist/src/setup/scaffold/update/channels.js +1 -1
  137. package/dist/src/shared/agent-definition.d.ts +11 -13
  138. package/dist/src/shared/dynamic-tool-definition.d.ts +3 -3
  139. package/dist/src/shared/tool-definition.d.ts +1 -2
  140. package/dist/src/shared/workflow-sandbox.d.ts +37 -0
  141. package/dist/src/shared/workflow-sandbox.js +1 -0
  142. package/docs/agent-config.md +30 -10
  143. package/docs/channels/custom.mdx +2 -2
  144. package/docs/channels/slack.mdx +7 -13
  145. package/docs/connections/mcp.mdx +2 -2
  146. package/docs/connections/openapi.mdx +37 -2
  147. package/docs/connections/overview.mdx +32 -0
  148. package/docs/guides/deployment.md +2 -2
  149. package/docs/guides/dynamic-workflows.md +1 -7
  150. package/docs/guides/frontend/overview.mdx +1 -1
  151. package/docs/guides/frontend/use-eve-agent-svelte.mdx +1 -1
  152. package/docs/guides/frontend/use-eve-agent-vue.mdx +1 -1
  153. package/docs/guides/session-context.md +2 -1
  154. package/docs/reference/typescript-api.md +2 -2
  155. package/docs/subagents.mdx +2 -2
  156. package/docs/tools/human-in-the-loop.md +43 -6
  157. package/docs/tools/overview.mdx +3 -3
  158. package/docs/tutorial/first-agent.mdx +1 -1
  159. package/docs/tutorial/guard-the-spend.mdx +4 -3
  160. package/docs/tutorial/ship-it.mdx +1 -1
  161. package/package.json +14 -11
  162. package/dist/src/compiled/@ai-sdk/anthropic/_provider-utils.d.ts +0 -15
  163. package/dist/src/compiled/@ai-sdk/google/_provider-utils.d.ts +0 -11
  164. package/dist/src/compiled/@ai-sdk/openai/_provider-utils.d.ts +0 -15
  165. package/dist/src/compiled/@ai-sdk/provider/_json-schema.d.ts +0 -5
  166. package/dist/src/execution/dispatch-code-mode-runtime-actions-step.d.ts +0 -21
  167. package/dist/src/execution/dispatch-code-mode-runtime-actions-step.js +0 -1
  168. package/dist/src/harness/code-mode-interrupt-state.d.ts +0 -26
  169. package/dist/src/harness/code-mode-interrupt-state.js +0 -1
  170. package/dist/src/harness/code-mode-lifecycle.d.ts +0 -16
  171. package/dist/src/harness/code-mode-lifecycle.js +0 -1
  172. package/dist/src/harness/code-mode-runtime-action-state.d.ts +0 -6
  173. package/dist/src/harness/code-mode-runtime-action-state.js +0 -1
  174. package/dist/src/harness/code-mode.d.ts +0 -26
  175. package/dist/src/harness/code-mode.js +0 -1
  176. package/dist/src/harness/sandbox-surface.d.ts +0 -68
  177. package/dist/src/harness/sandbox-surface.js +0 -1
  178. package/dist/src/internal/nitro/host/code-mode-runtime-dependency-plugin.d.ts +0 -1
  179. package/dist/src/internal/nitro/host/code-mode-runtime-dependency-plugin.js +0 -1
  180. package/dist/src/runtime/framework-tools/code-mode-connection-auth.d.ts +0 -29
  181. package/dist/src/runtime/framework-tools/code-mode-connection-auth.js +0 -1
  182. package/dist/src/shared/code-mode.d.ts +0 -29
  183. package/dist/src/shared/code-mode.js +0 -1
@@ -1,4 +1,5 @@
1
1
  import "#internal/workflow/queue-namespace.js";
2
2
  export * from "#compiled/@workflow/core/runtime.js";
3
+ export type { StartOptionsWithoutDeploymentId, WorkflowFunction, WorkflowMetadata, } from "#compiled/@workflow/core/runtime/start.js";
3
4
  /** Installs a World across source and vendored Workflow package identities. */
4
5
  export declare function setWorld(world: unknown): void;
@@ -1 +1 @@
1
- import{createLogger}from"#internal/logging.js";import{evaluateFilePart,formatUploadPolicyViolation,isUploadsDisabled}from"#public/channels/upload-policy.js";import{resolveSlackBotToken}from"#public/channels/slack/api.js";const log=createLogger(`slack.attachments`);function collectSlackFileParts(e,r){let i=[];for(let o of e??[]){let e=toSlackFilePart(o,i.length);if(e===null)continue;let s=evaluateFilePart(e,r);if(s!==null){log.warn(`dropped attachment — ${formatUploadPolicyViolation(s)}`,{name:o.name});continue}i.push(e)}return i}function toSlackFilePart(e,t){return e.type===`audio`||e.type===`video`?null:e.url?{type:`file`,mediaType:e.mimeType??`application/octet-stream`,filename:e.name??`attachment-${t}`,data:new URL(e.url)}:(log.warn(`dropped attachment — no url available`,{name:e.name}),null)}async function collectInboundFileParts(e){let t=collectSlackFileParts(e.mention.attachments,e.policy);if(t.length>0)return t;if(isUploadsDisabled(e.policy))return[];try{await e.thread.refresh()}catch(e){return log.warn(`slack thread refresh failed for attachment collection`,{error:e}),[]}let n=e.thread.recentMessages;for(let t=n.length-1;t>=0;--t){let r=n[t];if(!r||r.isMe)continue;let i=r.raw,a=collectSlackFileParts(extractAttachmentsFromRaw(i?.files),e.policy);return a.length>0?a:[]}return[]}function extractAttachmentsFromRaw(e){return Array.isArray(e)?e.map(e=>{let t=typeof e.mimetype==`string`?e.mimetype:void 0;return{id:typeof e.id==`string`?e.id:``,type:inferAttachmentType(t),url:typeof e.url_private==`string`?e.url_private:void 0,name:typeof e.name==`string`?e.name:void 0,mimeType:t,size:typeof e.size==`number`?e.size:void 0}}):[]}function inferAttachmentType(e){return e===void 0?`file`:e.startsWith(`image/`)?`image`:e.startsWith(`video/`)?`video`:e.startsWith(`audio/`)?`audio`:`file`}function buildSlackTurnMessage(e,t){return t.length===0?e:e.trim().length===0?[...t]:[{type:`text`,text:e},...t]}function createSlackFetchFile(e){return async t=>{if(!isSlackFileUrl(t))return null;let n=await resolveSlackBotToken(e.botToken),r=await fetch(t,{headers:{authorization:`Bearer ${n}`}});if(!r.ok)throw Error(`Slack file fetch returned HTTP ${r.status} for ${t}.`);return{bytes:Buffer.from(await r.arrayBuffer()),mediaType:r.headers.get(`content-type`)??void 0}}}function isSlackFileUrl(e){let t=URL.parse(e);return t?.protocol===`https:`?t.hostname===`files.slack.com`?!0:(t.hostname===`enterprise.slack.com`||t.hostname.endsWith(`.enterprise.slack.com`))&&t.pathname.startsWith(`/files/`):!1}export{buildSlackTurnMessage,collectInboundFileParts,collectSlackFileParts,createSlackFetchFile};
1
+ import{createLogger}from"#internal/logging.js";import{evaluateFilePart,formatUploadPolicyViolation,isUploadsDisabled}from"#public/channels/upload-policy.js";import{resolveSlackBotToken}from"#public/channels/slack/api.js";const log=createLogger(`slack.attachments`);function collectSlackFileParts(e,r){let i=[];for(let o of e??[]){let e=toSlackFilePart(o,i.length);if(e===null)continue;let s=evaluateFilePart(e,r);if(s!==null){log.warn(`dropped attachment — ${formatUploadPolicyViolation(s)}`,{name:o.name});continue}i.push(e)}return i}function toSlackFilePart(e,t){return e.type===`audio`||e.type===`video`?null:e.url?{type:`file`,mediaType:e.mimeType??`application/octet-stream`,filename:e.name??`attachment-${t}`,data:new URL(e.url)}:(log.warn(`dropped attachment — no url available`,{name:e.name}),null)}async function collectInboundFileParts(e){let t=collectSlackFileParts(e.mention.attachments,e.policy);if(t.length>0)return t;if(isUploadsDisabled(e.policy))return[];if(e.thread.recentMessages.length===0)try{await e.thread.refresh()}catch(e){return log.warn(`slack thread refresh failed for attachment collection`,{error:e}),[]}let n=e.thread.recentMessages;for(let t=n.length-1;t>=0;--t){let r=n[t];if(!r||r.isMe)continue;let i=r.raw,a=collectSlackFileParts(extractAttachmentsFromRaw(i?.files),e.policy);return a.length>0?a:[]}return[]}function extractAttachmentsFromRaw(e){return Array.isArray(e)?e.map(e=>{let t=typeof e.mimetype==`string`?e.mimetype:void 0;return{id:typeof e.id==`string`?e.id:``,type:inferAttachmentType(t),url:typeof e.url_private==`string`?e.url_private:void 0,name:typeof e.name==`string`?e.name:void 0,mimeType:t,size:typeof e.size==`number`?e.size:void 0}}):[]}function inferAttachmentType(e){return e===void 0?`file`:e.startsWith(`image/`)?`image`:e.startsWith(`video/`)?`video`:e.startsWith(`audio/`)?`audio`:`file`}function buildSlackTurnMessage(e,t){return t.length===0?e:e.trim().length===0?[...t]:[{type:`text`,text:e},...t]}function createSlackFetchFile(e){return async t=>{if(!isSlackFileUrl(t))return null;let n=await resolveSlackBotToken(e.botToken),r=await fetch(t,{headers:{authorization:`Bearer ${n}`}});if(!r.ok)throw Error(`Slack file fetch returned HTTP ${r.status} for ${t}.`);return{bytes:Buffer.from(await r.arrayBuffer()),mediaType:r.headers.get(`content-type`)??void 0}}}function isSlackFileUrl(e){let t=URL.parse(e);return t?.protocol===`https:`?t.hostname===`files.slack.com`?!0:(t.hostname===`enterprise.slack.com`||t.hostname.endsWith(`.enterprise.slack.com`))&&t.pathname.startsWith(`/files/`):!1}export{buildSlackTurnMessage,collectInboundFileParts,collectSlackFileParts,createSlackFetchFile};
@@ -8,6 +8,8 @@ interface SlackAuthContextInput {
8
8
  readonly userId: string;
9
9
  readonly userName?: string;
10
10
  }
11
+ /** Returns the Slack user id carried by a Slack-derived auth context. */
12
+ export declare function slackUserIdFromAuthContext(auth: SessionAuthContext | null): string | undefined;
11
13
  /**
12
14
  * Builds the Slack-derived session auth context used by inbound
13
15
  * messages and signed interactivity callbacks.
@@ -1 +1 @@
1
- function buildSlackAuthContext(e){let t=e.isBot===!0,n=e.teamId?t?`slack:${e.teamId}:bot:${e.userId}`:`slack:${e.teamId}:${e.userId}`:t?`slack:bot:${e.userId}`:`slack:${e.userId}`,r={author_type:t?`bot`:`user`,channel_id:e.channelId,thread_ts:e.threadTs,user_id:e.userId};return e.userName&&(r.user_name=e.userName),e.fullName&&(r.full_name=e.fullName),e.teamId&&(r.team_id=e.teamId),{attributes:r,authenticator:`slack-webhook`,issuer:e.teamId?`slack:${e.teamId}`:`slack`,principalId:n,principalType:t?`service`:`user`}}export{buildSlackAuthContext};
1
+ function slackUserIdFromAuthContext(e){if(e?.authenticator!==`slack-webhook`)return;let t=e.attributes.user_id;return typeof t==`string`&&t.length>0?t:void 0}function buildSlackAuthContext(e){let t=e.isBot===!0,n=e.teamId?t?`slack:${e.teamId}:bot:${e.userId}`:`slack:${e.teamId}:${e.userId}`:t?`slack:bot:${e.userId}`:`slack:${e.userId}`,r={author_type:t?`bot`:`user`,channel_id:e.channelId,thread_ts:e.threadTs,user_id:e.userId};return e.userName&&(r.user_name=e.userName),e.fullName&&(r.full_name=e.fullName),e.teamId&&(r.team_id=e.teamId),{attributes:r,authenticator:`slack-webhook`,issuer:e.teamId?`slack:${e.teamId}`:`slack`,principalId:n,principalType:t?`service`:`user`}}export{buildSlackAuthContext,slackUserIdFromAuthContext};
@@ -1,4 +1,4 @@
1
- import{createLogger,extractErrorId,formatErrorHint}from"#internal/logging.js";import{buildSlackAuthContext}from"#public/channels/slack/auth.js";import{buildAuthCompletedText,buildAuthEphemeralBlocks,buildAuthRequiredPublicText,formatConnectionDisplayName}from"#public/channels/slack/connections.js";import{renderInputRequestBlocks}from"#public/channels/slack/hitl.js";import{truncateMessageText,truncateTypingStatus}from"#public/channels/slack/limits.js";const log=createLogger(`slack.defaults`);function defaultSlackAuth(e,t){let n=e.author;return n?buildSlackAuthContext({channelId:t.slack.channelId,fullName:n.fullName,isBot:n.isBot,teamId:e.teamId,threadTs:t.slack.threadTs,userId:n.userId,userName:n.userName}):null}async function defaultOnAppMention(e,t){return await e.thread.startTyping(`Thinking...`),{auth:defaultSlackAuth(t,e)}}async function defaultOnDirectMessage(e,t){return await e.thread.startTyping(`Thinking...`),{auth:defaultSlackAuth(t,e)}}function firstNonEmptyLine(e){for(let t of e.split(/\r?\n/u)){let e=t.trim();if(e.length>0)return e}}function defaultInputRequestedHandler(){return async(e,t,n)=>{if(e.requests.length===0)return;let r=truncateMessageText(e.requests.map(e=>e.prompt).join(`
1
+ import{createLogger,extractErrorId,formatErrorHint}from"#internal/logging.js";import{buildSlackAuthContext,slackUserIdFromAuthContext}from"#public/channels/slack/auth.js";import{buildAuthCompletedText,buildAuthEphemeralBlocks,buildAuthRequiredPublicText,formatConnectionDisplayName}from"#public/channels/slack/connections.js";import{renderInputRequestBlocks}from"#public/channels/slack/hitl.js";import{truncateMessageText,truncateTypingStatus}from"#public/channels/slack/limits.js";const log=createLogger(`slack.defaults`);function defaultSlackAuth(e,t){let n=e.author;return n?buildSlackAuthContext({channelId:t.slack.channelId,fullName:n.fullName,isBot:n.isBot,teamId:e.teamId,threadTs:t.slack.threadTs,userId:n.userId,userName:n.userName}):null}async function defaultOnAppMention(e,t){return await e.thread.startTyping(`Thinking...`),{auth:defaultSlackAuth(t,e)}}async function defaultOnDirectMessage(e,t){return await e.thread.startTyping(`Thinking...`),{auth:defaultSlackAuth(t,e)}}function firstNonEmptyLine(e){for(let t of e.split(/\r?\n/u)){let e=t.trim();if(e.length>0)return e}}function defaultInputRequestedHandler(){return async(e,t,n)=>{if(e.requests.length===0)return;let r=truncateMessageText(e.requests.map(e=>e.prompt).join(`
2
2
  `));await t.thread.post({blocks:e.requests.flatMap(renderInputRequestBlocks),text:r})}}const defaultEvents={async"turn.started"(e,t,n){t.state.pendingToolCallMessage=null,t.state.lastReasoningTypingAtMs=null,t.state.lastReasoningTypingStatus=null,await t.thread.startTyping(`Working...`)},async"reasoning.appended"(e,t,n){let r=firstNonEmptyLine(e.reasoningSoFar);if(r===void 0)return;let i=truncateTypingStatus(r),a=t.state.lastReasoningTypingStatus,o=a!=null&&i.startsWith(a)&&i.length>=a.length+4,s=Date.now(),c=t.state.lastReasoningTypingAtMs;if(!o&&c!=null){let e=s-c;if(e>=0&&e<5e3)return}await t.thread.startTyping(i),t.state.lastReasoningTypingAtMs=s,t.state.lastReasoningTypingStatus=i},async"actions.requested"(e,t,n){let r=t.state.pendingToolCallMessage;if(t.state.pendingToolCallMessage=null,r){await t.thread.startTyping(truncateTypingStatus(r));return}let i=e.actions.map(e=>e.kind===`tool-call`?e.toolName:e.kind);await t.thread.startTyping(truncateTypingStatus(`Running ${i.join(`, `)}...`))},async"message.completed"(e,t,n){if(e.finishReason===`tool-calls`){t.state.pendingToolCallMessage=e.message?firstNonEmptyLine(e.message)??null:null;return}if(t.state.pendingToolCallMessage=null,!e.message){await t.thread.startTyping();return}await t.thread.post(e.message)},async"turn.failed"(e,r,i){let a=formatErrorHint(e),o=extractErrorId(e.details);await r.thread.post([`I hit an error while handling your request${a}.`,``,`Please try again, rephrase, or reach out if it keeps failing.`,...o?[``,`_Error id: \`${o}\`_`]:[]].join(`
3
3
  `))},async"session.failed"(e,r){let i=formatErrorHint(e),a=extractErrorId(e.details);await r.thread.post([`This session couldn't recover from an error${i}.`,``,`Start a new thread to continue — I can't pick this one back up.`,...a?[``,`_Error id: \`${a}\`_`]:[]].join(`
4
- `))},async"authorization.required"(e,t,n){let r=e.authorization?.displayName??formatConnectionDisplayName(e.name),i=t.state.triggeringUserId??null,c=e.authorization?.url,l=t.state.pendingAuthMessageTs??{};if(l[e.name]===void 0){let n=buildAuthRequiredPublicText({displayName:r,hasUser:i!==null});try{let r=await t.thread.post(n);r.id&&(t.state.pendingAuthMessageTs={...l,[e.name]:r.id})}catch(t){log.error(`Slack auth public message delivery failed`,{name:e.name,error:t})}}if(i&&c){let n=e.authorization?.userCode;try{await t.thread.postEphemeral(i,{blocks:buildAuthEphemeralBlocks({displayName:r,url:c,userCode:n}),text:n?`Sign in with ${r}: ${c} (code: ${n})`:`Sign in with ${r}: ${c}`})}catch(t){log.error(`Slack auth ephemeral delivery failed`,{name:e.name,error:t})}}},async"authorization.completed"(e,t,n){let r=t.state.pendingAuthMessageTs??{},a=r[e.name];if(a===void 0)return;let o=buildAuthCompletedText({displayName:e.authorization?.displayName??formatConnectionDisplayName(e.name),outcome:e.outcome,reason:e.reason});try{await t.slack.request(`chat.update`,{channel:t.slack.channelId,ts:a,text:o})}catch(t){log.error(`Slack auth status edit failed`,{name:e.name,error:t})}let c={...r};delete c[e.name],t.state.pendingAuthMessageTs=c}};export{defaultEvents,defaultInputRequestedHandler,defaultOnAppMention,defaultOnDirectMessage,defaultSlackAuth};
4
+ `))},async"authorization.required"(e,t,n){let r=e.authorization?.displayName??formatConnectionDisplayName(e.name),a=slackUserIdFromAuthContext(n.session.auth.current)??t.state.triggeringUserId??null,l=e.authorization?.url,u=t.state.pendingAuthMessageTs??{};if(u[e.name]===void 0){let n=buildAuthRequiredPublicText({displayName:r,hasUser:a!==null});try{let r=await t.thread.post(n);r.id&&(t.state.pendingAuthMessageTs={...u,[e.name]:r.id})}catch(t){log.error(`Slack auth public message delivery failed`,{name:e.name,error:t})}}if(a&&l){let n=e.authorization?.userCode;try{await t.thread.postEphemeral(a,{blocks:buildAuthEphemeralBlocks({displayName:r,url:l,userCode:n}),text:n?`Sign in with ${r}: ${l} (code: ${n})`:`Sign in with ${r}: ${l}`})}catch(t){log.error(`Slack auth ephemeral delivery failed`,{name:e.name,error:t})}}},async"authorization.completed"(e,t,n){let r=t.state.pendingAuthMessageTs??{},i=r[e.name];if(i===void 0)return;let o=buildAuthCompletedText({displayName:e.authorization?.displayName??formatConnectionDisplayName(e.name),outcome:e.outcome,reason:e.reason});try{await t.slack.request(`chat.update`,{channel:t.slack.channelId,ts:i,text:o})}catch(t){log.error(`Slack auth status edit failed`,{name:e.name,error:t})}let s={...r};delete s[e.name],t.state.pendingAuthMessageTs=s}};export{defaultEvents,defaultInputRequestedHandler,defaultOnAppMention,defaultOnDirectMessage,defaultSlackAuth};
@@ -8,10 +8,9 @@
8
8
  * a channel-owned {@link SlackMessage}, with the body's text already
9
9
  * re-rendered as GFM markdown so the agent does not see raw
10
10
  * `<@U…>` / `<https://…|…>` fragments.
11
- * 2. {@link formatSlackContextBlock} renders a `<slack_context>` block
12
- * naming the actor, channel, and thread. The channel delivers it as
13
- * a dedicated context entry so the agent always knows who and where
14
- * it is talking.
11
+ * 2. The channel renders the actor, message, channel, and thread as one
12
+ * attributed model message so speaker identity cannot drift away from
13
+ * the content it describes.
15
14
  */
16
15
  /**
17
16
  * Author metadata for an inbound Slack message. Channel-owned shape;
@@ -101,7 +100,7 @@ export declare function parseAppMentionEvent(envelope: SlackEventCallback): Slac
101
100
  */
102
101
  export declare function parseDirectMessageEvent(envelope: SlackEventCallback): SlackMessage | null;
103
102
  /**
104
- * Verified inbound identity used to render a `<slack_context>` block.
103
+ * Verified inbound identity used to attribute a model-visible Slack message.
105
104
  *
106
105
  * Channel-owned shape so the helper does not depend on the inbound
107
106
  * `SlackMessage` and is therefore trivially testable in isolation.
@@ -114,9 +113,3 @@ export interface SlackInboundContext {
114
113
  readonly threadTs: string;
115
114
  readonly teamId?: string;
116
115
  }
117
- /**
118
- * Renders one {@link SlackInboundContext} as a `<slack_context>` block.
119
- * Lines are deterministic and tag-delimited so the agent can match the
120
- * block in its prompt.
121
- */
122
- export declare function formatSlackContextBlock(context: SlackInboundContext): string;
@@ -1,2 +1 @@
1
- import{slackMrkdwnToGfm}from"#public/channels/slack/mrkdwn.js";function parseAppMentionEvent(e){if(e.type!==`event_callback`)return null;let t=e.event;return!t||t.type!==`app_mention`?null:buildSlackMessage(t,e.team_id)}function parseDirectMessageEvent(e){if(e.type!==`event_callback`)return null;let t=e.event;if(!t||t.type!==`message`)return null;let n=t;return n.channel_type!==`im`||typeof n.subtype==`string`&&n.subtype.length>0&&n.subtype!==`file_share`||typeof n.bot_id==`string`&&n.bot_id.length>0?null:buildSlackMessage(n,e.team_id)}function buildSlackMessage(t,n){let r=typeof t.channel==`string`?t.channel:``,i=typeof t.ts==`string`?t.ts:``;if(!r||!i)return null;let a=typeof t.text==`string`?t.text:``,o=typeof t.thread_ts==`string`?t.thread_ts:i,s=typeof n==`string`?n:void 0;return{text:a,markdown:slackMrkdwnToGfm(a),ts:i,threadTs:o,channelId:r,teamId:s,author:parseAuthor(t),attachments:parseAttachments(t.files),raw:t}}function parseAuthor(e){let t=typeof e.user==`string`?e.user:``;if(t)return{userId:t,userName:typeof e.username==`string`?e.username:void 0,fullName:void 0,isBot:typeof e.bot_id==`string`&&e.bot_id.length>0,isMe:!1}}function parseAttachments(e){return Array.isArray(e)?e.map(toAttachment):[]}function toAttachment(e){let t=typeof e.mimetype==`string`?e.mimetype:void 0,n=typeof e.url_private==`string`?e.url_private:void 0;return{id:typeof e.id==`string`?e.id:``,type:inferAttachmentType(t),url:n,name:typeof e.name==`string`?e.name:void 0,mimeType:t,size:typeof e.size==`number`?e.size:void 0}}function inferAttachmentType(e){return e===void 0?`file`:e.startsWith(`image/`)?`image`:e.startsWith(`video/`)?`video`:e.startsWith(`audio/`)?`audio`:`file`}function formatSlackContextBlock(e){return[`<slack_context>`,`user_id: ${e.userId}`,...e.userName?[`user_name: ${e.userName}`]:[],...e.fullName?[`full_name: ${e.fullName}`]:[],`channel_id: ${e.channelId}`,`thread_ts: ${e.threadTs}`,...e.teamId?[`team_id: ${e.teamId}`]:[],`</slack_context>`].join(`
2
- `)}export{formatSlackContextBlock,parseAppMentionEvent,parseDirectMessageEvent};
1
+ import{slackMrkdwnToGfm}from"#public/channels/slack/mrkdwn.js";function parseAppMentionEvent(e){if(e.type!==`event_callback`)return null;let t=e.event;return!t||t.type!==`app_mention`?null:buildSlackMessage(t,e.team_id)}function parseDirectMessageEvent(e){if(e.type!==`event_callback`)return null;let t=e.event;if(!t||t.type!==`message`)return null;let n=t;return n.channel_type!==`im`||typeof n.subtype==`string`&&n.subtype.length>0&&n.subtype!==`file_share`||typeof n.bot_id==`string`&&n.bot_id.length>0?null:buildSlackMessage(n,e.team_id)}function buildSlackMessage(t,n){let r=typeof t.channel==`string`?t.channel:``,i=typeof t.ts==`string`?t.ts:``;if(!r||!i)return null;let a=typeof t.text==`string`?t.text:``,o=typeof t.thread_ts==`string`?t.thread_ts:i,s=typeof n==`string`?n:void 0;return{text:a,markdown:slackMrkdwnToGfm(a),ts:i,threadTs:o,channelId:r,teamId:s,author:parseAuthor(t),attachments:parseAttachments(t.files),raw:t}}function parseAuthor(e){let t=typeof e.user==`string`?e.user:``;if(t)return{userId:t,userName:typeof e.username==`string`?e.username:void 0,fullName:void 0,isBot:typeof e.bot_id==`string`&&e.bot_id.length>0,isMe:!1}}function parseAttachments(e){return Array.isArray(e)?e.map(toAttachment):[]}function toAttachment(e){let t=typeof e.mimetype==`string`?e.mimetype:void 0,n=typeof e.url_private==`string`?e.url_private:void 0;return{id:typeof e.id==`string`?e.id:``,type:inferAttachmentType(t),url:n,name:typeof e.name==`string`?e.name:void 0,mimeType:t,size:typeof e.size==`number`?e.size:void 0}}function inferAttachmentType(e){return e===void 0?`file`:e.startsWith(`image/`)?`image`:e.startsWith(`video/`)?`video`:e.startsWith(`audio/`)?`audio`:`file`}export{parseAppMentionEvent,parseDirectMessageEvent};
@@ -0,0 +1,28 @@
1
+ import type { SlackThreadMessage } from "#public/channels/slack/api.js";
2
+ import type { SlackInboundContext } from "#public/channels/slack/inbound.js";
3
+ interface SlackModelMessageInput {
4
+ readonly channelId?: string;
5
+ readonly content: string;
6
+ readonly senderId?: string;
7
+ readonly senderType: "agent" | "bot" | "unknown" | "user";
8
+ readonly teamId?: string;
9
+ readonly threadTs: string;
10
+ readonly ts: string;
11
+ }
12
+ /**
13
+ * Renders one Slack message with its sender identity attached to the same
14
+ * model-visible message. Slack user ids are stable and require no profile
15
+ * lookup, so they remain the canonical speaker identity.
16
+ */
17
+ export declare function formatSlackModelMessage(input: SlackModelMessageInput): string;
18
+ /** Renders the triggering inbound Slack message as one attributed block. */
19
+ export declare function formatSlackInboundMessage(context: SlackInboundContext, message: {
20
+ readonly markdown: string;
21
+ readonly ts: string;
22
+ }): string;
23
+ /**
24
+ * Renders fetched Slack replies as explicitly attributed background context.
25
+ * Returns `undefined` when there are no messages to add to the turn.
26
+ */
27
+ export declare function formatSlackThreadContext(messages: readonly SlackThreadMessage[]): string | undefined;
28
+ export {};
@@ -0,0 +1,3 @@
1
+ function formatSlackModelMessage(e){return[`<slack_message>`,`sender_type: ${e.senderType}`,...e.senderId?[`sender_id: ${e.senderId}`]:[],...e.channelId?[`channel_id: ${e.channelId}`]:[],`thread_ts: ${e.threadTs}`,`message_ts: ${e.ts}`,...e.teamId?[`team_id: ${e.teamId}`]:[],`<content>`,e.content,`</content>`,`</slack_message>`].join(`
2
+ `)}function formatSlackInboundMessage(e,t){return formatSlackModelMessage({channelId:e.channelId,content:t.markdown,senderId:e.userId||void 0,senderType:e.userId?`user`:`unknown`,teamId:e.teamId,threadTs:e.threadTs,ts:t.ts})}function formatSlackThreadContext(e){if(e.length!==0)return[`<slack_thread_context>`,...e.map(e=>formatSlackModelMessage({content:e.markdown,senderId:e.user??e.botId,senderType:slackThreadSenderType(e),threadTs:e.threadTs,ts:e.ts})),`</slack_thread_context>`].join(`
3
+ `)}function slackThreadSenderType(e){return e.isMe?`agent`:e.botId?`bot`:e.user?`user`:`unknown`}export{formatSlackInboundMessage,formatSlackModelMessage,formatSlackThreadContext};
@@ -5,6 +5,7 @@ import type { ChannelSessionOps } from "#public/definitions/defineChannel.js";
5
5
  import type { HandleMessageStreamEvent } from "#protocol/message.js";
6
6
  import { type SlackBotToken, type SlackHandle, type SlackThread } from "#public/channels/slack/api.js";
7
7
  import { type SlackMessage } from "#public/channels/slack/inbound.js";
8
+ import { type LoadThreadContextMessagesOptions } from "#public/channels/slack/thread.js";
8
9
  import { type UploadPolicyInput } from "#public/channels/upload-policy.js";
9
10
  import { type SlackWebhookVerifier } from "#public/channels/slack/verify.js";
10
11
  import { type Channel } from "#public/definitions/defineChannel.js";
@@ -291,6 +292,13 @@ export interface SlackChannelConfig {
291
292
  * unrestricted media types.
292
293
  */
293
294
  readonly uploadPolicy?: UploadPolicyInput;
295
+ /**
296
+ * Adds earlier replies from the current Slack thread to each triggering
297
+ * turn. Messages are rendered with their Slack sender ids attached so a
298
+ * multi-user transcript retains unambiguous speaker attribution. Omit this
299
+ * option to avoid fetching thread history.
300
+ */
301
+ readonly threadContext?: LoadThreadContextMessagesOptions;
294
302
  /**
295
303
  * Invoked when a Slack `app_mention` event arrives (only `app_mention`;
296
304
  * other event types are ignored). Decides whether to dispatch and with
@@ -1 +1 @@
1
- import{markEventHandled}from"./utils.js";import{createLogger,logError}from"#internal/logging.js";import{POST,defineChannel}from"#public/definitions/defineChannel.js";import{mergeUploadPolicy}from"#public/channels/upload-policy.js";import{buildSlackBinding,slackContinuationToken}from"#public/channels/slack/api.js";import{defaultEvents,defaultInputRequestedHandler,defaultOnAppMention,defaultOnDirectMessage}from"#public/channels/slack/defaults.js";import{buildSlackTurnMessage,collectInboundFileParts,createSlackFetchFile}from"#public/channels/slack/attachments.js";import{formatSlackContextBlock,parseAppMentionEvent,parseDirectMessageEvent}from"#public/channels/slack/inbound.js";import{SLACK_CHANNEL_DEFAULT_ROUTE}from"#public/channels/slack/constants.js";import{handleInteractionPost}from"#public/channels/slack/interactions.js";import{verifySlackRequest}from"#public/channels/slack/verify.js";const log=createLogger(`slack.channel`);function rebuildSlackContext(e,t,n){let{thread:r,slack:i}=buildSlackBinding({botToken:n?.botToken,channelId:e.channelId??``,threadTs:e.threadTs??``,teamId:e.teamId??void 0,onThreadTsChanged(n){e.threadTs=n,e.channelId&&t.setContinuationToken(slackContinuationToken(e.channelId,n))}});return{thread:r,slack:i,state:e}}function slackChannel(e={}){let t=mergeUploadPolicy(e.uploadPolicy),n=createSlackFetchFile({botToken:e.credentials?.botToken}),u=e.onAppMention??defaultOnAppMention,d=e.onDirectMessage??defaultOnDirectMessage,f=e.events?.[`authorization.required`],p={...defaultEvents,...e.events,"input.requested":e.events?.[`input.requested`]??defaultInputRequestedHandler(),"authorization.required":f===void 0?defaultEvents[`authorization.required`]:constrainAuthorizationRequired(f)},m=new Set;return defineChannel({kindHint:`slack`,state:{channelId:null,threadTs:null,teamId:null,triggeringUserId:null,pendingToolCallMessage:null,lastReasoningTypingAtMs:null,lastReasoningTypingStatus:null,pendingAuthMessageTs:{}},fetchFile:n,metadata(e){return{channelId:e.channelId,teamId:e.teamId,threadTs:e.threadTs,triggeringUserId:e.triggeringUserId??null}},context(t,n){return rebuildSlackContext(t,n,e.credentials)},routes:[POST(e.route??SLACK_CHANNEL_DEFAULT_ROUTE,async(n,{send:r,waitUntil:i})=>{let a=await verifyInbound(n,e.credentials);return a===null?new Response(`unauthorized`,{status:401}):shouldDropSlackHttpTimeoutRetry(n.headers)?new Response(`ok`):(n.headers.get(`content-type`)??``).includes(`application/x-www-form-urlencoded`)?handleInteractionPost(a,{send:r,waitUntil:i},{config:e}):handleEventPost({body:a,send:r,waitUntil:i,onAppMention:u,onDirectMessage:d,uploadPolicy:t,handledEvents:m,headers:n.headers,credentials:e.credentials})})],async receive(t,{send:n}){let r=t.target,i=r.channelId;if(!i||typeof i!=`string`)throw Error(`slackChannel().receive requires target.channelId.`);let a=typeof r.threadTs==`string`?r.threadTs:``,s=r.initialMessage;if(s&&a.length>0)throw Error("slackChannel().receive: `threadTs` and `initialMessage` are mutually exclusive.");let c=a;if(s){let{thread:t}=buildSlackBinding({botToken:e.credentials?.botToken,channelId:i,threadTs:``,teamId:void 0}),n={card:s.card};s.fallbackText!==void 0&&(n.fallbackText=s.fallbackText),c=(await t.post(n)).id}let l=c||crypto.randomUUID();return n(t.message,{auth:t.auth,continuationToken:slackContinuationToken(i,l),state:{channelId:i,threadTs:c||null,teamId:null,triggeringUserId:null}})},events:p})}function constrainAuthorizationRequired(e){return(t,n,r)=>e(t,{postEphemeral:(e,t)=>n.thread.postEphemeral(e,t),postDirectMessage:(e,t)=>n.thread.postDirectMessage(e,t),state:n.state},r)}function shouldDropSlackHttpTimeoutRetry(e){return Number(e.get(`x-slack-retry-num`)??`0`)>=1&&e.get(`x-slack-retry-reason`)===`http_timeout`}async function handleEventPost(t){let n;try{n=JSON.parse(t.body)}catch(e){return log.warn(`inbound webhook body is not valid JSON`,{error:e}),new Response(`ok`)}if(typeof n.challenge==`string`)return new Response(n.challenge,{status:200,headers:{"content-type":`text/plain`}});if(n.event_id){if(t.handledEvents.has(n.event_id))return log.warn(`received a duplicate event`,{event_id:n.event_id,event_time:n.event_time,retry_num:t.headers.get(`x-slack-retry-num`)||`(null)`,retry_reason:t.headers.get(`x-slack-retry-reason`)||`(null)`}),new Response(`ok`);markEventHandled(n.event_id,t.handledEvents)}let r=parseAppMentionEvent(n);if(r)return t.waitUntil(dispatchInboundMessage({kind:`app_mention`,message:r,handler:t.onAppMention,send:t.send,uploadPolicy:t.uploadPolicy,credentials:t.credentials})),new Response(`ok`);let i=parseDirectMessageEvent(n);return i&&t.waitUntil(dispatchInboundMessage({kind:`direct_message`,message:i,handler:t.onDirectMessage,send:t.send,uploadPolicy:t.uploadPolicy,credentials:t.credentials})),new Response(`ok`)}async function verifyInbound(e,t){try{return await verifySlackRequest(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 dispatchInboundMessage(e){let{message:t,kind:r}=e,{thread:i,slack:a}=buildSlackBinding({botToken:e.credentials?.botToken,channelId:t.channelId,threadTs:t.threadTs,teamId:t.teamId}),s={thread:i,slack:a},c;try{c=await e.handler(s,t)}catch(e){logError(log,`${r} handler failed`,e,{channelId:t.channelId});return}if(c!=null)try{let n=await collectInboundFileParts({mention:t,thread:i,policy:e.uploadPolicy}),r=buildSlackTurnMessage(t.markdown,n),a={channelId:t.channelId,fullName:t.author?.fullName,teamId:t.teamId,threadTs:t.threadTs,userId:t.author?.userId??``,userName:t.author?.userName},o=c.context??[];await e.send({message:r,context:[formatSlackContextBlock(a),...o]},{auth:c.auth,continuationToken:slackContinuationToken(t.channelId,t.threadTs),state:{channelId:t.channelId,threadTs:t.threadTs,teamId:t.teamId??null,triggeringUserId:a.userId||null}})}catch(e){logError(log,`${r} delivery failed`,e,{channelId:t.channelId})}}export{constrainAuthorizationRequired,slackChannel};
1
+ import{markEventHandled}from"./utils.js";import{createLogger,logError}from"#internal/logging.js";import{POST,defineChannel}from"#public/definitions/defineChannel.js";import{mergeUploadPolicy}from"#public/channels/upload-policy.js";import{buildSlackBinding,slackContinuationToken}from"#public/channels/slack/api.js";import{slackUserIdFromAuthContext}from"#public/channels/slack/auth.js";import{defaultEvents,defaultInputRequestedHandler,defaultOnAppMention,defaultOnDirectMessage}from"#public/channels/slack/defaults.js";import{loadThreadContextMessages}from"#public/channels/slack/thread.js";import{buildSlackTurnMessage,collectInboundFileParts,createSlackFetchFile}from"#public/channels/slack/attachments.js";import{parseAppMentionEvent,parseDirectMessageEvent}from"#public/channels/slack/inbound.js";import{formatSlackInboundMessage,formatSlackThreadContext}from"#public/channels/slack/model-context.js";import{SLACK_CHANNEL_DEFAULT_ROUTE}from"#public/channels/slack/constants.js";import{handleInteractionPost}from"#public/channels/slack/interactions.js";import{verifySlackRequest}from"#public/channels/slack/verify.js";const log=createLogger(`slack.channel`);function rebuildSlackContext(e,t,n){let{thread:r,slack:i}=buildSlackBinding({botToken:n?.botToken,channelId:e.channelId??``,threadTs:e.threadTs??``,teamId:e.teamId??void 0,onThreadTsChanged(n){e.threadTs=n,e.channelId&&t.setContinuationToken(slackContinuationToken(e.channelId,n))}});return{thread:r,slack:i,state:e}}function slackChannel(e={}){let t=mergeUploadPolicy(e.uploadPolicy),n=createSlackFetchFile({botToken:e.credentials?.botToken}),u=e.onAppMention??defaultOnAppMention,d=e.onDirectMessage??defaultOnDirectMessage,f=e.events?.[`authorization.required`],p=e.events?.[`turn.started`]??defaultEvents[`turn.started`],m={...defaultEvents,...e.events,async"turn.started"(e,t,n){let r=slackUserIdFromAuthContext(n.session.auth.current);r!==void 0&&(t.state.triggeringUserId=r),await p(e,t,n)},"input.requested":e.events?.[`input.requested`]??defaultInputRequestedHandler(),"authorization.required":f===void 0?defaultEvents[`authorization.required`]:constrainAuthorizationRequired(f)},h=new Set;return defineChannel({kindHint:`slack`,state:{channelId:null,threadTs:null,teamId:null,triggeringUserId:null,pendingToolCallMessage:null,lastReasoningTypingAtMs:null,lastReasoningTypingStatus:null,pendingAuthMessageTs:{}},fetchFile:n,metadata(e){return{channelId:e.channelId,teamId:e.teamId,threadTs:e.threadTs,triggeringUserId:e.triggeringUserId??null}},context(t,n){return rebuildSlackContext(t,n,e.credentials)},routes:[POST(e.route??SLACK_CHANNEL_DEFAULT_ROUTE,async(n,{send:r,waitUntil:i})=>{let a=await verifyInbound(n,e.credentials);return a===null?new Response(`unauthorized`,{status:401}):shouldDropSlackHttpTimeoutRetry(n.headers)?new Response(`ok`):(n.headers.get(`content-type`)??``).includes(`application/x-www-form-urlencoded`)?handleInteractionPost(a,{send:r,waitUntil:i},{config:e}):handleEventPost({body:a,send:r,waitUntil:i,onAppMention:u,onDirectMessage:d,uploadPolicy:t,threadContext:e.threadContext,handledEvents:h,headers:n.headers,credentials:e.credentials})})],async receive(t,{send:n}){let r=t.target,i=r.channelId;if(!i||typeof i!=`string`)throw Error(`slackChannel().receive requires target.channelId.`);let a=typeof r.threadTs==`string`?r.threadTs:``,s=r.initialMessage;if(s&&a.length>0)throw Error("slackChannel().receive: `threadTs` and `initialMessage` are mutually exclusive.");let c=a;if(s){let{thread:t}=buildSlackBinding({botToken:e.credentials?.botToken,channelId:i,threadTs:``,teamId:void 0}),n={card:s.card};s.fallbackText!==void 0&&(n.fallbackText=s.fallbackText),c=(await t.post(n)).id}let l=c||crypto.randomUUID();return n(t.message,{auth:t.auth,continuationToken:slackContinuationToken(i,l),state:{channelId:i,threadTs:c||null,teamId:null,triggeringUserId:null}})},events:m})}function constrainAuthorizationRequired(e){return(t,n,r)=>e(t,{postEphemeral:(e,t)=>n.thread.postEphemeral(e,t),postDirectMessage:(e,t)=>n.thread.postDirectMessage(e,t),state:n.state},r)}function shouldDropSlackHttpTimeoutRetry(e){return Number(e.get(`x-slack-retry-num`)??`0`)>=1&&e.get(`x-slack-retry-reason`)===`http_timeout`}async function handleEventPost(t){let n;try{n=JSON.parse(t.body)}catch(e){return log.warn(`inbound webhook body is not valid JSON`,{error:e}),new Response(`ok`)}if(typeof n.challenge==`string`)return new Response(n.challenge,{status:200,headers:{"content-type":`text/plain`}});if(n.event_id){if(t.handledEvents.has(n.event_id))return log.warn(`received a duplicate event`,{event_id:n.event_id,event_time:n.event_time,retry_num:t.headers.get(`x-slack-retry-num`)||`(null)`,retry_reason:t.headers.get(`x-slack-retry-reason`)||`(null)`}),new Response(`ok`);markEventHandled(n.event_id,t.handledEvents)}let r=parseAppMentionEvent(n);if(r)return t.waitUntil(dispatchInboundMessage({kind:`app_mention`,message:r,handler:t.onAppMention,send:t.send,uploadPolicy:t.uploadPolicy,threadContext:t.threadContext,credentials:t.credentials})),new Response(`ok`);let i=parseDirectMessageEvent(n);return i&&t.waitUntil(dispatchInboundMessage({kind:`direct_message`,message:i,handler:t.onDirectMessage,send:t.send,uploadPolicy:t.uploadPolicy,threadContext:t.threadContext,credentials:t.credentials})),new Response(`ok`)}async function verifyInbound(e,t){try{return await verifySlackRequest(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 dispatchInboundMessage(e){let{message:t,kind:r}=e,{thread:i,slack:a}=buildSlackBinding({botToken:e.credentials?.botToken,channelId:t.channelId,threadTs:t.threadTs,teamId:t.teamId}),s={thread:i,slack:a},c;try{c=await e.handler(s,t)}catch(e){logError(log,`${r} handler failed`,e,{channelId:t.channelId});return}if(c!=null)try{let n=formatSlackThreadContext(e.threadContext===void 0?[]:await loadThreadContextMessages(i,t,e.threadContext)),r=await collectInboundFileParts({mention:t,thread:i,policy:e.uploadPolicy}),a={channelId:t.channelId,fullName:t.author?.fullName,teamId:t.teamId,threadTs:t.threadTs,userId:t.author?.userId??``,userName:t.author?.userName},o=formatSlackInboundMessage(a,t),s=buildSlackTurnMessage(n===void 0?o:`${n}\n\n${o}`,r),l=c.context??[];await e.send(l.length===0?{message:s}:{message:s,context:l},{auth:c.auth,continuationToken:slackContinuationToken(t.channelId,t.threadTs),state:{channelId:t.channelId,threadTs:t.threadTs,teamId:t.teamId??null,triggeringUserId:a.userId||null},title:t.markdown})}catch(e){logError(log,`${r} delivery failed`,e,{channelId:t.channelId})}}export{constrainAuthorizationRequired,slackChannel};
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Connection authoring helpers for `agent/connections/*.ts` files.
3
3
  */
4
- export type { AuthorizationCallback, AuthorizationDefinition, ConnectionAuthDefinition, ConnectionPrincipal, HeadersDefinition, InteractiveAuthorizationDefinition, NonInteractiveAuthorizationDefinition, TokenResult, ToolFilterDefinition, } from "#runtime/connections/types.js";
4
+ export type { AuthorizationCallback, AuthorizationDefinition, ConnectionAuthDefinition, ConnectionAuthProvider, ConnectionAuthResolver, ConnectionPrincipal, HeadersDefinition, InteractiveAuthorizationDefinition, NonInteractiveAuthorizationDefinition, TokenResult, ToolFilterDefinition, } from "#runtime/connections/types.js";
5
5
  export { defineInteractiveAuthorization } from "#runtime/connections/types.js";
6
6
  export type { JsonValue } from "#public/types/json.js";
7
7
  export { defineMcpClientConnection, type McpClientConnectionDefinition, } from "#public/definitions/connections/mcp.js";
@@ -1,6 +1,6 @@
1
1
  import type { PublicAgentDefinition } from "#shared/agent-definition.js";
2
2
  import type { ExactDefinition } from "#public/definitions/exact.js";
3
- export type { AgentModelOptionsDefinition, AgentBuildDefinition, AgentExperimentalDefinition, AgentWorkflowDefinition, AgentWorkflowWorldDefinition, PublicAgentModelDefinition as AgentModelDefinition, PublicAgentCompactionDefinition as AgentCompactionDefinition, } from "#shared/agent-definition.js";
3
+ export type { AgentModelOptionsDefinition, AgentReasoningDefinition, AgentBuildDefinition, AgentExperimentalDefinition, AgentWorkflowDefinition, AgentWorkflowWorldDefinition, PublicAgentModelDefinition as AgentModelDefinition, PublicAgentCompactionDefinition as AgentCompactionDefinition, } from "#shared/agent-definition.js";
4
4
  /**
5
5
  * Additive public agent configuration authored in `agent.ts`.
6
6
  *
@@ -0,0 +1,40 @@
1
+ import type { SessionContext } from "#public/definitions/callback-context.js";
2
+ type ApprovalToolInput<TInput> = TInput extends object ? Readonly<TInput> : TInput;
3
+ /**
4
+ * Context passed to an {@link Approval} function.
5
+ *
6
+ * Extends {@link SessionContext} so approval policies can make decisions from
7
+ * the active session, current caller, and turn.
8
+ *
9
+ * `approvedTools` is the set of tool names (or compound approval keys)
10
+ * already approved at least once in the current session. `toolName` is the
11
+ * runtime name of the tool being evaluated. `toolInput` is the raw input the
12
+ * model passed, available for input-aware decisions.
13
+ */
14
+ export interface ApprovalContext<TInput = Record<string, unknown>> extends SessionContext {
15
+ readonly approvedTools: ReadonlySet<string>;
16
+ readonly toolInput?: ApprovalToolInput<TInput>;
17
+ readonly toolName: string;
18
+ }
19
+ /**
20
+ * Approval decision returned by an {@link Approval} function.
21
+ *
22
+ * AI SDK 7 statuses are accepted directly. For compatibility, `true` maps to
23
+ * `"user-approval"` and `false` maps to `"not-applicable"`.
24
+ */
25
+ export type ApprovalStatus = undefined | boolean | "not-applicable" | "approved" | "denied" | "user-approval" | {
26
+ readonly type: "not-applicable";
27
+ readonly reason?: never;
28
+ } | {
29
+ readonly type: "approved";
30
+ readonly reason?: string;
31
+ } | {
32
+ readonly type: "denied";
33
+ readonly reason?: string;
34
+ } | {
35
+ readonly type: "user-approval";
36
+ readonly reason?: never;
37
+ };
38
+ /** Shared approval policy used by authored tools and connections. */
39
+ export type Approval<TInput = Record<string, unknown>> = (ctx: ApprovalContext<TInput>) => ApprovalStatus | Promise<ApprovalStatus>;
40
+ export {};
@@ -0,0 +1 @@
1
+ export{};
@@ -1,5 +1,5 @@
1
1
  import type { ConnectionAuthDefinition, HeadersDefinition, ToolFilterDefinition } from "#runtime/connections/types.js";
2
- import type { NeedsApprovalContext } from "#public/definitions/tool.js";
2
+ import type { Approval } from "#public/definitions/approval.js";
3
3
  /**
4
4
  * Public definition for an MCP client connection authored in
5
5
  * `connections/*.ts`.
@@ -37,6 +37,8 @@ export interface McpClientConnectionDefinition {
37
37
  * - Three-method form: provide `startAuthorization` and
38
38
  * `completeAuthorization` together to opt into
39
39
  * interactive OAuth authorization.
40
+ * - Resolver form: pass `(ctx) => provider` to select either shape
41
+ * from the active caller's session context.
40
42
  *
41
43
  * Optional when `headers` is provided for non-Bearer auth schemes.
42
44
  */
@@ -52,12 +54,14 @@ export interface McpClientConnectionDefinition {
52
54
  * When omitted, tool calls execute without approval, consistent
53
55
  * with authored tools.
54
56
  */
55
- approval?: (ctx: NeedsApprovalContext) => boolean;
57
+ approval?: Approval;
56
58
  /**
57
59
  * Arbitrary HTTP headers sent with every request to the MCP server.
58
60
  *
59
61
  * Use for non-Bearer auth (e.g. API key headers) or server-level
60
- * configuration headers. Can be combined with `auth`.
62
+ * configuration headers. Can be combined with `auth`. The whole map
63
+ * or individual values may be callbacks that receive the active
64
+ * session context.
61
65
  */
62
66
  headers?: HeadersDefinition;
63
67
  /**
@@ -72,11 +76,9 @@ export interface McpClientConnectionDefinition {
72
76
  /**
73
77
  * Defines an MCP client connection.
74
78
  *
75
- * Validates the {@link ConnectionAuthDefinition} shape at
76
- * definition time, in particular the "both-or-neither" constraint
77
- * for `startAuthorization` and `completeAuthorization`: providing
78
- * exactly one is a definition error. `getToken` alone is valid and
79
- * selects the non-interactive flow; providing both opts into
80
- * interactive OAuth authorization.
79
+ * Validates static auth providers at definition time, in particular the
80
+ * "both-or-neither" constraint for `startAuthorization` and
81
+ * `completeAuthorization`. Context-aware auth resolvers are validated when
82
+ * eve invokes them inside an active turn.
81
83
  */
82
84
  export declare function defineMcpClientConnection(definition: McpClientConnectionDefinition): McpClientConnectionDefinition;
@@ -1 +1 @@
1
- import{stampConnectionProtocol}from"#public/definitions/connections/protocol.js";import{normalizeAuthorizationSpec}from"#runtime/connections/validate-authorization.js";import{stampDefinitionKey}from"#public/tool-result-narrowing.js";function defineMcpClientConnection(e){return e.auth!==void 0&&(e.auth=normalizeAuthorizationSpec(e.auth,`defineMcpClientConnection:`)),stampDefinitionKey(e,`connection:${e.url}`),stampConnectionProtocol(e,`mcp`),e}export{defineMcpClientConnection};
1
+ import{stampConnectionProtocol}from"#public/definitions/connections/protocol.js";import{normalizeAuthorizationSpec}from"#runtime/connections/validate-authorization.js";import{stampDefinitionKey}from"#public/tool-result-narrowing.js";function defineMcpClientConnection(e){return e.auth!==void 0&&typeof e.auth!=`function`&&(e.auth=normalizeAuthorizationSpec(e.auth,`defineMcpClientConnection:`)),stampDefinitionKey(e,`connection:${e.url}`),stampConnectionProtocol(e,`mcp`),e}export{defineMcpClientConnection};
@@ -1,5 +1,5 @@
1
1
  import type { ConnectionAuthDefinition, HeadersDefinition, ToolFilterDefinition } from "#runtime/connections/types.js";
2
- import type { NeedsApprovalContext } from "#public/definitions/tool.js";
2
+ import type { Approval } from "#public/definitions/approval.js";
3
3
  /**
4
4
  * The OpenAPI document backing the connection: either an HTTPS URL the
5
5
  * runtime fetches on first use, or an already-parsed OpenAPI 3.x /
@@ -59,6 +59,8 @@ export interface OpenAPIConnectionDefinition {
59
59
  * omitted.
60
60
  * - Three-method form: provide `startAuthorization` and
61
61
  * `completeAuthorization` together to opt into interactive OAuth.
62
+ * - Resolver form: pass `(ctx) => provider` to select either shape
63
+ * from the active caller's session context.
62
64
  *
63
65
  * Optional when `headers` is provided for non-Bearer auth schemes.
64
66
  */
@@ -71,12 +73,13 @@ export interface OpenAPIConnectionDefinition {
71
73
  * - `once()`: require approval only the first time per session
72
74
  * - `always()`: require approval for every tool call
73
75
  */
74
- approval?: (ctx: NeedsApprovalContext) => boolean;
76
+ approval?: Approval;
75
77
  /**
76
78
  * Arbitrary HTTP headers sent with every request to the API.
77
79
  *
78
80
  * Use for non-Bearer auth (e.g. API key headers) or configuration
79
- * headers. Can be combined with `auth`.
81
+ * headers. Can be combined with `auth`. The whole map or individual
82
+ * values may be callbacks that receive the active session context.
80
83
  */
81
84
  headers?: HeadersDefinition;
82
85
  /**
@@ -92,10 +95,9 @@ export interface OpenAPIConnectionDefinition {
92
95
  /**
93
96
  * Defines an OpenAPI connection.
94
97
  *
95
- * Validates the auth shape at definition time, in particular the
98
+ * Validates static auth providers at definition time, in particular the
96
99
  * "both-or-neither" constraint for `startAuthorization` and
97
- * `completeAuthorization`: providing exactly one is a definition error.
98
- * `getToken` alone is valid and selects the non-interactive flow;
99
- * providing both opts into interactive OAuth.
100
+ * `completeAuthorization`. Context-aware auth resolvers are validated when
101
+ * eve invokes them inside an active turn.
100
102
  */
101
103
  export declare function defineOpenAPIConnection(definition: OpenAPIConnectionDefinition): OpenAPIConnectionDefinition;
@@ -1 +1 @@
1
- import{stampConnectionProtocol}from"#public/definitions/connections/protocol.js";import{normalizeAuthorizationSpec}from"#runtime/connections/validate-authorization.js";import{stampDefinitionKey}from"#public/tool-result-narrowing.js";function defineOpenAPIConnection(e){return e.auth!==void 0&&(e.auth=normalizeAuthorizationSpec(e.auth,`defineOpenAPIConnection:`)),stampDefinitionKey(e,`connection:${e.baseUrl??(typeof e.spec==`string`?e.spec:e.description)}`),stampConnectionProtocol(e,`openapi`),e}export{defineOpenAPIConnection};
1
+ import{stampConnectionProtocol}from"#public/definitions/connections/protocol.js";import{normalizeAuthorizationSpec}from"#runtime/connections/validate-authorization.js";import{stampDefinitionKey}from"#public/tool-result-narrowing.js";function defineOpenAPIConnection(e){return e.auth!==void 0&&typeof e.auth!=`function`&&(e.auth=normalizeAuthorizationSpec(e.auth,`defineOpenAPIConnection:`)),stampDefinitionKey(e,`connection:${e.baseUrl??(typeof e.spec==`string`?e.spec:e.description)}`),stampConnectionProtocol(e,`openapi`),e}export{defineOpenAPIConnection};
@@ -1,24 +1,11 @@
1
1
  import type { StandardJSONSchemaV1 } from "#compiled/@standard-schema/spec/index.js";
2
2
  import type { PublicToolDefinition, ToolModelOutput } from "#shared/tool-definition.js";
3
3
  import type { SessionContext } from "#public/definitions/callback-context.js";
4
+ import type { Approval } from "#public/definitions/approval.js";
4
5
  import type { JsonObject } from "#shared/json.js";
5
6
  import type { AuthorizationDefinition, ConnectionAuthorizationContext, NonInteractiveAuthorizationDefinition, TokenResult } from "#runtime/connections/types.js";
6
7
  import { type DynamicEvents, type DynamicSentinel } from "#shared/dynamic-tool-definition.js";
7
- type ApprovalToolInput<TInput> = TInput extends object ? Readonly<TInput> : TInput;
8
8
  type ApprovalContextInput<TInput> = unknown extends TInput ? Record<string, unknown> : TInput;
9
- /**
10
- * Context passed to a tool's {@link ToolDefinition.needsApproval} function.
11
- *
12
- * `approvedTools` is the set of tool names (or compound approval keys)
13
- * already approved at least once in the current session. `toolName` is the
14
- * runtime name of the tool being evaluated. `toolInput` is the raw input the
15
- * model passed, available for input-aware decisions (e.g. per-connection scoping).
16
- */
17
- export interface NeedsApprovalContext<TInput = Record<string, unknown>> {
18
- readonly approvedTools: ReadonlySet<string>;
19
- readonly toolInput?: ApprovalToolInput<TInput>;
20
- readonly toolName: string;
21
- }
22
9
  export type { ToolModelOutput } from "#shared/tool-definition.js";
23
10
  /**
24
11
  * Authorization provider passed to {@link ToolContext.getToken} or
@@ -96,7 +83,7 @@ export type ToolDefinition<TInput = unknown, TOutput = unknown> = PublicToolDefi
96
83
  * - {@link never}: never require approval
97
84
  * - {@link once}: require approval only the first time per session
98
85
  */
99
- needsApproval?: (ctx: NeedsApprovalContext<ApprovalContextInput<TInput>>) => boolean;
86
+ approval?: Approval<ApprovalContextInput<TInput>>;
100
87
  /**
101
88
  * Optional projection controlling what the model sees as the tool result.
102
89
  * Receives the full `TOutput` from {@link execute} and returns the
@@ -121,7 +108,7 @@ export declare function defineTool<TInputSchema extends StandardJSONSchemaV1<unk
121
108
  inputSchema: TInputSchema;
122
109
  outputSchema: TOutputSchema;
123
110
  execute(input: StandardJSONSchemaV1.InferOutput<TInputSchema>, ctx: ToolContext): Promise<StandardJSONSchemaV1.InferOutput<TOutputSchema>> | StandardJSONSchemaV1.InferOutput<TOutputSchema>;
124
- needsApproval?: ToolDefinition<StandardJSONSchemaV1.InferOutput<TInputSchema>, unknown>["needsApproval"];
111
+ approval?: ToolDefinition<StandardJSONSchemaV1.InferOutput<TInputSchema>, unknown>["approval"];
125
112
  toModelOutput?: ToolDefinition<unknown, StandardJSONSchemaV1.InferOutput<TOutputSchema>>["toModelOutput"];
126
113
  }): ToolDefinition<StandardJSONSchemaV1.InferOutput<TInputSchema>, StandardJSONSchemaV1.InferOutput<TOutputSchema>>;
127
114
  export declare function defineTool<TSchema extends StandardJSONSchemaV1<unknown, unknown>, TOutput>(definition: {
@@ -129,7 +116,7 @@ export declare function defineTool<TSchema extends StandardJSONSchemaV1<unknown,
129
116
  inputSchema: TSchema;
130
117
  outputSchema?: JsonObject;
131
118
  execute(input: StandardJSONSchemaV1.InferOutput<TSchema>, ctx: ToolContext): Promise<TOutput> | TOutput;
132
- needsApproval?: ToolDefinition<StandardJSONSchemaV1.InferOutput<TSchema>, unknown>["needsApproval"];
119
+ approval?: ToolDefinition<StandardJSONSchemaV1.InferOutput<TSchema>, unknown>["approval"];
133
120
  toModelOutput?: ToolDefinition<unknown, TOutput>["toModelOutput"];
134
121
  }): ToolDefinition<StandardJSONSchemaV1.InferOutput<TSchema>, TOutput>;
135
122
  export declare function defineTool<TOutputSchema extends StandardJSONSchemaV1<unknown, unknown>>(definition: {
@@ -137,7 +124,7 @@ export declare function defineTool<TOutputSchema extends StandardJSONSchemaV1<un
137
124
  inputSchema: JsonObject;
138
125
  outputSchema: TOutputSchema;
139
126
  execute(input: Record<string, unknown>, ctx: ToolContext): Promise<StandardJSONSchemaV1.InferOutput<TOutputSchema>> | StandardJSONSchemaV1.InferOutput<TOutputSchema>;
140
- needsApproval?: ToolDefinition<Record<string, unknown>, unknown>["needsApproval"];
127
+ approval?: ToolDefinition<Record<string, unknown>, unknown>["approval"];
141
128
  toModelOutput?: ToolDefinition<unknown, StandardJSONSchemaV1.InferOutput<TOutputSchema>>["toModelOutput"];
142
129
  }): ToolDefinition<Record<string, unknown>, StandardJSONSchemaV1.InferOutput<TOutputSchema>>;
143
130
  export declare function defineTool<TOutput>(definition: {
@@ -145,7 +132,7 @@ export declare function defineTool<TOutput>(definition: {
145
132
  inputSchema: JsonObject;
146
133
  outputSchema?: JsonObject;
147
134
  execute(input: Record<string, unknown>, ctx: ToolContext): Promise<TOutput> | TOutput;
148
- needsApproval?: ToolDefinition<Record<string, unknown>, unknown>["needsApproval"];
135
+ approval?: ToolDefinition<Record<string, unknown>, unknown>["approval"];
149
136
  toModelOutput?: ToolDefinition<unknown, TOutput>["toModelOutput"];
150
137
  }): ToolDefinition<Record<string, unknown>, TOutput>;
151
138
  export declare function defineTool<TInput = unknown, TOutput = unknown>(definition: ToolDefinition<TInput, TOutput>): ToolDefinition<TInput, TOutput>;
@@ -237,7 +224,7 @@ export interface EnableWorkflowToolSentinel {
237
224
  readonly kind: typeof ENABLE_WORKFLOW_TOOL_SENTINEL_KIND;
238
225
  }
239
226
  /**
240
- * Opt-in marker for the framework `Workflow` tool, a code-mode sandbox whose
227
+ * Opt-in marker for the framework `Workflow` tool, an isolated JavaScript sandbox whose
241
228
  * only callable operations are this agent's subagents and remote agents, for
242
229
  * orchestrating them from model-authored JavaScript. Re-export it as the
243
230
  * default export of `agent/tools/workflow.ts`:
@@ -1,5 +1,5 @@
1
1
  /**
2
2
  * Core agent authoring helpers for `agent/agent.ts`.
3
3
  */
4
- export { type AgentCompactionDefinition, type AgentDefinition, type AgentExperimentalDefinition, type AgentModelDefinition, type AgentModelOptionsDefinition, type AgentWorkflowDefinition, type AgentWorkflowWorldDefinition, defineAgent, } from "#public/definitions/agent.js";
4
+ export { type AgentCompactionDefinition, type AgentDefinition, type AgentExperimentalDefinition, type AgentModelDefinition, type AgentModelOptionsDefinition, type AgentReasoningDefinition, type AgentWorkflowDefinition, type AgentWorkflowWorldDefinition, defineAgent, } from "#public/definitions/agent.js";
5
5
  export { type RemoteAgentDefinition, type RemoteAgentDefinitionInput, defineRemoteAgent, } from "#public/definitions/remote-agent.js";
@@ -1,19 +1,19 @@
1
- import type { NeedsApprovalContext } from "#public/definitions/tool.js";
1
+ import type { Approval } from "#public/definitions/approval.js";
2
2
  /**
3
- * Returns a `needsApproval` callback that always requires user approval before
3
+ * Returns an `approval` callback that always requires user approval before
4
4
  * the tool executes.
5
5
  */
6
- export declare function always<TInput = unknown>(): (ctx: NeedsApprovalContext<TInput>) => boolean;
6
+ export declare function always<TInput = unknown>(): Approval<TInput>;
7
7
  /**
8
- * Returns a `needsApproval` callback that never requires user approval before
8
+ * Returns an `approval` callback that never requires user approval before
9
9
  * the tool executes.
10
10
  */
11
- export declare function never<TInput = unknown>(): (ctx: NeedsApprovalContext<TInput>) => boolean;
11
+ export declare function never<TInput = unknown>(): Approval<TInput>;
12
12
  /**
13
- * Returns a `needsApproval` callback that requires approval until the user
13
+ * Returns an `approval` callback that requires approval until the user
14
14
  * approves this tool once in the current session. A tool is recorded as
15
15
  * approved only on an explicit approval; a denial (or continuing without
16
16
  * responding) leaves it unrecorded, so the next call prompts again. Keys off
17
17
  * the bare tool name, so it ignores compound approval keys.
18
18
  */
19
- export declare function once<TInput = unknown>(): (ctx: NeedsApprovalContext<TInput>) => boolean;
19
+ export declare function once<TInput = unknown>(): Approval<TInput>;
@@ -1 +1 @@
1
- function always(){return()=>!0}function never(){return()=>!1}function once(){return({approvedTools:e,toolName:t})=>!e.has(t)}export{always,never,once};
1
+ function always(){return()=>`user-approval`}function never(){return()=>`not-applicable`}function once(){return({approvedTools:e,toolName:t})=>e.has(t)?`not-applicable`:`user-approval`}export{always,never,once};
@@ -1,5 +1,5 @@
1
1
  /**
2
2
  * Per-tool approval helpers used inside `agent/tools/*.ts` files.
3
3
  */
4
- export type { NeedsApprovalContext } from "#public/definitions/tool.js";
4
+ export type { Approval, ApprovalContext, ApprovalStatus } from "#public/definitions/approval.js";
5
5
  export { always, never, once } from "#public/tools/approval/approval-helpers.js";
@@ -1,7 +1,8 @@
1
1
  /**
2
2
  * Tool authoring helpers for `agent/tools/*.ts` files.
3
3
  */
4
- export { type DisabledToolSentinel, type EnableWorkflowToolSentinel, defineDynamic, defineTool, disableTool, isDisabledToolSentinel, isEnableWorkflowToolSentinel, type NeedsApprovalContext, type ToolAuthOptions, type ToolAuthProvider, type ToolDefinition, type ToolContext, type ToolModelOutput, ExperimentalWorkflow, } from "#public/definitions/tool.js";
4
+ export { type DisabledToolSentinel, type EnableWorkflowToolSentinel, defineDynamic, defineTool, disableTool, isDisabledToolSentinel, isEnableWorkflowToolSentinel, type ToolAuthOptions, type ToolAuthProvider, type ToolDefinition, type ToolContext, type ToolModelOutput, ExperimentalWorkflow, } from "#public/definitions/tool.js";
5
+ export type { Approval, ApprovalContext, ApprovalStatus } from "#public/definitions/approval.js";
5
6
  export type { DynamicToolEntry, DynamicEvents, DynamicToolEvents, DynamicResolveContext, DynamicSentinel, DynamicToolSet, DynamicToolResult, } from "#shared/dynamic-tool-definition.js";
6
7
  export { type SessionContext } from "#public/definitions/callback-context.js";
7
8
  export { toolResultFrom, type MatchedConnectionResult, type MatchedToolResult, type ToolResultFromFn, } from "#public/tool-result-narrowing.js";
@@ -1 +1 @@
1
- function toPublicToolDefinition(e){if(!e.execute)throw Error(`Tool "${e.name}" is client-side and cannot be re-exported publicly.`);let t=e.execute,n=e.inputSchema,r={description:e.description,execute:e=>t(e),inputSchema:n??{},outputSchema:e.outputSchema};return e.needsApproval!==void 0&&(r.needsApproval=e.needsApproval),r}export{toPublicToolDefinition};
1
+ function toPublicToolDefinition(e){if(!e.execute)throw Error(`Tool "${e.name}" is client-side and cannot be re-exported publicly.`);let t=e.execute,n=e.inputSchema,r={description:e.description,execute:e=>t(e),inputSchema:n??{},outputSchema:e.outputSchema};return e.approval!==void 0&&(r.approval=e.approval),r}export{toPublicToolDefinition};
@@ -26,6 +26,7 @@ export interface RuntimeTurnAgent {
26
26
  readonly model: RuntimeModelReference;
27
27
  readonly nodeId?: string;
28
28
  readonly outputSchema?: ResolvedAgent["config"]["outputSchema"];
29
+ readonly reasoning?: ResolvedAgent["config"]["reasoning"];
29
30
  readonly tools: readonly PreparedRuntimeTool[];
30
31
  readonly workspaceSpec: WorkspaceRuntimeSpec;
31
32
  }
@@ -1 +1 @@
1
- import{composeRuntimeBasePrompt}from"#runtime/prompt/compose.js";const BOOTSTRAP_RUNTIME_MODEL_ID=`eve-bootstrap-model`,BOOTSTRAP_RUNTIME_SYSTEM_PROMPT=`You are the eve bootstrap agent. Be concise, stay grounded in the current conversation, and do not assume tools are available unless the runtime provides them.`;function createResolvedRuntimeTurnAgent(e){let t=e.agent;return{id:t.config.name,instructions:composeRuntimeBasePrompt({connections:t.connections,instructions:t.instructions,skills:t.skills,toolsAvailable:e.tools.length>0,workspaceSpec:t.workspaceSpec}),compactionModel:t.config.compaction?.model,model:t.config.model,nodeId:e.nodeId,outputSchema:t.config.outputSchema,tools:[...e.tools],workspaceSpec:t.workspaceSpec}}export{BOOTSTRAP_RUNTIME_MODEL_ID,BOOTSTRAP_RUNTIME_SYSTEM_PROMPT,createResolvedRuntimeTurnAgent};
1
+ import{composeRuntimeBasePrompt}from"#runtime/prompt/compose.js";const BOOTSTRAP_RUNTIME_MODEL_ID=`eve-bootstrap-model`,BOOTSTRAP_RUNTIME_SYSTEM_PROMPT=`You are the eve bootstrap agent. Be concise, stay grounded in the current conversation, and do not assume tools are available unless the runtime provides them.`;function createResolvedRuntimeTurnAgent(e){let t=e.agent;return{id:t.config.name,instructions:composeRuntimeBasePrompt({connections:t.connections,instructions:t.instructions,skills:t.skills,toolsAvailable:e.tools.length>0,workspaceSpec:t.workspaceSpec}),compactionModel:t.config.compaction?.model,model:t.config.model,nodeId:e.nodeId,outputSchema:t.config.outputSchema,reasoning:t.config.reasoning,tools:[...e.tools],workspaceSpec:t.workspaceSpec}}export{BOOTSTRAP_RUNTIME_MODEL_ID,BOOTSTRAP_RUNTIME_SYSTEM_PROMPT,createResolvedRuntimeTurnAgent};
@@ -1,5 +1,4 @@
1
- import{z}from"#compiled/zod/index.js";import{LOAD_SKILL_TOOL_NAME}from"#runtime/skills/fragment-context.js";import{CODE_MODE_TOOL_NAME}from"#shared/code-mode.js";import{FINAL_OUTPUT_TOOL_NAME}from"#runtime/framework-tools/final-output.js";import{MockLanguageModelV3}from"ai/test";import{BOOTSTRAP_RUNTIME_MODEL_ID,BOOTSTRAP_RUNTIME_SYSTEM_PROMPT}from"#runtime/agent/bootstrap.js";import{createBootstrapGenerateResult,createBootstrapStreamResult,estimateTokenCount,getLastUserPromptText,getPromptContentText,getPromptText}from"#runtime/agent/bootstrap-model-utils.js";import{createMockAuthoredToolInput,formatToolOutput,resolveMockFixtureToken,resolveWeatherCity}from"#runtime/agent/mock-model-fixtures.js";import{findRelevantSkill,getActivatedSkillIds,getAvailableSkills}from"#runtime/agent/mock-model-skill-selection.js";import{createJsonSchemaSample}from"#runtime/agent/mock-structured-output.js";const authoredRuntimeModelMocks=new Map,bootstrapWeatherPayloadSchema=z.object({city:z.string(),condition:z.string(),summary:z.string(),temperatureF:z.number().finite()}).strict();function shouldMockAuthoredRuntimeModels(){return process.env.NODE_ENV===`test`}function createMockAuthoredRuntimeModel(e){let t=authoredRuntimeModelMocks.get(e.id);if(t!==void 0)return t;let n=new MockLanguageModelV3({modelId:e.id,provider:`eve-runtime-mock`,doGenerate:async t=>createMockModelResult(t,e.id),doStream:async t=>createBootstrapStreamResult(createMockModelResult(t,e.id))});return authoredRuntimeModelMocks.set(e.id,n),n}function createMockModelResult(e,t){let n=getLastAuthoredToolResult(e.prompt);if(n!==null){let r=createFollowUpToolCallResult({modelId:t,options:e,result:n});if(r!==null)return r}else{let n=createSkillLoadResult(e.prompt,t)??createAuthoredToolCallResult(e,t);if(n!==null)return n}let r=createFinalOutputResult(e,t);if(r!==null)return r;let i=n===null?createAssistantMessage(e.prompt):formatToolResultReply(n,e.prompt);return createBootstrapGenerateResult({inputTokens:estimateTokenCount(getPromptText(e.prompt)),modelId:t,outputTokens:estimateTokenCount(i),text:i})}function createFinalOutputResult(e,t){let n=getAvailableTools(e).find(e=>e.name===FINAL_OUTPUT_TOOL_NAME);if(n===void 0)return null;let i=createJsonSchemaSample(n.inputSchema);return createToolCallGenerateResult({input:i,inputTokens:estimateTokenCount(getPromptText(e.prompt)),modelId:t,outputTokens:estimateTokenCount(JSON.stringify(i)),toolCallId:createToolCallId(FINAL_OUTPUT_TOOL_NAME),toolName:FINAL_OUTPUT_TOOL_NAME})}function resolveMockAuthoredRuntimeModel(e){return!shouldMockAuthoredRuntimeModels()||e.id===BOOTSTRAP_RUNTIME_MODEL_ID?null:createMockAuthoredRuntimeModel(e)}function createSkillLoadResult(e,n){let r=getLastUserPromptText(e);if(r===null||getActivatedSkillIds(e).length>0)return null;let i=findRelevantSkill(getAvailableSkills(e),r);return i===null?null:createToolCallGenerateResult({input:{skill:i.name},inputTokens:estimateTokenCount(getPromptText(e)),modelId:n,outputTokens:estimateTokenCount(i.name),toolCallId:`call_load_skill`,toolName:LOAD_SKILL_TOOL_NAME})}function createAuthoredToolCallResult(e,t){let r=getLastUserPromptText(e.prompt);if(r===null)return null;let i=findRelevantTool(getAvailableTools(e),r);if(i===null)return null;let a=resolveWeatherCity(r),o=createMockAuthoredToolInput(i,r,a);if(i.name===CODE_MODE_TOOL_NAME){let n=findRelevantCodeModeHostTool(i.description,r);if(n===null)return null;let o=`return await tools${formatCodeModeToolAccess(n)}({ city: ${JSON.stringify(a)} });`;return createToolCallGenerateResult({input:{js:o},inputTokens:estimateTokenCount(getPromptText(e.prompt)),modelId:t,outputTokens:estimateTokenCount(o),toolCallId:createToolCallId(i.name),toolName:i.name})}return createToolCallGenerateResult({input:o,inputTokens:estimateTokenCount(getPromptText(e.prompt)),modelId:t,outputTokens:estimateTokenCount(Object.values(o).join(` `)),toolCallId:createToolCallId(i.name),toolName:i.name})}function createFollowUpToolCallResult(e){let t=findNextExplicitToolAfterResult({previousToolName:e.result.toolName,prompt:e.options.prompt,tools:getAvailableTools(e.options)});if(t===null)return null;let n=createFollowUpToolInput(e.result.output);return n===null?null:createToolCallGenerateResult({input:n,inputTokens:estimateTokenCount(getPromptText(e.options.prompt)),modelId:e.modelId,outputTokens:estimateTokenCount(Object.values(n).join(` `)),toolCallId:createToolCallId(t.name),toolName:t.name})}function createAssistantMessage(e){let t=getLastUserPromptText(e)??`Hello from eve`,n=getSystemPromptLabels(e),r=resolveSystemProbe(e),i=resolveMockFixtureToken(e);return i===null?n.length>0?r===null?`Bootstrap reply [${n.join(`, `)}]: ${t}`:`Bootstrap reply [${n.join(`, `)}; probe=${r}]: ${t}`:r===null?`Bootstrap reply: ${t}`:`Bootstrap reply [probe=${r}]: ${t}`:i}function formatToolResultReply(e,t){if(e.isError)return`Local weather tool failed: ${formatToolOutput(e.output)}`;if(isWeatherPayload(e.output))return`Used local weather tool for ${e.output.city}: ${e.output.condition}, ${e.output.temperatureF}F. ${e.output.summary}`;let n=getLastUserPromptText(t)??`Hello from eve`;return`Used ${e.toolName} for "${n}": ${formatToolOutput(e.output)}`}function createToolCallGenerateResult(e){return{content:[{input:JSON.stringify(e.input),toolCallId:e.toolCallId,toolName:e.toolName,type:`tool-call`}],finishReason:{raw:void 0,unified:`tool-calls`},response:{id:`bootstrap-response`,modelId:e.modelId,timestamp:new Date(`2026-03-16T00:00:00.000Z`)},usage:{inputTokens:{cacheRead:0,cacheWrite:0,noCache:e.inputTokens,total:e.inputTokens},outputTokens:{reasoning:0,text:e.outputTokens,total:e.outputTokens}},warnings:[]}}function getAvailableTools(e){return(e.tools??[]).flatMap(e=>e.type===`function`?[{description:e.description,inputSchema:`inputSchema`in e?e.inputSchema:void 0,name:e.name,outputSchema:`outputSchema`in e?e.outputSchema:void 0}]:[])}function getLastAuthoredToolResult(e){for(let n of[...e].reverse()){if(n.role===`user`)return null;if(!(n.role!==`tool`&&n.role!==`assistant`)){for(let e of[...n.content].reverse())if(!(typeof e==`string`||e.type!==`tool-result`)&&e.toolName!==LOAD_SKILL_TOOL_NAME)return{isError:e.output.type===`error-json`||e.output.type===`error-text`||e.output.type===`execution-denied`,output:e.output.type===`execution-denied`?{reason:e.output.reason??null,type:e.output.type}:e.output.value,toolCallId:e.toolCallId,toolName:e.toolName}}}return null}function findNextExplicitToolAfterResult(e){let t=getLastUserPromptText(e.prompt);if(t===null)return null;let n=normalizeText(t),r=n.indexOf(normalizeText(e.previousToolName));return r<0?null:e.tools.filter(t=>t.name!==e.previousToolName).flatMap(e=>{let t=n.indexOf(normalizeText(e.name),r+1);return t<0?[]:[{index:t,tool:e}]}).sort((e,t)=>e.index-t.index)[0]?.tool??null}function createFollowUpToolInput(e){return isRecord(e)&&typeof e.stepKey==`string`?{stepKey:e.stepKey}:null}function getSystemPromptLabels(e){let t=e.filter(e=>e.role===`system`);if(t.length===0)return[];let n=t.flatMap(e=>{let t=getPromptContentText(e.content);if(t.startsWith(`Available skills
1
+ import{z}from"#compiled/zod/index.js";import{LOAD_SKILL_TOOL_NAME}from"#runtime/skills/fragment-context.js";import{FINAL_OUTPUT_TOOL_NAME}from"#runtime/framework-tools/final-output.js";import{MockLanguageModelV3}from"ai/test";import{BOOTSTRAP_RUNTIME_MODEL_ID,BOOTSTRAP_RUNTIME_SYSTEM_PROMPT}from"#runtime/agent/bootstrap.js";import{createBootstrapGenerateResult,createBootstrapStreamResult,estimateTokenCount,getLastUserPromptText,getPromptContentText,getPromptText}from"#runtime/agent/bootstrap-model-utils.js";import{createMockAuthoredToolInput,formatToolOutput,resolveMockFixtureToken,resolveWeatherCity}from"#runtime/agent/mock-model-fixtures.js";import{findRelevantSkill,getActivatedSkillIds,getAvailableSkills}from"#runtime/agent/mock-model-skill-selection.js";import{createJsonSchemaSample}from"#runtime/agent/mock-structured-output.js";const authoredRuntimeModelMocks=new Map,bootstrapWeatherPayloadSchema=z.object({city:z.string(),condition:z.string(),summary:z.string(),temperatureF:z.number().finite()}).strict();function shouldMockAuthoredRuntimeModels(){return process.env.NODE_ENV===`test`}function createMockAuthoredRuntimeModel(e){let t=authoredRuntimeModelMocks.get(e.id);if(t!==void 0)return t;let n=new MockLanguageModelV3({modelId:e.id,provider:`eve-runtime-mock`,doGenerate:async t=>createMockModelResult(t,e.id),doStream:async t=>createBootstrapStreamResult(createMockModelResult(t,e.id))});return authoredRuntimeModelMocks.set(e.id,n),n}function createMockModelResult(e,t){let n=getLastAuthoredToolResult(e.prompt);if(n!==null){let r=createFollowUpToolCallResult({modelId:t,options:e,result:n});if(r!==null)return r}else{let n=createSkillLoadResult(e.prompt,t)??createAuthoredToolCallResult(e,t);if(n!==null)return n}let r=createFinalOutputResult(e,t);if(r!==null)return r;let i=n===null?createAssistantMessage(e.prompt):formatToolResultReply(n,e.prompt);return createBootstrapGenerateResult({inputTokens:estimateTokenCount(getPromptText(e.prompt)),modelId:t,outputTokens:estimateTokenCount(i),text:i})}function createFinalOutputResult(e,t){let r=getAvailableTools(e).find(e=>e.name===FINAL_OUTPUT_TOOL_NAME);if(r===void 0)return null;let i=createJsonSchemaSample(r.inputSchema);return createToolCallGenerateResult({input:i,inputTokens:estimateTokenCount(getPromptText(e.prompt)),modelId:t,outputTokens:estimateTokenCount(JSON.stringify(i)),toolCallId:createToolCallId(FINAL_OUTPUT_TOOL_NAME),toolName:FINAL_OUTPUT_TOOL_NAME})}function resolveMockAuthoredRuntimeModel(e){return!shouldMockAuthoredRuntimeModels()||e.id===BOOTSTRAP_RUNTIME_MODEL_ID?null:createMockAuthoredRuntimeModel(e)}function createSkillLoadResult(e,n){let r=getLastUserPromptText(e);if(r===null||getActivatedSkillIds(e).length>0)return null;let i=findRelevantSkill(getAvailableSkills(e),r);return i===null?null:createToolCallGenerateResult({input:{skill:i.name},inputTokens:estimateTokenCount(getPromptText(e)),modelId:n,outputTokens:estimateTokenCount(i.name),toolCallId:`call_load_skill`,toolName:LOAD_SKILL_TOOL_NAME})}function createAuthoredToolCallResult(e,t){let n=getLastUserPromptText(e.prompt);if(n===null)return null;let r=findRelevantTool(getAvailableTools(e),n);if(r===null)return null;let i=createMockAuthoredToolInput(r,n,resolveWeatherCity(n));return createToolCallGenerateResult({input:i,inputTokens:estimateTokenCount(getPromptText(e.prompt)),modelId:t,outputTokens:estimateTokenCount(Object.values(i).join(` `)),toolCallId:createToolCallId(r.name),toolName:r.name})}function createFollowUpToolCallResult(e){let t=findNextExplicitToolAfterResult({previousToolName:e.result.toolName,prompt:e.options.prompt,tools:getAvailableTools(e.options)});if(t===null)return null;let n=createFollowUpToolInput(e.result.output);return n===null?null:createToolCallGenerateResult({input:n,inputTokens:estimateTokenCount(getPromptText(e.options.prompt)),modelId:e.modelId,outputTokens:estimateTokenCount(Object.values(n).join(` `)),toolCallId:createToolCallId(t.name),toolName:t.name})}function createAssistantMessage(e){let t=getLastUserPromptText(e)??`Hello from eve`,n=getSystemPromptLabels(e),r=resolveSystemProbe(e),i=resolveMockFixtureToken(e);return i===null?n.length>0?r===null?`Bootstrap reply [${n.join(`, `)}]: ${t}`:`Bootstrap reply [${n.join(`, `)}; probe=${r}]: ${t}`:r===null?`Bootstrap reply: ${t}`:`Bootstrap reply [probe=${r}]: ${t}`:i}function formatToolResultReply(e,t){if(e.isError)return`Local weather tool failed: ${formatToolOutput(e.output)}`;if(isWeatherPayload(e.output))return`Used local weather tool for ${e.output.city}: ${e.output.condition}, ${e.output.temperatureF}F. ${e.output.summary}`;let n=getLastUserPromptText(t)??`Hello from eve`;return`Used ${e.toolName} for "${n}": ${formatToolOutput(e.output)}`}function createToolCallGenerateResult(e){return{content:[{input:JSON.stringify(e.input),toolCallId:e.toolCallId,toolName:e.toolName,type:`tool-call`}],finishReason:{raw:void 0,unified:`tool-calls`},response:{id:`bootstrap-response`,modelId:e.modelId,timestamp:new Date(`2026-03-16T00:00:00.000Z`)},usage:{inputTokens:{cacheRead:0,cacheWrite:0,noCache:e.inputTokens,total:e.inputTokens},outputTokens:{reasoning:0,text:e.outputTokens,total:e.outputTokens}},warnings:[]}}function getAvailableTools(e){return(e.tools??[]).flatMap(e=>e.type===`function`?[{description:e.description,inputSchema:`inputSchema`in e?e.inputSchema:void 0,name:e.name,outputSchema:`outputSchema`in e?e.outputSchema:void 0}]:[])}function getLastAuthoredToolResult(e){for(let n of[...e].reverse()){if(n.role===`user`)return null;if(!(n.role!==`tool`&&n.role!==`assistant`)){for(let e of[...n.content].reverse())if(!(typeof e==`string`||e.type!==`tool-result`)&&e.toolName!==LOAD_SKILL_TOOL_NAME)return{isError:e.output.type===`error-json`||e.output.type===`error-text`||e.output.type===`execution-denied`,output:e.output.type===`execution-denied`?{reason:e.output.reason??null,type:e.output.type}:e.output.value,toolCallId:e.toolCallId,toolName:e.toolName}}}return null}function findNextExplicitToolAfterResult(e){let t=getLastUserPromptText(e.prompt);if(t===null)return null;let n=normalizeText(t),r=n.indexOf(normalizeText(e.previousToolName));return r<0?null:e.tools.filter(t=>t.name!==e.previousToolName).flatMap(e=>{let t=n.indexOf(normalizeText(e.name),r+1);return t<0?[]:[{index:t,tool:e}]}).sort((e,t)=>e.index-t.index)[0]?.tool??null}function createFollowUpToolInput(e){return isRecord(e)&&typeof e.stepKey==`string`?{stepKey:e.stepKey}:null}function getSystemPromptLabels(e){let t=e.filter(e=>e.role===`system`);if(t.length===0)return[];let n=t.flatMap(e=>{let t=getPromptContentText(e.content);if(t.startsWith(`Available skills
2
2
  `))return[];let n=t.split(`
3
- `).map(e=>e.trim()).filter(e=>e.length>0),r=[];for(let e of n){if(e===BOOTSTRAP_RUNTIME_SYSTEM_PROMPT||e===`Available skills`)continue;let t=/^System \((.+)\)$/.exec(e);if(t?.[1]){r.push(t[1]);continue}let n=/^Skill \((.+)\)$/.exec(e);n?.[1]&&r.push(n[1])}if(r.length>0)return r;let i=n.find(e=>e!==BOOTSTRAP_RUNTIME_SYSTEM_PROMPT&&e!==`Available skills`);return i===void 0?[]:[i]});return[...new Set(n)]}function findRelevantTool(e,n){let r=normalizeText(n),i=e.find(e=>e.name!==`agent`&&e.name!==LOAD_SKILL_TOOL_NAME&&r.includes(normalizeText(e.name)));return i===void 0?/\b(forecast|temperature|weather|wind|rain|snow)\b/u.test(r)?e.find(e=>/\b(forecast|temperature|weather|wind|rain|snow)\b/u.test(normalizeText(`${e.name} ${e.description??``}`)))??null:null:i}function findRelevantCodeModeHostTool(e,t){return e===void 0?null:findRelevantTool(parseCodeModeHostTools(e),t)?.name??null}function parseCodeModeHostTools(e){let t=[],n;for(let r of e.split(`
4
- `)){let e=/^\s*\/\*\*\s*(.*?)\s*\*\/\s*$/u.exec(r);if(e?.[1]!==void 0){n=e[1];continue}let i=/^\s*(?:([$A-Z_a-z][$\w]*)|(["'])(.*?)\2)\s*:\s*\(input:/u.exec(r),a=i?.[1]??i?.[3];a!==void 0&&(t.push({description:n,name:a}),n=void 0)}return t}function formatCodeModeToolAccess(e){return/^[$A-Z_a-z][$\w]*$/u.test(e)?`.${e}`:`[${JSON.stringify(e)}]`}function normalizeText(e){return e.toLowerCase().replace(/[^a-z0-9]+/gu,` `).trim()}function createToolCallId(e){return`call_${e.toLowerCase().replace(/[^a-z0-9]+/gu,`_`).replace(/^_+|_+$/gu,``)||`tool`}`}function resolveSystemProbe(e){let t=e.filter(e=>e.role===`system`).map(e=>getPromptContentText(e.content)).join(`
3
+ `).map(e=>e.trim()).filter(e=>e.length>0),r=[];for(let e of n){if(e===BOOTSTRAP_RUNTIME_SYSTEM_PROMPT||e===`Available skills`)continue;let t=/^System \((.+)\)$/.exec(e);if(t?.[1]){r.push(t[1]);continue}let n=/^Skill \((.+)\)$/.exec(e);n?.[1]&&r.push(n[1])}if(r.length>0)return r;let i=n.find(e=>e!==BOOTSTRAP_RUNTIME_SYSTEM_PROMPT&&e!==`Available skills`);return i===void 0?[]:[i]});return[...new Set(n)]}function findRelevantTool(e,n){let r=normalizeText(n),i=e.find(e=>e.name!==`agent`&&e.name!==LOAD_SKILL_TOOL_NAME&&r.includes(normalizeText(e.name)));return i===void 0?/\b(forecast|temperature|weather|wind|rain|snow)\b/u.test(r)?e.find(e=>/\b(forecast|temperature|weather|wind|rain|snow)\b/u.test(normalizeText(`${e.name} ${e.description??``}`)))??null:null:i}function normalizeText(e){return e.toLowerCase().replace(/[^a-z0-9]+/gu,` `).trim()}function createToolCallId(e){return`call_${e.toLowerCase().replace(/[^a-z0-9]+/gu,`_`).replace(/^_+|_+$/gu,``)||`tool`}`}function resolveSystemProbe(e){let t=e.filter(e=>e.role===`system`).map(e=>getPromptContentText(e.content)).join(`
5
4
  `);return/hmr-probe:\s*([^\n]+)/iu.exec(t)?.[1]?.trim()||null}function isWeatherPayload(e){return bootstrapWeatherPayloadSchema.safeParse(e).success}function isRecord(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}export{createMockAuthoredRuntimeModel,resolveMockAuthoredRuntimeModel,shouldMockAuthoredRuntimeModels};