eve 0.22.1 → 0.22.2

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 (95) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/dist/src/cli/commands/init-repl.d.ts +6 -5
  3. package/dist/src/compiled/.vendor-stamp.json +6 -4
  4. package/dist/src/compiled/@workflow/core/create-hook.d.ts +2 -2
  5. package/dist/src/compiled/@workflow/core/events-consumer.d.ts +1 -1
  6. package/dist/src/compiled/@workflow/core/index.js +2 -2
  7. package/dist/src/compiled/@workflow/core/private.js +1 -1
  8. package/dist/src/compiled/@workflow/core/runtime/constants.d.ts +14 -0
  9. package/dist/src/compiled/@workflow/core/runtime/get-world-lazy.d.ts +3 -12
  10. package/dist/src/compiled/@workflow/core/runtime/wait-continuation.d.ts +2 -2
  11. package/dist/src/compiled/@workflow/core/runtime/world-compatibility.d.ts +5 -0
  12. package/dist/src/compiled/@workflow/core/runtime/world-init.d.ts +16 -41
  13. package/dist/src/compiled/@workflow/core/runtime/world-target.d.ts +11 -0
  14. package/dist/src/compiled/@workflow/core/runtime/world.d.ts +21 -9
  15. package/dist/src/compiled/@workflow/core/runtime.d.ts +2 -1
  16. package/dist/src/compiled/@workflow/core/runtime.js +3 -141
  17. package/dist/src/compiled/@workflow/core/version.d.ts +1 -1
  18. package/dist/src/compiled/@workflow/core/workflow/world-init-stub.d.ts +2 -2
  19. package/dist/src/compiled/@workflow/core/workflow.js +1 -1
  20. package/dist/src/compiled/@workflow/errors/index.js +1 -1
  21. package/dist/src/compiled/@workflow/world/analytics.d.ts +182 -0
  22. package/dist/src/compiled/@workflow/world/env-config.d.ts +39 -0
  23. package/dist/src/compiled/@workflow/world/events.d.ts +25 -0
  24. package/dist/src/compiled/@workflow/world/index.d.ts +6 -3
  25. package/dist/src/compiled/@workflow/world/interfaces.d.ts +14 -7
  26. package/dist/src/compiled/@workflow/world/runs.d.ts +9 -1
  27. package/dist/src/compiled/@workflow/world/shared.d.ts +15 -0
  28. package/dist/src/compiled/@workflow/world/steps.d.ts +8 -0
  29. package/dist/src/compiled/@workflow/world-local/LICENSE.md +201 -0
  30. package/dist/src/compiled/@workflow/world-local/index.js +4 -0
  31. package/dist/src/compiled/@workflow/world-vercel/LICENSE.md +201 -0
  32. package/dist/src/compiled/@workflow/world-vercel/index.js +42 -0
  33. package/dist/src/compiled/_chunks/workflow/attribute-changes-BnKD8Y3m.js +20 -0
  34. package/dist/src/compiled/_chunks/workflow/{dist-FLIfyJ4Y.js → dist-CttsoN4D.js} +1 -1
  35. package/dist/src/compiled/_chunks/workflow/dist-DJU_7R9s.js +40 -0
  36. package/dist/src/compiled/_chunks/workflow/dist-DpDDcpTl.js +3 -0
  37. package/dist/src/compiled/_chunks/workflow/resume-hook-DjPY9VGg.js +1 -0
  38. package/dist/src/compiled/_chunks/workflow/run-BSANnUPR.js +1 -0
  39. package/dist/src/compiled/_chunks/workflow/sleep-phozDCW8.js +1 -0
  40. package/dist/src/compiled/_chunks/workflow/token-CaY0nA5J.js +1 -0
  41. package/dist/src/compiled/_chunks/workflow/token-D4VIwGlD.js +1 -0
  42. package/dist/src/compiled/_chunks/workflow/undici-fb54XL8i.js +95 -0
  43. package/dist/src/harness/emission.js +1 -1
  44. package/dist/src/harness/model-call-error.d.ts +5 -0
  45. package/dist/src/harness/model-call-error.js +1 -1
  46. package/dist/src/harness/prompt-cache.d.ts +18 -9
  47. package/dist/src/harness/prompt-cache.js +1 -1
  48. package/dist/src/harness/tool-loop.js +1 -1
  49. package/dist/src/internal/application/compiled-artifacts.d.ts +4 -0
  50. package/dist/src/internal/application/compiled-artifacts.js +5 -4
  51. package/dist/src/internal/application/package.d.ts +9 -5
  52. package/dist/src/internal/application/package.js +1 -1
  53. package/dist/src/internal/nitro/host/configure-nitro-routes.js +2 -2
  54. package/dist/src/internal/nitro/host/create-application-nitro.js +1 -1
  55. package/dist/src/internal/nitro/routes/health.d.ts +3 -3
  56. package/dist/src/internal/workflow/runtime.js +1 -1
  57. package/dist/src/internal/workflow/validate-world.d.ts +16 -0
  58. package/dist/src/internal/workflow/validate-world.js +1 -0
  59. package/dist/src/internal/workflow/world-compatibility.d.ts +1 -12
  60. package/dist/src/node_modules/.pnpm/@workflow_utils@5.0.0-beta.6/node_modules/@workflow/utils/dist/index.js +1 -0
  61. package/dist/src/node_modules/.pnpm/@workflow_utils@5.0.0-beta.6/node_modules/@workflow/utils/dist/parse-name.js +1 -0
  62. package/dist/src/node_modules/.pnpm/@workflow_utils@5.0.0-beta.6/node_modules/@workflow/utils/dist/pluralize.js +1 -0
  63. package/dist/src/node_modules/.pnpm/@workflow_utils@5.0.0-beta.6/node_modules/@workflow/utils/dist/promise.js +1 -0
  64. package/dist/src/node_modules/.pnpm/@workflow_utils@5.0.0-beta.6/node_modules/@workflow/utils/dist/time.js +1 -0
  65. package/dist/src/node_modules/.pnpm/@workflow_utils@5.0.0-beta.6/node_modules/@workflow/utils/dist/workflow-routes.js +1 -0
  66. package/dist/src/node_modules/.pnpm/@workflow_utils@5.0.0-beta.6/node_modules/@workflow/utils/dist/world-target.js +1 -0
  67. package/dist/src/node_modules/.pnpm/ms@2.1.3/node_modules/ms/index.js +1 -0
  68. package/dist/src/public/channels/slack/action-status.d.ts +19 -0
  69. package/dist/src/public/channels/slack/action-status.js +1 -0
  70. package/dist/src/public/channels/slack/defaults.js +2 -2
  71. package/dist/src/public/channels/slack/index.d.ts +1 -0
  72. package/dist/src/public/channels/slack/index.js +1 -1
  73. package/dist/src/public/channels/slack/slackChannel.d.ts +1 -1
  74. package/dist/src/public/next/index.d.ts +9 -9
  75. package/dist/src/public/next/index.js +1 -1
  76. package/dist/src/public/next/vercel-output-config.js +1 -1
  77. package/dist/src/setup/scaffold/create/project.js +2 -2
  78. package/docs/agent-config.md +1 -1
  79. package/docs/channels/github.mdx +35 -2
  80. package/docs/channels/linear.mdx +35 -5
  81. package/docs/channels/slack.mdx +3 -3
  82. package/docs/concepts/execution-model-and-durability.md +1 -1
  83. package/docs/guides/deployment.md +1 -1
  84. package/docs/guides/frontend/nextjs.mdx +7 -7
  85. package/docs/subagents.mdx +2 -0
  86. package/package.json +7 -5
  87. package/dist/src/compiled/_chunks/workflow/attribute-changes-zAifvEhb.js +0 -59
  88. package/dist/src/compiled/_chunks/workflow/dist-Dxrjttr2.js +0 -3
  89. package/dist/src/compiled/_chunks/workflow/resume-hook-C15uJ2ik.js +0 -1
  90. package/dist/src/compiled/_chunks/workflow/run-BJUPZ0Ni.js +0 -1
  91. package/dist/src/compiled/_chunks/workflow/sleep-C8B-TYir.js +0 -1
  92. package/dist/src/compiled/_chunks/workflow/token-Bm-WLAUB.js +0 -1
  93. package/dist/src/compiled/_chunks/workflow/token-J7YP0s9a.js +0 -1
  94. package/dist/src/internal/workflow/configure-world.d.ts +0 -18
  95. package/dist/src/internal/workflow/configure-world.js +0 -1
@@ -0,0 +1 @@
1
+ import"../../../../../../../_virtual/_rolldown/runtime.js";import{require_ms}from"../../../../../ms@2.1.3/node_modules/ms/index.js";require_ms();export{};
@@ -0,0 +1 @@
1
+ const WORKFLOW_ROUTE_BASE=`/.well-known/workflow/v1`;export{WORKFLOW_ROUTE_BASE};
@@ -0,0 +1 @@
1
+ function normalizeWorkflowTargetWorldImport(e){if(e)return e===`local`?`@workflow/world-local`:e===`vercel`?`@workflow/world-vercel`:e}function resolveWorkflowTargetWorld(e=process.env){return e.WORKFLOW_TARGET_WORLD||(e.VERCEL_DEPLOYMENT_ID?`vercel`:`local`)}function getWorldImport(e=process.env){return normalizeWorkflowTargetWorldImport(e.WORKFLOW_TARGET_WORLD)??(e.VERCEL_DEPLOYMENT_ID?`@workflow/world-vercel`:`@workflow/world-local`)}function isVercelWorldTarget(e){return e===`vercel`||e===`@workflow/world-vercel`}export{getWorldImport,isVercelWorldTarget,normalizeWorkflowTargetWorldImport,resolveWorkflowTargetWorld};
@@ -0,0 +1 @@
1
+ import{__commonJSMin}from"../../../../../_virtual/_rolldown/runtime.js";var require_ms=__commonJSMin(((e,t)=>{var n=1e3,r=n*60,i=r*60,a=i*24,o=a*7,s=a*365.25;t.exports=function(e,t){t||={};var n=typeof e;if(n===`string`&&e.length>0)return parse(e);if(n===`number`&&isFinite(e))return t.long?fmtLong(e):fmtShort(e);throw Error(`val is not a non-empty string or a valid number. val=`+JSON.stringify(e))};function parse(e){if(e=String(e),!(e.length>100)){var t=/^(-?(?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec(e);if(t){var c=parseFloat(t[1]);switch((t[2]||`ms`).toLowerCase()){case`years`:case`year`:case`yrs`:case`yr`:case`y`:return c*s;case`weeks`:case`week`:case`w`:return c*o;case`days`:case`day`:case`d`:return c*a;case`hours`:case`hour`:case`hrs`:case`hr`:case`h`:return c*i;case`minutes`:case`minute`:case`mins`:case`min`:case`m`:return c*r;case`seconds`:case`second`:case`secs`:case`sec`:case`s`:return c*n;case`milliseconds`:case`millisecond`:case`msecs`:case`msec`:case`ms`:return c;default:return}}}}function fmtShort(e){var t=Math.abs(e);return t>=a?Math.round(e/a)+`d`:t>=i?Math.round(e/i)+`h`:t>=r?Math.round(e/r)+`m`:t>=n?Math.round(e/n)+`s`:e+`ms`}function fmtLong(e){var t=Math.abs(e);return t>=a?plural(e,t,a,`day`):t>=i?plural(e,t,i,`hour`):t>=r?plural(e,t,r,`minute`):t>=n?plural(e,t,n,`second`):e+` ms`}function plural(e,t,n,r){var i=t>=n*1.5;return Math.round(e/n)+` `+r+(i?`s`:``)}}));export default require_ms();export{require_ms};
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Typing-indicator labels for requested actions. The Slack indicator is
3
+ * plain text (`assistant.threads.setStatus` renders no markdown), so the
4
+ * label is the action's name plus its most telling argument — `grep useEve`
5
+ * or `read_file agent/agent.ts` instead of `Running grep...`.
6
+ */
7
+ import type { RuntimeActionRequest } from "#runtime/actions/types.js";
8
+ /**
9
+ * One action's typing-indicator label: `grep useEveAgent` for tool calls,
10
+ * the subagent or remote-agent name for dispatched calls, and
11
+ * `load_skill <name>` for skill loads.
12
+ */
13
+ export declare function describeActionRequest(action: RuntimeActionRequest): string;
14
+ /**
15
+ * Typing-indicator text for one requested batch: the first action's
16
+ * {@link describeActionRequest} label, plus `+N more` when the model
17
+ * requested several actions at once.
18
+ */
19
+ export declare function describeActionRequests(actions: readonly RuntimeActionRequest[]): string;
@@ -0,0 +1 @@
1
+ const SALIENT_KEYS={bash:[`command`],glob:[`pattern`],grep:[`pattern`,`path`],load_skill:[`skill`],read_file:[`filePath`],web_fetch:[`url`],web_search:[`query`],write_file:[`filePath`]},GENERIC_KEYS=[`filePath`,`path`,`pattern`,`command`,`query`,`name`,`repo`,`url`,`issueNumber`,`number`];function salientArg(n,r){for(let i of SALIENT_KEYS[n]??GENERIC_KEYS){let e=r[i];if(typeof e==`string`&&e.trim().length>0)return e;if(typeof e==`number`)return String(e)}return null}function shortenArg(e){let t=e.split(/\r?\n/u,1)[0]?.trim()??``;if(t.length<=40)return t;if(t.includes(`/`)&&!t.includes(` `)){let e=t.split(`/`).filter(e=>e.length>0).slice(-2).join(`/`);if(e.length<=40)return e}return`${t.slice(0,37).trimEnd()}...`}function toolCallLabel(e,t){let n=salientArg(e,t);return n===null?e:`${e} ${shortenArg(n)}`}function describeActionRequest(e){switch(e.kind){case`load-skill`:return toolCallLabel(`load_skill`,e.input);case`remote-agent-call`:return e.remoteAgentName;case`subagent-call`:return e.subagentName;case`tool-call`:return toolCallLabel(e.toolName,e.input)}}function describeActionRequests(e){let[t]=e;if(t===void 0)return`Working...`;let n=describeActionRequest(t);return e.length===1?n:`${n} +${e.length-1} more`}export{describeActionRequest,describeActionRequests};
@@ -1,4 +1,4 @@
1
- import{createLogger,extractErrorId,formatErrorHint}from"#internal/logging.js";import{SLACK_MAX_BLOCKS_PER_MESSAGE,truncateMessageText,truncateTypingStatus}from"#public/channels/slack/limits.js";import{buildSlackAuthContext,slackUserIdFromAuthContext}from"#public/channels/slack/auth.js";import{buildAuthCompletedText,buildAuthEphemeralBlocks,buildAuthRequiredPublicText,formatConnectionDisplayName}from"#public/channels/slack/connections.js";import{formatInputRequestFallbackText,renderInputRequestBlocks}from"#public/channels/slack/hitl.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)=>{for(let n of buildInputRequestPosts(e.requests))await t.thread.post(n)}}function buildInputRequestPosts(e){let t=[];for(let n of e){let e=renderInputRequestBlocks(n),i=t.at(-1);i&&i.blocks.length+e.length<=SLACK_MAX_BLOCKS_PER_MESSAGE?(i.blocks.push(...e),i.fallbacks.push(formatInputRequestFallbackText(n))):t.push({blocks:e,fallbacks:[formatInputRequestFallbackText(n)]})}return t.map(e=>({blocks:e.blocks,text:truncateMessageText(e.fallbacks.join(`
2
- `))}))}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),o=t.state.lastReasoningTypingStatus,s=o!=null&&i.startsWith(o)&&i.length>=o.length+4,c=Date.now(),l=t.state.lastReasoningTypingAtMs;if(!s&&l!=null){let e=c-l;if(e>=0&&e<5e3)return}await t.thread.startTyping(i),t.state.lastReasoningTypingAtMs=c,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(`
1
+ import{createLogger,extractErrorId,formatErrorHint}from"#internal/logging.js";import{SLACK_MAX_BLOCKS_PER_MESSAGE,truncateMessageText,truncateTypingStatus}from"#public/channels/slack/limits.js";import{describeActionRequests}from"#public/channels/slack/action-status.js";import{buildSlackAuthContext,slackUserIdFromAuthContext}from"#public/channels/slack/auth.js";import{buildAuthCompletedText,buildAuthEphemeralBlocks,buildAuthRequiredPublicText,formatConnectionDisplayName}from"#public/channels/slack/connections.js";import{formatInputRequestFallbackText,renderInputRequestBlocks}from"#public/channels/slack/hitl.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)=>{for(let n of buildInputRequestPosts(e.requests))await t.thread.post(n)}}function buildInputRequestPosts(e){let t=[];for(let n of e){let e=renderInputRequestBlocks(n),i=t.at(-1);i&&i.blocks.length+e.length<=SLACK_MAX_BLOCKS_PER_MESSAGE?(i.blocks.push(...e),i.fallbacks.push(formatInputRequestFallbackText(n))):t.push({blocks:e,fallbacks:[formatInputRequestFallbackText(n)]})}return t.map(e=>({blocks:e.blocks,text:truncateMessageText(e.fallbacks.join(`
2
+ `))}))}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),o=t.state.lastReasoningTypingStatus,s=o!=null&&i.startsWith(o)&&i.length>=o.length+4,c=Date.now(),l=t.state.lastReasoningTypingAtMs;if(!s&&l!=null){let e=c-l;if(e>=0&&e<5e3)return}await t.thread.startTyping(i),t.state.lastReasoningTypingAtMs=c,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}await t.thread.startTyping(truncateTypingStatus(describeActionRequests(e.actions)))},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
4
  `))},async"authorization.required"(e,t,n){let r=e.authorization?.displayName??formatConnectionDisplayName(e.name),i=slackUserIdFromAuthContext(n.session.auth.current)??t.state.triggeringUserId??null,a=e.authorization?.url,o=t.state.pendingAuthMessageTs??{};if(o[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={...o,[e.name]:r.id})}catch(t){log.error(`Slack auth public message delivery failed`,{name:e.name,error:t})}}if(i&&a){let n=e.authorization?.userCode;try{await t.thread.postEphemeral(i,{blocks:buildAuthEphemeralBlocks({displayName:r,url:a,userCode:n}),text:n?`Sign in with ${r}: ${a} (code: ${n})`:`Sign in with ${r}: ${a}`})}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 a=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:a})}catch(t){log.error(`Slack auth status edit failed`,{name:e.name,error:t})}let o={...r};delete o[e.name],t.state.pendingAuthMessageTs=o}};export{defaultEvents,defaultInputRequestedHandler,defaultOnAppMention,defaultOnDirectMessage,defaultSlackAuth};
@@ -9,6 +9,7 @@ export { slackChannel, type SlackApiResponse, type SlackAuthorizationEventContex
9
9
  export type { SlackAttachment, SlackAuthor, SlackInboundContext, SlackMessage, } from "#public/channels/slack/inbound.js";
10
10
  export { callSlackApi, resolveSlackBotToken, slackContinuationToken, type SlackPostInput, type SlackPostedMessage, type SlackThreadMessage, type SlackUploadFilesOptions, type SlackUploadFilesResult, } from "#public/channels/slack/api.js";
11
11
  export { defaultSlackAuth } from "#public/channels/slack/defaults.js";
12
+ export { describeActionRequest, describeActionRequests, } from "#public/channels/slack/action-status.js";
12
13
  export { loadThreadContextMessages, type LoadThreadContextMessagesOptions, type ThreadContextSince, } from "#public/channels/slack/thread.js";
13
14
  export { cardToBlocks, cardToFallbackText, type BlockKitBlock, } from "#public/channels/slack/blocks.js";
14
15
  /**
@@ -1 +1 @@
1
- import{Actions,Button,Card,CardLink,CardText,Divider,ExternalSelect,Field,Fields,Image,LinkButton,Modal,RadioSelect,Section,Select,SelectOption,Table,TextInput,cardChildToFallbackText,isCardElement}from"#compiled/chat/index.js";import{cardToBlocks,cardToFallbackText}from"#public/channels/slack/blocks.js";import{callSlackApi,resolveSlackBotToken,slackContinuationToken}from"#public/channels/slack/api.js";import{slackChannel}from"#public/channels/slack/slackChannel.js";import{defaultSlackAuth}from"#public/channels/slack/defaults.js";import{loadThreadContextMessages}from"#public/channels/slack/thread.js";export{Actions,Button,Card,CardLink,CardText,Divider,ExternalSelect,Field,Fields,Image,LinkButton,Modal,RadioSelect,Section,Select,SelectOption,Table,TextInput,callSlackApi,cardChildToFallbackText,cardToBlocks,cardToFallbackText,defaultSlackAuth,isCardElement,loadThreadContextMessages,resolveSlackBotToken,slackChannel,slackContinuationToken};
1
+ import{Actions,Button,Card,CardLink,CardText,Divider,ExternalSelect,Field,Fields,Image,LinkButton,Modal,RadioSelect,Section,Select,SelectOption,Table,TextInput,cardChildToFallbackText,isCardElement}from"#compiled/chat/index.js";import{cardToBlocks,cardToFallbackText}from"#public/channels/slack/blocks.js";import{callSlackApi,resolveSlackBotToken,slackContinuationToken}from"#public/channels/slack/api.js";import{describeActionRequest,describeActionRequests}from"#public/channels/slack/action-status.js";import{slackChannel}from"#public/channels/slack/slackChannel.js";import{defaultSlackAuth}from"#public/channels/slack/defaults.js";import{loadThreadContextMessages}from"#public/channels/slack/thread.js";export{Actions,Button,Card,CardLink,CardText,Divider,ExternalSelect,Field,Fields,Image,LinkButton,Modal,RadioSelect,Section,Select,SelectOption,Table,TextInput,callSlackApi,cardChildToFallbackText,cardToBlocks,cardToFallbackText,defaultSlackAuth,describeActionRequest,describeActionRequests,isCardElement,loadThreadContextMessages,resolveSlackBotToken,slackChannel,slackContinuationToken};
@@ -104,7 +104,7 @@ export interface SlackChannelState {
104
104
  * Buffered text from a `message.completed` event whose `finishReason`
105
105
  * was `"tool-calls"`. The default `actions.requested` handler uses the
106
106
  * first non-empty line as the next typing indicator, surfacing the
107
- * model's pre-tool narration instead of "Running ...". Cleared at
107
+ * model's pre-tool narration instead of the action label. Cleared at
108
108
  * `turn.started` and after use.
109
109
  */
110
110
  pendingToolCallMessage?: string | null;
@@ -1,8 +1,7 @@
1
1
  import type { NextConfig } from "next";
2
2
  /**
3
- * Default private route namespace for hosting eve as a separate experimental
4
- * Vercel service behind the Next.js app. {@link WithEveOptions.servicePrefix}
5
- * defaults to this value.
3
+ * Default private route namespace for legacy manually configured Vercel
4
+ * services. {@link WithEveOptions.servicePrefix} defaults to this value.
6
5
  */
7
6
  export declare const EVE_NEXT_SERVICE_PREFIX = "/_eve_internal/eve";
8
7
  type ArrayElement<T> = T extends readonly (infer TElement)[] ? TElement : never;
@@ -63,11 +62,11 @@ export interface WithEveOptions {
63
62
  */
64
63
  readonly eveBuildCommand?: string;
65
64
  /**
66
- * Private Vercel service prefix for the eve deployment. Defaults to
67
- * {@link EVE_NEXT_SERVICE_PREFIX} (`/_eve_internal/eve`). `withEve` normalizes
68
- * the prefix (adds a leading slash, strips trailing slashes) and rejects a
69
- * prefix that resolves to the root route. The prefix must match the eve
70
- * service's mount in Vercel Build Output config.
65
+ * Private route namespace for legacy manually configured Vercel services and
66
+ * non-Vercel production proxying. Defaults to {@link EVE_NEXT_SERVICE_PREFIX}
67
+ * (`/_eve_internal/eve`). `withEve` normalizes the prefix (adds a leading
68
+ * slash, strips trailing slashes) and rejects a prefix that resolves to the
69
+ * root route.
71
70
  */
72
71
  readonly servicePrefix?: string;
73
72
  }
@@ -77,7 +76,8 @@ export interface WithEveOptions {
77
76
  *
78
77
  * In development, starts `eve dev --no-ui --port 0` for the eve app and
79
78
  * rewrites eve protocol endpoints to that local URL. In Vercel production,
80
- * rewrites to the resolved private eve service prefix.
79
+ * writes Build Output service routes so Vercel sends eve protocol endpoints to
80
+ * the eve service directly.
81
81
  * Outside Vercel production, serves an existing `.output/server/index.mjs` build
82
82
  * on a stable local port when present; otherwise set `EVE_NEXT_PRODUCTION_ORIGIN`
83
83
  * to the origin serving the eve service namespace.
@@ -1 +1 @@
1
- import{resolveEveDestinationPrefix}from"./server.js";import{ensureEveVercelOutputConfig}from"./vercel-output-config.js";import{EVE_ROUTE_PREFIX}from"#protocol/routes.js";import{isAbsolute,resolve}from"node:path";const EVE_NEXT_SERVICE_PREFIX=`/_eve_internal/eve`,EVE_NEXT_PRODUCTION_PORT_ENV=`EVE_NEXT_PRODUCTION_PORT`,EVE_PROXY_REWRITE_SOURCES=[`${EVE_ROUTE_PREFIX}/:path+`];function resolveApplicationRoot(e){return e===void 0||e.length===0?process.cwd():isAbsolute(e)?e:resolve(process.cwd(),e)}function resolveDevServerTimeout(e){if(e!==void 0){if(!Number.isFinite(e)||e<=0)throw Error(`eve Next.js development server timeout must be a positive number.`);return e}}function normalizeRoutePrefix(e){let t=(e.startsWith(`/`)?e:`/${e}`).replace(/\/+$/,``);if(t.length===0)throw Error(`eve Next.js service prefix cannot resolve to the root route.`);return t}function joinRoutePrefix(e,t){return`${e.replace(/\/+$/,``)}/${t.replace(/^\/+/,``)}`}function normalizeOrigin(e){return new URL(e.trim()).origin}function readLocalProductionPort(){let e=process.env[EVE_NEXT_PRODUCTION_PORT_ENV];if(e===void 0||e.trim().length===0)return 4274;let t=Number.parseInt(e,10);if(String(t)!==e.trim()||t<1||t>65535)throw Error(`${EVE_NEXT_PRODUCTION_PORT_ENV} must be an integer between 1 and 65535.`);return t}function resolveProductionDestination(e){if(process.env.VERCEL)return{destinationPrefix:e};let t=process.env.EVE_NEXT_PRODUCTION_ORIGIN;if(t!==void 0&&t.trim().length>0)return{destinationPrefix:joinRoutePrefix(normalizeOrigin(t),e)};let n=`http://127.0.0.1:${String(readLocalProductionPort())}`;return{destinationPrefix:n,localServerOrigin:n}}function createEveRewriteRules(e){return EVE_PROXY_REWRITE_SOURCES.map(t=>({destination:joinRoutePrefix(e,t),source:t}))}async function resolveExistingRewrites(e){return await e?.()}function mergeRewriteRules(e,t){return e===void 0?{beforeFiles:t}:isRewriteSections(e)?{...e,beforeFiles:[...t,...e.beforeFiles??[]]}:{afterFiles:e,beforeFiles:t}}function isRewriteSections(e){return!Array.isArray(e)}async function resolveNextConfig(e,t,n){return typeof e==`function`?await e(t,n):e}function withEve(n,r={}){let i=process.cwd(),a=resolveApplicationRoot(r.eveRoot),o=resolveDevServerTimeout(r.devServerTimeoutMs),s=normalizeRoutePrefix(r.servicePrefix??`/_eve_internal/eve`);return async function(c,l){let u=await resolveNextConfig(n,c,l),d=u.rewrites,f=resolveProductionDestination((await ensureEveVercelOutputConfig({appRoot:a,eveBuildCommand:r.eveBuildCommand??`eve build`,nextRoot:i,servicePrefix:s})).servicePrefix);return{...u,async rewrites(){let[t,n]=await Promise.all([resolveExistingRewrites(d),resolveEveDestinationPrefix({appRoot:a,devServerTimeoutMs:o,phase:c,productionDestinationPrefix:f.destinationPrefix,productionServerOrigin:f.localServerOrigin})]);return mergeRewriteRules(t,createEveRewriteRules(n))}}}}export{EVE_NEXT_SERVICE_PREFIX,withEve};
1
+ import{resolveEveDestinationPrefix}from"./server.js";import{ensureEveVercelOutputConfig}from"./vercel-output-config.js";import{EVE_ROUTE_PREFIX}from"#protocol/routes.js";import{isAbsolute,resolve}from"node:path";const EVE_NEXT_SERVICE_PREFIX=`/_eve_internal/eve`,EVE_NEXT_PRODUCTION_PORT_ENV=`EVE_NEXT_PRODUCTION_PORT`,EVE_PROXY_REWRITE_SOURCES=[`${EVE_ROUTE_PREFIX}/:path+`];function resolveApplicationRoot(e){return e===void 0||e.length===0?process.cwd():isAbsolute(e)?e:resolve(process.cwd(),e)}function resolveDevServerTimeout(e){if(e!==void 0){if(!Number.isFinite(e)||e<=0)throw Error(`eve Next.js development server timeout must be a positive number.`);return e}}function normalizeRoutePrefix(e){let t=(e.startsWith(`/`)?e:`/${e}`).replace(/\/+$/,``);if(t.length===0)throw Error(`eve Next.js service prefix cannot resolve to the root route.`);return t}function joinRoutePrefix(e,t){return`${e.replace(/\/+$/,``)}/${t.replace(/^\/+/,``)}`}function normalizeOrigin(e){return new URL(e.trim()).origin}function readLocalProductionPort(){let e=process.env[EVE_NEXT_PRODUCTION_PORT_ENV];if(e===void 0||e.trim().length===0)return 4274;let t=Number.parseInt(e,10);if(String(t)!==e.trim()||t<1||t>65535)throw Error(`${EVE_NEXT_PRODUCTION_PORT_ENV} must be an integer between 1 and 65535.`);return t}function resolveProductionDestination(e){if(process.env.VERCEL)return{destinationPrefix:e};let t=process.env.EVE_NEXT_PRODUCTION_ORIGIN;if(t!==void 0&&t.trim().length>0)return{destinationPrefix:joinRoutePrefix(normalizeOrigin(t),e)};let n=`http://127.0.0.1:${String(readLocalProductionPort())}`;return{destinationPrefix:n,localServerOrigin:n}}function createEveRewriteRules(e){return EVE_PROXY_REWRITE_SOURCES.map(t=>({destination:joinRoutePrefix(e,t),source:t}))}async function resolveExistingRewrites(e){return await e?.()}function mergeRewriteRules(e,t){return e===void 0?{beforeFiles:t}:isRewriteSections(e)?{...e,beforeFiles:[...t,...e.beforeFiles??[]]}:{afterFiles:e,beforeFiles:t}}function isRewriteSections(e){return!Array.isArray(e)}async function resolveNextConfig(e,t,n){return typeof e==`function`?await e(t,n):e}function withEve(n,r={}){let i=process.cwd(),a=resolveApplicationRoot(r.eveRoot),o=resolveDevServerTimeout(r.devServerTimeoutMs),s=normalizeRoutePrefix(r.servicePrefix??`/_eve_internal/eve`);return async function(c,l){let u=await resolveNextConfig(n,c,l),d=u.rewrites,f=await ensureEveVercelOutputConfig({appRoot:a,eveBuildCommand:r.eveBuildCommand??`eve build`,nextRoot:i,servicePrefix:s});if(process.env.VERCEL)return u;let p=resolveProductionDestination(f.servicePrefix);return{...u,async rewrites(){let[t,n]=await Promise.all([resolveExistingRewrites(d),resolveEveDestinationPrefix({appRoot:a,devServerTimeoutMs:o,phase:c,productionDestinationPrefix:p.destinationPrefix,productionServerOrigin:p.localServerOrigin})]);return mergeRewriteRules(t,createEveRewriteRules(n))}}}}export{EVE_NEXT_SERVICE_PREFIX,withEve};
@@ -1 +1 @@
1
- import{dirname,join,relative}from"node:path";import{mkdir,readFile,writeFile}from"node:fs/promises";import{findClosestLinkedVercelDirectory,findClosestVercelOutputDirectory}from"#shared/vercel-output-directory.js";const VERCEL_JSON_FILE_NAME=`vercel.json`,VERCEL_OUTPUT_CONFIG_FILE_NAME=`.vercel/output/config.json`;function isRecord(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function hasServices(e){return e!==void 0&&Object.keys(e).length>0}function resolveRelativeEntrypoint(e,t){let r=relative(e,t);return r.length===0?`.`:r.replaceAll(`\\`,`/`)}async function resolveVercelOutputConfigLocation(n){let r=await findClosestLinkedVercelDirectory(n),i=r===void 0?n:dirname(r),a=await findClosestVercelOutputDirectory(n);return a===void 0?r===void 0?{canWriteGeneratedOutput:!1,outputConfigPath:join(n,VERCEL_OUTPUT_CONFIG_FILE_NAME),projectRoot:i}:{canWriteGeneratedOutput:!0,outputConfigPath:join(r,`output`,`config.json`),projectRoot:i}:{canWriteGeneratedOutput:!0,outputConfigPath:join(a,`config.json`),projectRoot:i}}function normalizeVercelServicesConfig(e,t){if(!isRecord(e))throw Error(`${t} must contain a JSON object.`);let n=e.experimentalServices;if(n!==void 0&&!isRecord(n))throw Error(`${t} experimentalServices must be a JSON object.`);return e}async function readVercelServicesConfig(e,t){try{return normalizeVercelServicesConfig(JSON.parse(await readFile(e,`utf8`)),t)}catch(e){if(e instanceof Error&&`code`in e&&e.code===`ENOENT`)return{};throw e}}function findServiceByFramework(e,t){return Object.values(e).find(e=>e.framework===t)}function resolveServicePrefix(e){if(e!==void 0){if(typeof e.routePrefix==`string`&&e.routePrefix.trim().length>0)return e.routePrefix.trim();if(typeof e.mount==`string`&&e.mount.trim().length>0)return e.mount.trim();if(isRecord(e.mount)&&typeof e.mount.path==`string`&&e.mount.path.trim().length>0)return e.mount.path.trim()}}function resolveConfiguredServicePrefix(e){return resolveServicePrefix(findServiceByFramework(e.services,`eve`))??e.servicePrefix}function assertRootServicesAreComplete(e){let t=findServiceByFramework(e.services,`eve`),n=findServiceByFramework(e.services,`nextjs`);if(t!==void 0&&n!==void 0)return resolveServicePrefix(t)??e.servicePrefix;throw Error(`${VERCEL_JSON_FILE_NAME} already defines experimentalServices, so withEve cannot add generated services through ${VERCEL_OUTPUT_CONFIG_FILE_NAME}. Add both the Next.js and eve services to ${VERCEL_JSON_FILE_NAME}, or remove experimentalServices from ${VERCEL_JSON_FILE_NAME}.`)}async function ensureEveVercelOutputConfig(n){let{canWriteGeneratedOutput:i,outputConfigPath:o,projectRoot:s}=await resolveVercelOutputConfigLocation(n.nextRoot),c=(await readVercelServicesConfig(join(s,VERCEL_JSON_FILE_NAME),VERCEL_JSON_FILE_NAME)).experimentalServices;if(hasServices(c))return{servicePrefix:assertRootServicesAreComplete({services:c,servicePrefix:n.servicePrefix})};let l=await readVercelServicesConfig(o,VERCEL_OUTPUT_CONFIG_FILE_NAME),u=resolveRelativeEntrypoint(n.nextRoot,n.appRoot),d=l.experimentalServices??{},f=findServiceByFramework(d,`eve`),p=findServiceByFramework(d,`nextjs`),m=resolveConfiguredServicePrefix({services:d,servicePrefix:n.servicePrefix});if(!i)return{servicePrefix:m};let h={...d};p===void 0&&(h.web={entrypoint:`.`,framework:`nextjs`,mount:`/`,type:`web`}),f===void 0&&(h.eve={buildCommand:n.eveBuildCommand,entrypoint:u,framework:`eve`,mount:m,type:`web`});let g={...l,version:3,experimentalServices:h};return JSON.stringify(l)!==JSON.stringify(g)&&(await mkdir(dirname(o),{recursive:!0}),await writeFile(o,`${JSON.stringify(g,null,2)}\n`)),{servicePrefix:m}}export{ensureEveVercelOutputConfig};
1
+ import{dirname,join,relative}from"node:path";import{mkdir,readFile,writeFile}from"node:fs/promises";import{findClosestLinkedVercelDirectory,findClosestVercelOutputDirectory}from"#shared/vercel-output-directory.js";const VERCEL_JSON_FILE_NAME=`vercel.json`,VERCEL_OUTPUT_CONFIG_FILE_NAME=`.vercel/output/config.json`,EVE_SERVICE_ROUTE_SRC=`^/eve/v1/(.*)$`;function isRecord(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function hasServices(e){return e!==void 0&&Object.keys(e).length>0}function resolveRelativeEntrypoint(e,t){let r=relative(e,t);return r.length===0?`.`:r.replaceAll(`\\`,`/`)}async function resolveVercelOutputConfigLocation(n){let r=await findClosestLinkedVercelDirectory(n),i=r===void 0?n:dirname(r),a=await findClosestVercelOutputDirectory(n);return a===void 0?r===void 0?{canWriteGeneratedOutput:!!process.env.VERCEL,outputConfigPath:join(n,VERCEL_OUTPUT_CONFIG_FILE_NAME),projectRoot:i}:{canWriteGeneratedOutput:!0,outputConfigPath:join(r,`output`,`config.json`),projectRoot:i}:{canWriteGeneratedOutput:!0,outputConfigPath:join(a,`config.json`),projectRoot:i}}function normalizeVercelServicesConfig(e,t){if(!isRecord(e))throw Error(`${t} must contain a JSON object.`);let n=e.services;if(n!==void 0&&!isRecord(n))throw Error(`${t} services must be a JSON object.`);let r=e.routes;if(r!==void 0&&!Array.isArray(r))throw Error(`${t} routes must be an array.`);return e}async function readVercelServicesConfig(e,t){try{return normalizeVercelServicesConfig(JSON.parse(await readFile(e,`utf8`)),t)}catch(e){if(e instanceof Error&&`code`in e&&e.code===`ENOENT`)return{};throw e}}function findServiceByFramework(e,t){return findServiceEntryByFramework(e,t)?.service}function findServiceEntryByFramework(e,t){return Object.entries(e).map(([e,t])=>({name:e,service:t})).find(e=>e.service.framework===t)}function resolveServicePrefix(e){if(e!==void 0){if(typeof e.routePrefix==`string`&&e.routePrefix.trim().length>0)return e.routePrefix.trim();if(typeof e.mount==`string`&&e.mount.trim().length>0)return e.mount.trim();if(isRecord(e.mount)&&typeof e.mount.path==`string`&&e.mount.path.trim().length>0)return e.mount.path.trim()}}function resolveConfiguredServicePrefix(e){return resolveServicePrefix(findServiceByFramework(e.services,`eve`))??e.servicePrefix}function assertRootServicesIncludeEve(e){let t=findServiceByFramework(e.services,`eve`);if(t!==void 0)return resolveServicePrefix(t)??e.servicePrefix;throw Error(`${VERCEL_JSON_FILE_NAME} already defines services, so withEve cannot add a generated eve service through ${VERCEL_OUTPUT_CONFIG_FILE_NAME}. Add the eve service to ${VERCEL_JSON_FILE_NAME}, or remove services from ${VERCEL_JSON_FILE_NAME}.`)}function isEveServiceRoute(e,t){let n=e.destination;return e.src===EVE_SERVICE_ROUTE_SRC&&isRecord(n)&&n.type===`service`&&n.service===t}function createEveServiceRoute(e){return{destination:{service:e,type:`service`},src:EVE_SERVICE_ROUTE_SRC}}function insertEveServiceRoute(e,t){let n=e.find(e=>isEveServiceRoute(e,t)),r=e.filter(e=>!isEveServiceRoute(e,t)),i=r.findIndex(e=>e.handle===`filesystem`),a=n??createEveServiceRoute(t);return i===-1?[a,...r]:[...r.slice(0,i),a,...r.slice(i)]}async function ensureEveVercelOutputConfig(n){let{canWriteGeneratedOutput:i,outputConfigPath:o,projectRoot:s}=await resolveVercelOutputConfigLocation(n.nextRoot),c=(await readVercelServicesConfig(join(s,VERCEL_JSON_FILE_NAME),VERCEL_JSON_FILE_NAME)).services;if(hasServices(c))return{servicePrefix:assertRootServicesIncludeEve({services:c,servicePrefix:n.servicePrefix})};let l=await readVercelServicesConfig(o,VERCEL_OUTPUT_CONFIG_FILE_NAME),u=resolveRelativeEntrypoint(n.nextRoot,n.appRoot),d=l.services??{},f=findServiceEntryByFramework(d,`eve`),p=resolveConfiguredServicePrefix({services:d,servicePrefix:n.servicePrefix});if(!i)return{servicePrefix:p};let m={...d},h=f?.name??`eve`;f===void 0&&(m.eve={buildCommand:n.eveBuildCommand,entrypoint:`package.json`,framework:`eve`,root:u},h=`eve`);let{services:g,..._}=l,v={..._,routes:insertEveServiceRoute(l.routes??[],h),services:m,version:3};return JSON.stringify(l)!==JSON.stringify(v)&&(await mkdir(dirname(o),{recursive:!0}),await writeFile(o,`${JSON.stringify(v,null,2)}\n`)),{servicePrefix:p}}export{ensureEveVercelOutputConfig};
@@ -1,4 +1,4 @@
1
- import{pinnedNodeEngineMajor}from"../../node-engine.js";import{pathExists,writeTextFile}from"../files.js";import{resolveVersionToken}from"../version-tokens.js";import{applyPackageManagerWorkspaceConfiguration,isPackageManagerWorkspaceMember,patchWorkspaceRootPackageJson}from"../workspace-root.js";import{SUPPORTED_AUTHORED_MODULE_FILE_EXTENSIONS}from"../update/module-files.js";import{WEB_APP_TEMPLATE_FILES}from"./web-template.js";import{basename,join,resolve}from"node:path";import{mkdir,readdir,stat}from"node:fs/promises";const CURRENT_DIRECTORY_PROJECT_NAME=`.`,ALLOWED_CREATE_IN_PLACE_ENTRIES=new Set([`.DS_Store`,`.git`,`.gitkeep`,`.hg`]),DEFAULT_AI_PACKAGE_VERSION=`^7.0.0`,DEFAULT_CONNECT_PACKAGE_VERSION=`0.2.2`,DEFAULT_ZOD_PACKAGE_VERSION=`4.4.3`,DEFAULT_EVE_PACKAGE_CONTRACT={version:`0.22.1`,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){return{"agent/agent.ts":BASE_AGENT_TEMPLATE.replaceAll(`__EVE_INIT_MODEL__`,e),"agent/channels/eve.ts":WEB_APP_TEMPLATE_FILES[`agent/channels/eve.ts`],"agent/instructions.md":AGENT_INSTRUCTIONS_TEMPLATE}}function renderTemplate(e,t){return e.replaceAll(`__EVE_INIT_APP_NAME__`,t.appName).replaceAll(`__EVE_INIT_MODEL__`,t.model).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{pathExists,writeTextFile}from"../files.js";import{resolveVersionToken}from"../version-tokens.js";import{applyPackageManagerWorkspaceConfiguration,isPackageManagerWorkspaceMember,patchWorkspaceRootPackageJson}from"../workspace-root.js";import{SUPPORTED_AUTHORED_MODULE_FILE_EXTENSIONS}from"../update/module-files.js";import{WEB_APP_TEMPLATE_FILES}from"./web-template.js";import{basename,join,resolve}from"node:path";import{mkdir,readdir,stat}from"node:fs/promises";const CURRENT_DIRECTORY_PROJECT_NAME=`.`,ALLOWED_CREATE_IN_PLACE_ENTRIES=new Set([`.DS_Store`,`.git`,`.gitkeep`,`.hg`]),DEFAULT_AI_PACKAGE_VERSION=`^7.0.0`,DEFAULT_CONNECT_PACKAGE_VERSION=`0.2.2`,DEFAULT_ZOD_PACKAGE_VERSION=`4.4.3`,DEFAULT_EVE_PACKAGE_CONTRACT={version:`0.22.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){return{"agent/agent.ts":BASE_AGENT_TEMPLATE.replaceAll(`__EVE_INIT_MODEL__`,e),"agent/channels/eve.ts":WEB_APP_TEMPLATE_FILES[`agent/channels/eve.ts`],"agent/instructions.md":AGENT_INSTRUCTIONS_TEMPLATE}}function renderTemplate(e,t){return e.replaceAll(`__EVE_INIT_APP_NAME__`,t.appName).replaceAll(`__EVE_INIT_MODEL__`,t.model).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__",
@@ -95,4 +95,4 @@ export default defineAgent({
95
95
  },
96
96
  },
97
97
  });
98
- `:BASE_AGENT_TEMPLATE,...SHARED_TEMPLATE_FILES,"package.json":packageJsonTemplate({includeRootOnlyFields:e.includeRootOnlyPackageJsonFields,packageManager:e.packageManager})}}async function assertCanCreateInPlace(e,n){if(!await pathExists(e))return;let r=(await readdir(e)).filter(e=>!ALLOWED_CREATE_IN_PLACE_ENTRIES.has(e));if(r.length>0&&!n){let e=r.slice(0,5).join(`, `),t=r.length>5?`, and ${r.length-5} more`:``;throw Error(`Cannot create project in current directory because it is not empty. Found: ${e}${t}. Use an empty directory.`)}}async function scaffoldBaseProject(o){let s=resolve(o.targetDirectory??process.cwd(),o.projectName),c=o.projectName===`.`,l=o.overwriteExisting??!1,u=o.byokProvider??!1,d=o.packageManager??`pnpm`,f=resolveEvePackageContract(o.evePackage),p=pinnedNodeEngineMajor(f.nodeEngine),m=resolve(o.workspaceProbeDirectory??s),h=isPackageManagerWorkspaceMember(d,m);if(c)await assertCanCreateInPlace(s,l);else if(await pathExists(s))throw Error(`Cannot create project because "${s}" already exists.`);let g={appName:basename(s),model:o.model,eveVersion:f.version,aiPackageVersion:resolveVersionToken(`aiPackageVersion`,o.aiPackageVersion??`^7.0.0`),connectPackageVersion:resolveVersionToken(`connectPackageVersion`,o.connectPackageVersion??`0.2.2`),zodPackageVersion:resolveVersionToken(`zodPackageVersion`,o.zodPackageVersion??`4.4.3`),typescriptPackageVersion:resolveVersionToken(`typescriptPackageVersion`,o.typescriptPackageVersion??`7.0.1-rc`),nodeTypesVersion:p,nodeEngine:p};await mkdir(s,{recursive:!0});for(let[e,r]of Object.entries(templateFiles({byokProvider:u,includeRootOnlyPackageJsonFields:!h,packageManager:d}))){let i=`${s}/${e}`,a=await pathExists(i);await writeTextFile(i,renderTemplate(r,g),{force:c&&l}),a&&await o.onOverwriteFile?.(i)}return await applyPackageManagerWorkspaceConfiguration({packageManager:d,projectRoot:s,workspaceProbeRoot:m,onWorkspaceRootMutation:o.onWorkspaceRootMutation}),await patchWorkspaceRootPackageJson(d,m,{aiPackageVersion:g.aiPackageVersion,nodeEngineRequirement:f.nodeEngine,onWorkspaceRootMutation:o.onWorkspaceRootMutation}),s}async function isEveProject(e){for(let t of SUPPORTED_AUTHORED_MODULE_FILE_EXTENSIONS)try{return await stat(join(e,`agent`,`agent${t}`)),!0}catch{}return!1}export{CURRENT_DIRECTORY_PROJECT_NAME,DEFAULT_AI_PACKAGE_VERSION,DEFAULT_CONNECT_PACKAGE_VERSION,DEFAULT_EVE_PACKAGE_CONTRACT,DEFAULT_ZOD_PACKAGE_VERSION,agentTemplateFiles,byokProviderEnvVar,formatEveDependencySpecifier,isEveProject,modelProviderSlug,resolveEvePackageContract,scaffoldBaseProject};
98
+ `:BASE_AGENT_TEMPLATE,...SHARED_TEMPLATE_FILES,"package.json":packageJsonTemplate({includeRootOnlyFields:e.includeRootOnlyPackageJsonFields,packageManager:e.packageManager})}}async function assertCanCreateInPlace(e,n){if(!await pathExists(e))return;let r=(await readdir(e)).filter(e=>!ALLOWED_CREATE_IN_PLACE_ENTRIES.has(e));if(r.length>0&&!n){let e=r.slice(0,5).join(`, `),t=r.length>5?`, and ${r.length-5} more`:``;throw Error(`Cannot create project in current directory because it is not empty. Found: ${e}${t}. Use an empty directory.`)}}async function scaffoldBaseProject(o){let s=resolve(o.targetDirectory??process.cwd(),o.projectName),c=o.projectName===`.`,l=o.overwriteExisting??!1,u=o.byokProvider??!1,d=o.packageManager??`pnpm`,f=resolveEvePackageContract(o.evePackage),p=pinnedNodeEngineMajor(f.nodeEngine),m=resolve(o.workspaceProbeDirectory??s),h=isPackageManagerWorkspaceMember(d,m);if(c)await assertCanCreateInPlace(s,l);else if(await pathExists(s))throw Error(`Cannot create project because "${s}" already exists.`);let g={appName:basename(s),model:o.model,eveVersion:f.version,aiPackageVersion:resolveVersionToken(`aiPackageVersion`,o.aiPackageVersion??`^7.0.0`),connectPackageVersion:resolveVersionToken(`connectPackageVersion`,o.connectPackageVersion??`0.2.2`),zodPackageVersion:resolveVersionToken(`zodPackageVersion`,o.zodPackageVersion??`4.4.3`),typescriptPackageVersion:resolveVersionToken(`typescriptPackageVersion`,o.typescriptPackageVersion??`7.0.2`),nodeTypesVersion:p,nodeEngine:p};await mkdir(s,{recursive:!0});for(let[e,r]of Object.entries(templateFiles({byokProvider:u,includeRootOnlyPackageJsonFields:!h,packageManager:d}))){let i=`${s}/${e}`,a=await pathExists(i);await writeTextFile(i,renderTemplate(r,g),{force:c&&l}),a&&await o.onOverwriteFile?.(i)}return await applyPackageManagerWorkspaceConfiguration({packageManager:d,projectRoot:s,workspaceProbeRoot:m,onWorkspaceRootMutation:o.onWorkspaceRootMutation}),await patchWorkspaceRootPackageJson(d,m,{aiPackageVersion:g.aiPackageVersion,nodeEngineRequirement:f.nodeEngine,onWorkspaceRootMutation:o.onWorkspaceRootMutation}),s}async function isEveProject(e){for(let t of SUPPORTED_AUTHORED_MODULE_FILE_EXTENSIONS)try{return await stat(join(e,`agent`,`agent${t}`)),!0}catch{}return!1}export{CURRENT_DIRECTORY_PROJECT_NAME,DEFAULT_AI_PACKAGE_VERSION,DEFAULT_CONNECT_PACKAGE_VERSION,DEFAULT_EVE_PACKAGE_CONTRACT,DEFAULT_ZOD_PACKAGE_VERSION,agentTemplateFiles,byokProviderEnvVar,formatEveDependencySpecifier,isEveProject,modelProviderSlug,resolveEvePackageContract,scaffoldBaseProject};
@@ -191,7 +191,7 @@ pnpm add @workflow/world-postgres@5.0.0-beta.x
191
191
  ```
192
192
 
193
193
  The npm `latest` tag can lag behind that line, so an unpinned install may pull
194
- an incompatible major that fails with `ZodError: invalid_union` at run replay.
194
+ an incompatible protocol version that the Workflow SDK rejects during initialization.
195
195
 
196
196
  Put credentials and host-specific options in runtime environment variables read
197
197
  by the world package, not in `agent.ts`. For the Postgres world, that means
@@ -1,13 +1,46 @@
1
1
  ---
2
2
  title: "GitHub"
3
- description: "Reach your agent from GitHub App webhooks, with @mention dispatch, PR diff context, and sandbox checkout."
3
+ description: "Reach your agent from GitHub App webhooks, with @mention dispatch, PR diff context, sandbox checkout, and Vercel Connect credentials."
4
4
  type: integration
5
5
  ---
6
6
 
7
- The GitHub channel lets the agent work directly on a repository. Someone `@mentions` it in an issue, PR, or review comment, and the agent answers right there in the thread, with the PR diff already in context and the repo checked out into the sandbox. It takes GitHub App webhooks at `/eve/v1/github`, checks the signature, derives auth from whoever triggered the event, and replies on the native surface. See [Channels](./overview) for the contract this builds on.
7
+ The GitHub channel lets the agent work directly on a repository. Someone `@mentions` it in an issue, PR, or review comment, and the agent answers right there in the thread, with the PR diff already in context and the repo checked out into the sandbox. It takes GitHub App webhooks at `/eve/v1/github`, checks the signature, derives auth from whoever triggered the event, and replies on the native surface. Credentials can run through [Vercel Connect](../guides/auth-and-route-protection), which manages the GitHub App, the installation token, and inbound webhook verification, so there's no app private key or webhook secret for you to hold. See [Channels](./overview) for the contract this builds on.
8
+
9
+ ## Set up Connect
10
+
11
+ Create a GitHub Connect client and copy its UID (e.g. `github/my-agent`), then attach this project as the trigger destination at eve's GitHub route:
12
+
13
+ ```bash
14
+ npm install -g vercel@latest
15
+ vercel connect create github --triggers
16
+ vercel connect detach <uid> --yes
17
+ vercel connect attach <uid> --triggers --trigger-path /eve/v1/github --yes
18
+ ```
19
+
20
+ The `create` step provisions the GitHub App and a trigger destination at the default Connect path. `detach` then `attach --trigger-path /eve/v1/github` re-points the trigger at the eve GitHub route, since eve does not serve the default Connect path. `--triggers` makes Connect receive the App's webhooks, verify them, and forward them to your deployment. During registration, subscribe to `issue_comment` and `pull_request_review_comment` for mention-driven turns — the managed App defaults to `pull_request` only — and add `issues`, `pull_request`, `check_suite`, `check_run`, or `workflow_run` if you wire up their opt-in hooks. You can also create the client from the [Connect dashboard](https://vercel.com/d?to=/%5Bteam%5D/~/connect&title=Go+to+Connect).
8
21
 
9
22
  ## Add the channel
10
23
 
24
+ ```bash
25
+ npm install @vercel/connect
26
+ ```
27
+
28
+ ```ts title="agent/channels/github.ts"
29
+ import { connectGitHubCredentials } from "@vercel/connect/eve";
30
+ import { githubChannel } from "eve/channels/github";
31
+
32
+ export default githubChannel({
33
+ botName: "my-agent",
34
+ credentials: connectGitHubCredentials("github/my-agent"),
35
+ });
36
+ ```
37
+
38
+ `connectGitHubCredentials` returns `{ installationToken, webhookVerifier }`: eve uses the Connect-managed installation token directly for GitHub API calls, skipping its native App JWT exchange, and verifies Connect-forwarded webhooks by their Vercel OIDC signature instead of a GitHub webhook secret. Token rotation, refresh, and multi-installation tenancy stay inside Connect, so there is no `GITHUB_APP_ID`, `GITHUB_APP_PRIVATE_KEY`, or `GITHUB_WEBHOOK_SECRET` to manage.
39
+
40
+ ### Bring your own GitHub App
41
+
42
+ To run a GitHub App you manage yourself, pass its credentials directly instead:
43
+
11
44
  ```ts title="agent/channels/github.ts"
12
45
  import { githubChannel } from "eve/channels/github";
13
46
 
@@ -1,13 +1,45 @@
1
1
  ---
2
2
  title: "Linear"
3
- description: "Reach your agent through Linear Agent Sessions, with native Agent Activities for progress, questions, and responses."
3
+ description: "Reach your agent through Linear Agent Sessions, with native Agent Activities for progress, questions, and responses, and Vercel Connect credentials."
4
4
  type: integration
5
5
  ---
6
6
 
7
- The Linear channel uses Linear's Agent Session surface rather than ordinary comments. Users delegate work to the agent from Linear, eve receives `AgentSessionEvent` webhooks at `/eve/v1/linear`, and the channel replies with native Agent Activities, including `thought`, `action`, `elicitation`, `response`, and `error`. See [Channels](./overview) for the contract this builds on.
7
+ The Linear channel uses Linear's Agent Session surface rather than ordinary comments. Users delegate work to the agent from Linear, eve receives `AgentSessionEvent` webhooks at `/eve/v1/linear`, and the channel replies with native Agent Activities, including `thought`, `action`, `elicitation`, `response`, and `error`. Credentials can run through [Vercel Connect](../guides/auth-and-route-protection), which manages the Linear app, its access token, and inbound webhook verification, so there's no API key or webhook secret for you to hold. See [Channels](./overview) for the contract this builds on.
8
+
9
+ ## Set up Connect
10
+
11
+ Create a Linear Connect client and copy its UID (e.g. `linear/my-agent`), then attach this project as the trigger destination at eve's Linear route:
12
+
13
+ ```bash
14
+ npm install -g vercel@latest
15
+ vercel connect create linear --triggers
16
+ vercel connect detach <uid> --yes
17
+ vercel connect attach <uid> --triggers --trigger-path /eve/v1/linear --yes
18
+ ```
19
+
20
+ The `create` step provisions the Linear app — with the `app:assignable` and `app:mentionable` scopes the agent surface needs — and a trigger destination at the default Connect path. `detach` then `attach --trigger-path /eve/v1/linear` re-points the trigger at the eve Linear route, since eve does not serve the default Connect path. `--triggers` makes Connect receive Linear's webhooks, verify them, and forward them to your deployment. During registration, subscribe to the `AgentSessionEvent` webhook category — the managed app defaults to `Comment` and `Issue` — so Linear sends `created` events when the agent is delegated or mentioned and `prompted` events when the user continues the session. You can also create the client from the [Connect dashboard](https://vercel.com/d?to=/%5Bteam%5D/~/connect&title=Go+to+Connect).
8
21
 
9
22
  ## Add the channel
10
23
 
24
+ ```bash
25
+ npm install @vercel/connect
26
+ ```
27
+
28
+ ```ts title="agent/channels/linear.ts"
29
+ import { connectLinearCredentials } from "@vercel/connect/eve";
30
+ import { linearChannel } from "eve/channels/linear";
31
+
32
+ export default linearChannel({
33
+ credentials: connectLinearCredentials("linear/my-agent"),
34
+ });
35
+ ```
36
+
37
+ `connectLinearCredentials` returns `{ accessToken, webhookVerifier }`: eve uses the Connect-managed app token for Linear GraphQL calls and verifies Connect-forwarded webhooks by their Vercel OIDC signature instead of a Linear webhook secret. Token rotation, refresh, and multi-workspace tenancy stay inside Connect, so there is no `LINEAR_AGENT_ACCESS_TOKEN` or `LINEAR_WEBHOOK_SECRET` to manage.
38
+
39
+ ### Bring your own Linear app
40
+
41
+ To run a Linear OAuth app you manage yourself, pass its credentials directly instead:
42
+
11
43
  ```ts title="agent/channels/linear.ts"
12
44
  import { linearChannel } from "eve/channels/linear";
13
45
 
@@ -26,9 +58,7 @@ LINEAR_WEBHOOK_SECRET=... # verifies Linear-Signature
26
58
 
27
59
  The sample passes credentials explicitly. To rely on env vars instead, drop the `credentials` block: the access token falls back to `LINEAR_AGENT_ACCESS_TOKEN`, `LINEAR_ACCESS_TOKEN`, `LINEAR_API_KEY`, or `LINEAR_API_TOKEN`, and the webhook secret falls back to `LINEAR_WEBHOOK_SECRET`. Both fields also accept lazy resolver functions.
28
60
 
29
- ## Configure Linear
30
-
31
- Create a Linear OAuth app, enable Agent Session events, and point the webhook URL at:
61
+ Create the Linear OAuth app, enable Agent Session events, and point the webhook URL at:
32
62
 
33
63
  ```text
34
64
  https://<deployment>/eve/v1/linear
@@ -11,13 +11,13 @@ The Slack channel puts your agent inside a workspace. It answers `@mentions` and
11
11
  Create a Slack Connect client and copy its UID (e.g. `slack/my-agent`), then attach this project as the trigger destination at eve's Slack route:
12
12
 
13
13
  ```bash
14
- npm install -g vercel@latest && export FF_CONNECT_ENABLED=1
14
+ npm install -g vercel@latest
15
15
  vercel connect create slack --triggers
16
16
  vercel connect detach <uid> --yes
17
17
  vercel connect attach <uid> --triggers --trigger-path /eve/v1/slack --yes
18
18
  ```
19
19
 
20
- `FF_CONNECT_ENABLED=1` turns on the Connect commands, which are feature-flagged in the Vercel CLI today. The `create` step provisions a destination at the default Connect path. `detach` then `attach --trigger-path /eve/v1/slack` re-points the trigger at the eve Slack route, since eve does not serve the default Connect path. `--triggers` turns on Slack Event Subscriptions; without it, Slack never delivers `app_mention` or `message.im`. You can also create the client from the [Connect dashboard](https://vercel.com/d?to=/%5Bteam%5D/~/connect&title=Go+to+Connect).
20
+ The `create` step provisions a destination at the default Connect path. `detach` then `attach --trigger-path /eve/v1/slack` re-points the trigger at the eve Slack route, since eve does not serve the default Connect path. `--triggers` turns on Slack Event Subscriptions; without it, Slack never delivers `app_mention` or `message.im`. You can also create the client from the [Connect dashboard](https://vercel.com/d?to=/%5Bteam%5D/~/connect&title=Go+to+Connect).
21
21
 
22
22
  ## Add the channel
23
23
 
@@ -99,7 +99,7 @@ when you need the bearer token itself.
99
99
 
100
100
  ### Delivery
101
101
 
102
- The default handlers reply in-thread and show progress. Typing indicators post automatically: `Thinking…` on inbound, `Working…` on `turn.started`, a truncated reasoning snippet on `reasoning.appended`, and tool status on `actions.requested`. Reasoning snippets build progressively: extensions of at least four characters appear immediately, while smaller streamed deltas use the five-second refresh interval to avoid one Slack request per token. Override `events["reasoning.appended"]` if you prefer generic wording. Override `onAppMention` or the `events` handlers to customize.
102
+ The default handlers reply in-thread and show progress. Typing indicators post automatically: `Thinking…` on inbound, `Working…` on `turn.started`, a truncated reasoning snippet on `reasoning.appended`, and an action label on `actions.requested` — the tool name plus its most telling argument (`grep useEveAgent`, `read_file agent/agent.ts`), the subagent or remote-agent name for dispatched calls, and `+N more` when the model requests several actions at once. The model's own pre-tool narration, when present, takes precedence over the derived label. Reasoning snippets build progressively: extensions of at least four characters appear immediately, while smaller streamed deltas use the five-second refresh interval to avoid one Slack request per token. Override `events["reasoning.appended"]` if you prefer generic wording. Override `onAppMention` or the `events` handlers to customize.
103
103
 
104
104
  When a session starts without a `threadTs` (say, from a schedule or `receive(slack, ...)`), eve gives it a unique temporary continuation token. The first agent post anchors the session to the Slack message timestamp, and later posts and mentions resume that same session. Pass `initialMessage` with a `Card` to land a structured anchor first instead. `threadTs` and `initialMessage` are mutually exclusive.
105
105
 
@@ -36,7 +36,7 @@ export default defineAgent({
36
36
  });
37
37
  ```
38
38
 
39
- The world package backs workflow state, queues, hooks, and streams. Keep secrets and deployment-specific options in runtime environment variables read by that package, not in `agent.ts`. The selected world must match eve's bundled `@workflow/*` line (currently the `5.0.0-beta` line); pin it explicitly, since a mismatched world fails with a `ZodError: invalid_union` during run replay. See the [deployment guide](../guides/deployment#8-deploy-without-vercel) for the install command, plus [agent.ts](../agent-config#workflow-world) and [Workflow Worlds](https://workflow-sdk.dev/worlds).
39
+ The world package backs workflow state, queues, hooks, and streams. Keep secrets and deployment-specific options in runtime environment variables read by that package, not in `agent.ts`. Custom worlds must implement the runtime protocol expected by eve's vendored `@workflow/*` packages (currently the `5.0.0-beta` line); the Workflow SDK rejects incompatible protocol versions during initialization. See the [deployment guide](../guides/deployment#8-deploy-without-vercel) for the install command, plus [agent.ts](../agent-config#workflow-world) and [Workflow Worlds](https://workflow-sdk.dev/worlds).
40
40
 
41
41
  ## Resuming after a crash
42
42
 
@@ -140,7 +140,7 @@ Eve writes the standard Nitro output under `.output/` instead of Vercel Build Ou
140
140
 
141
141
  Self-deployed agents should make the Vercel-specific choices explicit:
142
142
 
143
- - Let the Workflow SDK use its default local world, which stores workflow state under `.workflow-data`, configure your host so that directory is on persistent storage, or select another world with `experimental.workflow.world` in the root `agent.ts`. When you select a custom world, install a world package built against the same `@workflow/*` line as your eve release (currently the `5.0.0-beta` line). The npm `latest` tag may lag, so pin the version explicitly, for example `pnpm add @workflow/world-postgres@5.0.0-beta.x`. A mismatched world (such as a `4.x` package against a `5.x` core) fails with a `ZodError: invalid_union` during run replay.
143
+ - Let the Workflow SDK use its default local world, which stores workflow state under `.workflow-data`, configure your host so that directory is on persistent storage, or select another world with `experimental.workflow.world` in the root `agent.ts`. When you select a custom world, install a world package built against the same `@workflow/*` line as your eve release (currently the `5.0.0-beta` line). The npm `latest` tag may lag, so pin the version explicitly, for example `pnpm add @workflow/world-postgres@5.0.0-beta.x`. The Workflow SDK rejects worlds with an incompatible runtime protocol during initialization.
144
144
  - If you put a reverse proxy or ingress in front of eve, forward **both** `/eve/` and `/.well-known/workflow/`. The workflow world delivers run callbacks to `/.well-known/workflow/v1/flow`; a proxy restricted to `/eve/` lets sessions start but silently stalls runs forever, because the callbacks never reach eve.
145
145
  - Install the AI SDK package for your provider, then use a direct provider model object and `OPENAI_API_KEY` / `ANTHROPIC_API_KEY` when you want no Gateway dependency.
146
146
  - Use `AI_GATEWAY_API_KEY` if you still want Gateway routing from a non-Vercel host.
@@ -34,12 +34,12 @@ export default withEve(nextConfig, {
34
34
 
35
35
  All fields are optional.
36
36
 
37
- | Option | Type | Default | Purpose |
38
- | -------------------- | -------- | ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
39
- | `eveRoot` | `string` | Next.js app root | Path to the eve app root, relative to `process.cwd()` unless absolute. Set it when the agent lives outside the Next.js project. |
40
- | `eveBuildCommand` | `string` | `"eve build"` | Build command for the generated eve Vercel service. Use it when the eve service needs project-specific prework, without changing the Next.js build. |
41
- | `servicePrefix` | `string` | `"/_eve_internal/eve"` | Private Vercel route namespace for the eve service. Must match the eve service's mount in your Vercel Build Output config when you set it manually. |
42
- | `devServerTimeoutMs` | `number` | `180000` | Maximum time to wait for the eve development server to become available. |
37
+ | Option | Type | Default | Purpose |
38
+ | -------------------- | -------- | ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
39
+ | `eveRoot` | `string` | Next.js app root | Path to the eve app root, relative to `process.cwd()` unless absolute. Set it when the agent lives outside the Next.js project. |
40
+ | `eveBuildCommand` | `string` | `"eve build"` | Build command for the generated eve Vercel service. Use it when the eve service needs project-specific prework, without changing the Next.js build. |
41
+ | `servicePrefix` | `string` | `"/_eve_internal/eve"` | Private route namespace for legacy manual Vercel service configs and non-Vercel production proxying. Generated Vercel configs use service routes instead. |
42
+ | `devServerTimeoutMs` | `number` | `180000` | Maximum time to wait for the eve development server to become available. |
43
43
 
44
44
  For slow cold starts, increase the development timeout:
45
45
 
@@ -75,7 +75,7 @@ For a public demo, use `none()` (also from `eve/channels/auth`) to skip authenti
75
75
  ## Dev vs deploy topology
76
76
 
77
77
  - **Local dev.** `npm run dev` boots the eve dev server next to `next dev` and rewrites the eve routes over to it. The browser only ever talks to the Next.js origin.
78
- - **Vercel.** The web app and the eve runtime deploy as a single project. The web app stays public; the eve runtime sits behind it on the same site origin. When the agent needs its own build step, set `eveBuildCommand`:
78
+ - **Vercel.** The web app and the eve runtime deploy as a single project. `withEve()` writes Build Output `services` for eve and `routes` that send `/eve/v1/**` to that service before filesystem routing; the Next.js app itself remains the default app. When the agent needs its own build step, set `eveBuildCommand`:
79
79
 
80
80
  ```ts
81
81
  export default withEve(nextConfig, {
@@ -111,6 +111,8 @@ Do not rely on subagent delegation by itself as an approval boundary. Put sensit
111
111
 
112
112
  Each delegated subagent spins up its own child session and stream. The parent stream carries the control-plane events `subagent.called` and `subagent.completed`, plus interactive `input.requested`, `authorization.required`, and `authorization.completed` events proxied from descendants so the root channel can prompt the user. To follow the child's other progress, read `subagent.called.data.childSessionId` and subscribe at `GET /eve/v1/session/:childSessionId/stream`.
113
113
 
114
+ Subagent model calls automatically retry classified transient provider failures, including overload errors delivered after a stream starts. eve makes at most three fresh model-call attempts, repeating only the current uncommitted call so completed earlier steps, tool results, and sandbox work remain available to the child. Other recoverable task errors fall back to Workflow's durable step retry from the last committed session snapshot. Exhausting the transient model-call attempts or the dedicated empty-response reissue returns one failed task result instead of stacking both retry budgets; terminal errors fail immediately.
115
+
114
116
  ## When to split
115
117
 
116
118
  Split out a subagent when the task needs a different prompt or specialist role, a narrower tool surface, or its own runtime context. Don't reach for one when a [skill](./skills) would do. If the agent can keep its identity and needs only an optional procedure, a skill is the lighter choice.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eve",
3
- "version": "0.22.1",
3
+ "version": "0.22.2",
4
4
  "private": false,
5
5
  "description": "Filesystem-first framework for durable backend AI agents that run anywhere.",
6
6
  "keywords": [
@@ -293,11 +293,13 @@
293
293
  "@vercel/oidc": "3.5.0",
294
294
  "@vercel/sandbox": "2.3.0",
295
295
  "@vercel/sdk": "1.28.1",
296
- "@workflow/core": "5.0.0-beta.26",
297
- "@workflow/errors": "5.0.0-beta.8",
296
+ "@workflow/core": "5.0.0-beta.28",
297
+ "@workflow/errors": "5.0.0-beta.10",
298
298
  "@workflow/serde": "5.0.0-beta.2",
299
- "@workflow/world": "5.0.0-beta.14",
300
- "@workflow/world-local": "5.0.0-beta.22",
299
+ "@workflow/utils": "5.0.0-beta.6",
300
+ "@workflow/world": "5.0.0-beta.16",
301
+ "@workflow/world-local": "5.0.0-beta.24",
302
+ "@workflow/world-vercel": "5.0.0-beta.24",
301
303
  "ai": "^7.0.0",
302
304
  "autoevals": "0.0.132",
303
305
  "chat": "4.31.0",