eve 0.17.2 → 0.18.1

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 (35) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/dist/src/compiled/.vendor-stamp.json +1 -1
  3. package/dist/src/compiled/@vercel/sandbox/api-client/api-client.d.ts +19 -16
  4. package/dist/src/compiled/@vercel/sandbox/api-client/index.d.ts +1 -1
  5. package/dist/src/compiled/@vercel/sandbox/api-client/validators.d.ts +37 -23
  6. package/dist/src/compiled/@vercel/sandbox/command.d.ts +2 -8
  7. package/dist/src/compiled/@vercel/sandbox/index.js +5 -5
  8. package/dist/src/compiled/@vercel/sandbox/sandbox.d.ts +43 -16
  9. package/dist/src/compiled/@vercel/sandbox/snapshot.d.ts +5 -5
  10. package/dist/src/compiled/_chunks/node/{auth-DF_ft5ea.js → auth-CWHn3Yve.js} +1 -1
  11. package/dist/src/compiled/_chunks/node/{version-TugPKZua.js → version-DD-FX9rK.js} +1 -1
  12. package/dist/src/execution/sandbox/bindings/vercel-create-sdk.js +1 -1
  13. package/dist/src/execution/sandbox/bindings/vercel.js +1 -1
  14. package/dist/src/internal/application/package.js +1 -1
  15. package/dist/src/internal/nitro/dev-runtime-source-snapshot-copy.js +1 -1
  16. package/dist/src/public/channels/auth.d.ts +2 -2
  17. package/dist/src/public/channels/slack/defaults.d.ts +3 -1
  18. package/dist/src/public/channels/slack/defaults.js +3 -3
  19. package/dist/src/public/channels/slack/hitl.d.ts +10 -4
  20. package/dist/src/public/channels/slack/hitl.js +4 -1
  21. package/dist/src/public/channels/slack/interactions.js +1 -1
  22. package/dist/src/public/channels/slack/limits.d.ts +5 -0
  23. package/dist/src/public/channels/slack/limits.js +1 -1
  24. package/dist/src/public/sandbox/vercel-sandbox.d.ts +4 -1
  25. package/dist/src/runtime/governance/auth/oidc.js +1 -1
  26. package/dist/src/setup/boxes/link-project.d.ts +7 -3
  27. package/dist/src/setup/boxes/link-project.js +1 -1
  28. package/dist/src/setup/onboarding.js +1 -1
  29. package/dist/src/setup/scaffold/create/project.js +1 -1
  30. package/dist/src/setup/vercel-project-framework.d.ts +10 -0
  31. package/dist/src/setup/vercel-project-framework.js +1 -0
  32. package/dist/src/setup/vercel-project.d.ts +8 -3
  33. package/dist/src/setup/vercel-project.js +0 -0
  34. package/docs/sandbox.mdx +1 -1
  35. package/package.json +3 -31
@@ -1 +1 @@
1
- import{createLogger}from"#internal/logging.js";import{buildSlackBinding,resolveSlackBotToken,slackContinuationToken}from"#public/channels/slack/api.js";import{buildSlackAuthContext}from"#public/channels/slack/auth.js";import{HITL_FREEFORM_MODAL_ACTION_ID,HITL_FREEFORM_MODAL_BLOCK_ID,HITL_FREEFORM_MODAL_CALLBACK_ID,buildAnsweredBlocks,buildFreeformModalView,deriveHitlResponse,freeformRequestIdFromActionId,isFreeformAction,isHitlAction}from"#public/channels/slack/hitl.js";import{parseSlackWebhookBody}from"#compiled/@chat-adapter/slack/webhook.js";const log=createLogger(`slack.interactions`);function parseBlockActionsPayload(e){if(isSharedBlockActionsPayload(e))return parseSharedBlockActionsPayload(e);let t=e,n=t.actions;if(!Array.isArray(n))return null;let r=t.channel?.id,i=t.message,a=i?.thread_ts??i?.ts;if(!r||!a)return null;let o=t.team,s=t.user,c=o?.id??s.team_id,l={id:s.id,username:s.username,name:s.name},u=i?.blocks??[];return{actions:n.map(e=>({actionId:String(e.action_id??``),value:e.value==null?void 0:String(e.value),blockId:e.block_id==null?void 0:String(e.block_id),selectedOptionValue:extractSelectedOptionValue(e),messageTs:i?.ts,label:extractActionLabel(e),user:l})),channelId:r,threadTs:a,teamId:c,messageBlocks:u}}function isSharedBlockActionsPayload(e){return e.kind===`block_actions`&&Array.isArray(e.actions)}function parseSharedBlockActionsPayload(e){return!e.channelId||!e.threadTs?null:{actions:e.actions.map(t=>({actionId:t.actionId,value:t.value,blockId:t.blockId,selectedOptionValue:t.selectedOptionValue,messageTs:e.messageTs,label:t.label,user:{id:t.user?.id??e.userId,username:t.user?.username,name:t.user?.name}})),channelId:e.channelId,threadTs:e.threadTs,teamId:e.teamId,messageBlocks:e.messageBlocks??[]}}function extractSelectedOptionValue(e){let t=e.selected_option;return typeof t?.value==`string`?t.value:void 0}function extractActionLabel(e){let t=e.selected_option?.text?.text;if(typeof t==`string`&&t.length>0)return t;let n=e.text?.text;if(typeof n==`string`&&n.length>0)return n}function findPromptBlock(e){for(let t of e)if(typeof t==`object`&&t&&t.type===`section`)return t}function readPromptTextFromBlocks(e){let t=findPromptBlock(e)?.text?.text;return typeof t==`string`&&t.length>0?t:void 0}async function handleInteractionPost(e,n,a){let o=new Response(`ok`,{status:200}),s;try{s=parseSlackWebhookBody(e,{contentType:`application/x-www-form-urlencoded`})}catch{return log.warn(`failed to parse Slack interaction payload`),o}if(s.kind===`view_submission`)return handleViewSubmission(s,n,a);if(s.kind!==`block_actions`)return o;let c=parseBlockActionsPayload(s);if(!c)return o;let l=c.actions.find(e=>isFreeformAction(e.actionId));if(l)return await openFreeformModal({payload:s.raw,interaction:c,freeformAction:l,deps:a}),o;let d=slackContinuationToken(c.channelId,c.threadTs),p=c.actions.map(deriveHitlResponse).filter(e=>e!==null);if(p.length>0){let e=c.actions[0]?.user;if(!e)return o;n.waitUntil(n.send({inputResponses:p},{auth:buildSlackAuthContext({channelId:c.channelId,teamId:c.teamId,threadTs:c.threadTs,userId:e.id,userName:e.username??e.name}),continuationToken:d,state:{channelId:c.channelId,threadTs:c.threadTs,teamId:c.teamId??null,triggeringUserId:e.id}}).catch(e=>{log.error(`HITL interaction delivery failed`,{error:e})})),n.waitUntil(updateAnsweredHitlCard(c,a).catch(e=>{log.error(`HITL answered-card update failed`,{error:e})}))}let m=a.config.onInteraction;if(m){let e=c.actions.filter(e=>!isHitlAction(e.actionId));if(e.length>0){let{thread:r,slack:i}=buildSlackBinding({botToken:a.config.credentials?.botToken,channelId:c.channelId,threadTs:c.threadTs,teamId:c.teamId}),o={thread:r,slack:i};for(let t of e)n.waitUntil(Promise.resolve(m(t,o)).catch(e=>{log.error(`custom interaction handler failed`,{error:e})}))}}return o}async function openFreeformModal(e){let t=e.payload.trigger_id;if(typeof t!=`string`||t.length===0){log.warn(`freeform button click missing trigger_id — cannot open modal`);return}let i=freeformRequestIdFromActionId(e.freeformAction.actionId)??e.freeformAction.value;if(!i){log.warn(`freeform button click missing requestId`);return}let a=e.freeformAction.messageTs;if(!a){log.warn(`freeform button click missing messageTs`);return}let o=buildFreeformModalView({metadata:{continuationToken:slackContinuationToken(e.interaction.channelId,e.interaction.threadTs),channelId:e.interaction.channelId,threadTs:e.interaction.threadTs,messageTs:a,requestId:i},prompt:readPromptTextFromBlocks(e.interaction.messageBlocks)}),s=await resolveSlackBotToken(e.deps.config.credentials?.botToken),c=await fetch(`https://slack.com/api/views.open`,{method:`POST`,headers:{authorization:`Bearer ${s}`,"content-type":`application/json; charset=utf-8`},body:JSON.stringify({trigger_id:t,view:o})});c.ok||log.error(`Slack views.open returned non-2xx`,{status:c.status})}async function handleViewSubmission(e,t,n){let r=new Response(null,{status:200});if(e.callbackId!==HITL_FREEFORM_MODAL_CALLBACK_ID)return r;let c;try{c=JSON.parse(e.privateMetadata??``)}catch{return log.warn(`freeform view_submission carries invalid private_metadata`),r}if(!c.continuationToken||!c.requestId||!c.messageTs||!c.channelId||!c.threadTs)return r;let l=e.values?.find(e=>e.blockId===HITL_FREEFORM_MODAL_BLOCK_ID&&e.actionId===HITL_FREEFORM_MODAL_ACTION_ID)?.value??``;if(l.length===0)return r;let u=e.user,d=e.userId,f=u?.teamId??e.teamId??null;return t.waitUntil(t.send({inputResponses:[{requestId:c.requestId,text:l}]},{auth:buildSlackAuthContext({channelId:c.channelId,teamId:f,threadTs:c.threadTs,userId:d,userName:u?.username??u?.name}),continuationToken:c.continuationToken,state:{channelId:c.channelId,threadTs:c.threadTs,teamId:f,triggeringUserId:d}}).catch(e=>{log.error(`freeform answer delivery failed`,{error:e})})),t.waitUntil(updateAnsweredFreeformCard({channelId:c.channelId,messageTs:c.messageTs,answerLabel:l,userId:d??void 0,deps:n}).catch(e=>{log.error(`freeform answered-card update failed`,{error:e})})),r}async function updateAnsweredHitlCard(e,t){let r=e.actions.find(e=>isHitlAction(e.actionId));if(!r||!r.messageTs)return;let i=r.label??r.selectedOptionValue??r.value;if(!i)return;let a=buildAnsweredBlocks({promptBlock:findPromptBlock(e.messageBlocks),answerLabel:i,userId:r.user.id}),o=await resolveSlackBotToken(t.config.credentials?.botToken),s=await fetch(`https://slack.com/api/chat.update`,{method:`POST`,headers:{authorization:`Bearer ${o}`,"content-type":`application/json; charset=utf-8`},body:JSON.stringify({channel:e.channelId,ts:r.messageTs,blocks:a,text:`Answered: ${i}`})});if(!s.ok)throw Error(`Slack chat.update returned HTTP ${s.status}`)}async function updateAnsweredFreeformCard(e){let t=buildAnsweredBlocks({promptBlock:void 0,answerLabel:e.answerLabel,userId:e.userId}),r=await resolveSlackBotToken(e.deps.config.credentials?.botToken),i=await fetch(`https://slack.com/api/chat.update`,{method:`POST`,headers:{authorization:`Bearer ${r}`,"content-type":`application/json; charset=utf-8`},body:JSON.stringify({channel:e.channelId,ts:e.messageTs,blocks:t,text:`Answered: ${e.answerLabel}`})});if(!i.ok)throw Error(`Slack chat.update returned HTTP ${i.status}`)}export{handleInteractionPost,parseBlockActionsPayload};
1
+ import{createLogger}from"#internal/logging.js";import{buildSlackBinding,resolveSlackBotToken,slackContinuationToken}from"#public/channels/slack/api.js";import{buildSlackAuthContext}from"#public/channels/slack/auth.js";import{HITL_FREEFORM_MODAL_ACTION_ID,HITL_FREEFORM_MODAL_BLOCK_ID,HITL_FREEFORM_MODAL_CALLBACK_ID,buildAnsweredBlocks,buildFreeformModalView,deriveHitlResponse,freeformRequestIdFromActionId,isFreeformAction,isHitlAction}from"#public/channels/slack/hitl.js";import{parseSlackWebhookBody}from"#compiled/@chat-adapter/slack/webhook.js";const log=createLogger(`slack.interactions`);function parseBlockActionsPayload(e){if(isSharedBlockActionsPayload(e))return parseSharedBlockActionsPayload(e);let t=e,n=t.actions;if(!Array.isArray(n))return null;let r=t.channel?.id,i=t.message,a=i?.thread_ts??i?.ts;if(!r||!a)return null;let o=t.team,s=t.user,c=o?.id??s.team_id,l={id:s.id,username:s.username,name:s.name},u=i?.blocks??[];return{actions:n.map(e=>({actionId:String(e.action_id??``),value:e.value==null?void 0:String(e.value),blockId:e.block_id==null?void 0:String(e.block_id),selectedOptionValue:extractSelectedOptionValue(e),messageTs:i?.ts,label:extractActionLabel(e),user:l})),channelId:r,threadTs:a,teamId:c,messageBlocks:u}}function isSharedBlockActionsPayload(e){return e.kind===`block_actions`&&Array.isArray(e.actions)}function parseSharedBlockActionsPayload(e){return!e.channelId||!e.threadTs?null:{actions:e.actions.map(t=>({actionId:t.actionId,value:t.value,blockId:t.blockId,selectedOptionValue:t.selectedOptionValue,messageTs:e.messageTs,label:t.label,user:{id:t.user?.id??e.userId,username:t.user?.username,name:t.user?.name}})),channelId:e.channelId,threadTs:e.threadTs,teamId:e.teamId,messageBlocks:e.messageBlocks??[]}}function extractSelectedOptionValue(e){let t=e.selected_option;return typeof t?.value==`string`?t.value:void 0}function extractActionLabel(e){let t=e.selected_option?.text?.text;if(typeof t==`string`&&t.length>0)return t;let n=e.text?.text;if(typeof n==`string`&&n.length>0)return n}function findPromptBlock(e){return findPromptBlocks(e)[0]}function findPromptBlocks(e){let t=[];for(let n of e){if(typeof n!=`object`||!n)continue;let e=n.type;if(e===`actions`)break;(e===`section`||e===`context`||e===`divider`||e===`image`)&&t.push(n)}return t}function readPromptTextFromBlocks(e){let t=findPromptBlock(e)?.text?.text;return typeof t==`string`&&t.length>0?t:void 0}async function handleInteractionPost(e,n,a){let o=new Response(`ok`,{status:200}),s;try{s=parseSlackWebhookBody(e,{contentType:`application/x-www-form-urlencoded`})}catch{return log.warn(`failed to parse Slack interaction payload`),o}if(s.kind===`view_submission`)return handleViewSubmission(s,n,a);if(s.kind!==`block_actions`)return o;let c=parseBlockActionsPayload(s);if(!c)return o;let l=c.actions.find(e=>isFreeformAction(e.actionId));if(l)return await openFreeformModal({payload:s.raw,interaction:c,freeformAction:l,deps:a}),o;let d=slackContinuationToken(c.channelId,c.threadTs),p=c.actions.map(deriveHitlResponse).filter(e=>e!==null);if(p.length>0){let e=c.actions[0]?.user;if(!e)return o;n.waitUntil(n.send({inputResponses:p},{auth:buildSlackAuthContext({channelId:c.channelId,teamId:c.teamId,threadTs:c.threadTs,userId:e.id,userName:e.username??e.name}),continuationToken:d,state:{channelId:c.channelId,threadTs:c.threadTs,teamId:c.teamId??null,triggeringUserId:e.id}}).catch(e=>{log.error(`HITL interaction delivery failed`,{error:e})})),n.waitUntil(updateAnsweredHitlCard(c,a).catch(e=>{log.error(`HITL answered-card update failed`,{error:e})}))}let m=a.config.onInteraction;if(m){let e=c.actions.filter(e=>!isHitlAction(e.actionId));if(e.length>0){let{thread:r,slack:i}=buildSlackBinding({botToken:a.config.credentials?.botToken,channelId:c.channelId,threadTs:c.threadTs,teamId:c.teamId}),o={thread:r,slack:i};for(let t of e)n.waitUntil(Promise.resolve(m(t,o)).catch(e=>{log.error(`custom interaction handler failed`,{error:e})}))}}return o}async function openFreeformModal(e){let t=e.payload.trigger_id;if(typeof t!=`string`||t.length===0){log.warn(`freeform button click missing trigger_id — cannot open modal`);return}let i=freeformRequestIdFromActionId(e.freeformAction.actionId)??e.freeformAction.value;if(!i){log.warn(`freeform button click missing requestId`);return}let a=e.freeformAction.messageTs;if(!a){log.warn(`freeform button click missing messageTs`);return}let o=buildFreeformModalView({metadata:{continuationToken:slackContinuationToken(e.interaction.channelId,e.interaction.threadTs),channelId:e.interaction.channelId,threadTs:e.interaction.threadTs,messageTs:a,requestId:i},prompt:readPromptTextFromBlocks(e.interaction.messageBlocks)}),s=await resolveSlackBotToken(e.deps.config.credentials?.botToken),c=await fetch(`https://slack.com/api/views.open`,{method:`POST`,headers:{authorization:`Bearer ${s}`,"content-type":`application/json; charset=utf-8`},body:JSON.stringify({trigger_id:t,view:o})});c.ok||log.error(`Slack views.open returned non-2xx`,{status:c.status})}async function handleViewSubmission(e,t,n){let r=new Response(null,{status:200});if(e.callbackId!==HITL_FREEFORM_MODAL_CALLBACK_ID)return r;let c;try{c=JSON.parse(e.privateMetadata??``)}catch{return log.warn(`freeform view_submission carries invalid private_metadata`),r}if(!c.continuationToken||!c.requestId||!c.messageTs||!c.channelId||!c.threadTs)return r;let l=e.values?.find(e=>e.blockId===HITL_FREEFORM_MODAL_BLOCK_ID&&e.actionId===HITL_FREEFORM_MODAL_ACTION_ID)?.value??``;if(l.length===0)return r;let u=e.user,d=e.userId,f=u?.teamId??e.teamId??null;return t.waitUntil(t.send({inputResponses:[{requestId:c.requestId,text:l}]},{auth:buildSlackAuthContext({channelId:c.channelId,teamId:f,threadTs:c.threadTs,userId:d,userName:u?.username??u?.name}),continuationToken:c.continuationToken,state:{channelId:c.channelId,threadTs:c.threadTs,teamId:f,triggeringUserId:d}}).catch(e=>{log.error(`freeform answer delivery failed`,{error:e})})),t.waitUntil(updateAnsweredFreeformCard({channelId:c.channelId,messageTs:c.messageTs,answerLabel:l,userId:d??void 0,deps:n}).catch(e=>{log.error(`freeform answered-card update failed`,{error:e})})),r}async function updateAnsweredHitlCard(e,t){let r=e.actions.find(e=>isHitlAction(e.actionId));if(!r||!r.messageTs)return;let i=r.label??r.selectedOptionValue??r.value;if(!i)return;let a=buildAnsweredBlocks({promptBlocks:findPromptBlocks(e.messageBlocks),answerLabel:i,userId:r.user.id}),o=await resolveSlackBotToken(t.config.credentials?.botToken),s=await fetch(`https://slack.com/api/chat.update`,{method:`POST`,headers:{authorization:`Bearer ${o}`,"content-type":`application/json; charset=utf-8`},body:JSON.stringify({channel:e.channelId,ts:r.messageTs,blocks:a,text:`Answered: ${i}`})});if(!s.ok)throw Error(`Slack chat.update returned HTTP ${s.status}`)}async function updateAnsweredFreeformCard(e){let t=buildAnsweredBlocks({promptBlocks:[],answerLabel:e.answerLabel,userId:e.userId}),r=await resolveSlackBotToken(e.deps.config.credentials?.botToken),i=await fetch(`https://slack.com/api/chat.update`,{method:`POST`,headers:{authorization:`Bearer ${r}`,"content-type":`application/json; charset=utf-8`},body:JSON.stringify({channel:e.channelId,ts:e.messageTs,blocks:t,text:`Answered: ${e.answerLabel}`})});if(!i.ok)throw Error(`Slack chat.update returned HTTP ${i.status}`)}export{handleInteractionPost,parseBlockActionsPayload};
@@ -29,6 +29,11 @@ export declare const SLACK_SECTION_TEXT_MAX_LENGTH = 3000;
29
29
  * Top-level `text` field on `chat.postMessage` is capped at 40000 chars.
30
30
  */
31
31
  export declare const SLACK_MESSAGE_TEXT_MAX_LENGTH = 40000;
32
+ /**
33
+ * `chat.postMessage` rejects payloads with more than 50 blocks
34
+ * (`invalid_blocks`).
35
+ */
36
+ export declare const SLACK_MAX_BLOCKS_PER_MESSAGE = 50;
32
37
  /**
33
38
  * `views.open` modal title is capped at 24 characters.
34
39
  */
@@ -1 +1 @@
1
- const SLACK_TYPING_STATUS_MAX_LENGTH=50,SLACK_BLOCK_KIT_PLAIN_TEXT_MAX_LENGTH=75,SLACK_SECTION_TEXT_MAX_LENGTH=3e3,SLACK_MESSAGE_TEXT_MAX_LENGTH=4e4,SLACK_MODAL_TITLE_MAX_LENGTH=24;function truncateTypingStatus(e){return truncateWithEllipsis(stripTypingStatusMarkdown(e).trim().replace(/\s+/gu,` `),50)}function truncatePlainText(e){if(e!==void 0)return truncateWithEllipsis(e,75)}function truncateSectionText(e){return truncateWithEllipsis(e,SLACK_SECTION_TEXT_MAX_LENGTH)}function truncateMessageText(e){return truncateWithEllipsis(e,SLACK_MESSAGE_TEXT_MAX_LENGTH)}function truncateModalTitle(e){return truncateWithEllipsis(e,24)}function truncateWithEllipsis(e,t){if(e.length<=t)return e;let n=Math.max(0,t-3);return`${e.slice(0,n).trimEnd()}...`}function stripTypingStatusMarkdown(e){return e.replace(/\[([^\]]+)\]\([^)]+\)/gu,`$1`).replace(/`([^`]+)`/gu,`$1`).replace(/~~([^~]+)~~/gu,`$1`).replace(/(\*\*|__)([^*_]+)\1/gu,`$2`).replace(/(^|[^\p{L}\p{N}])([*_])([^*_]+)\2(?=$|[^\p{L}\p{N}])/gu,`$1$3`)}export{SLACK_BLOCK_KIT_PLAIN_TEXT_MAX_LENGTH,SLACK_MESSAGE_TEXT_MAX_LENGTH,SLACK_MODAL_TITLE_MAX_LENGTH,SLACK_SECTION_TEXT_MAX_LENGTH,SLACK_TYPING_STATUS_MAX_LENGTH,truncateMessageText,truncateModalTitle,truncatePlainText,truncateSectionText,truncateTypingStatus};
1
+ const SLACK_TYPING_STATUS_MAX_LENGTH=50,SLACK_BLOCK_KIT_PLAIN_TEXT_MAX_LENGTH=75,SLACK_SECTION_TEXT_MAX_LENGTH=3e3,SLACK_MESSAGE_TEXT_MAX_LENGTH=4e4,SLACK_MAX_BLOCKS_PER_MESSAGE=50,SLACK_MODAL_TITLE_MAX_LENGTH=24;function truncateTypingStatus(e){return truncateWithEllipsis(stripTypingStatusMarkdown(e).trim().replace(/\s+/gu,` `),50)}function truncatePlainText(e){if(e!==void 0)return truncateWithEllipsis(e,75)}function truncateSectionText(e){return truncateWithEllipsis(e,SLACK_SECTION_TEXT_MAX_LENGTH)}function truncateMessageText(e){return truncateWithEllipsis(e,SLACK_MESSAGE_TEXT_MAX_LENGTH)}function truncateModalTitle(e){return truncateWithEllipsis(e,24)}function truncateWithEllipsis(e,t){if(e.length<=t)return e;let n=Math.max(0,t-3);return`${e.slice(0,n).trimEnd()}...`}function stripTypingStatusMarkdown(e){return e.replace(/\[([^\]]+)\]\([^)]+\)/gu,`$1`).replace(/`([^`]+)`/gu,`$1`).replace(/~~([^~]+)~~/gu,`$1`).replace(/(\*\*|__)([^*_]+)\1/gu,`$2`).replace(/(^|[^\p{L}\p{N}])([*_])([^*_]+)\2(?=$|[^\p{L}\p{N}])/gu,`$1$3`)}export{SLACK_BLOCK_KIT_PLAIN_TEXT_MAX_LENGTH,SLACK_MAX_BLOCKS_PER_MESSAGE,SLACK_MESSAGE_TEXT_MAX_LENGTH,SLACK_MODAL_TITLE_MAX_LENGTH,SLACK_SECTION_TEXT_MAX_LENGTH,SLACK_TYPING_STATUS_MAX_LENGTH,truncateMessageText,truncateModalTitle,truncatePlainText,truncateSectionText,truncateTypingStatus};
@@ -4,7 +4,7 @@ type VercelUpdateOptions = Parameters<Vercel.Sandbox["update"]>[0];
4
4
  type VercelSandboxInternalCreateOptions = {
5
5
  readonly [key: `__${string}`]: unknown;
6
6
  };
7
- type VercelSandboxAuthorCreateOptions<T> = T extends unknown ? Omit<T, "name" | "onResume" | "persistent" | "signal"> & VercelSandboxInternalCreateOptions : never;
7
+ type VercelSandboxAuthorCreateOptions<T> = T extends unknown ? Omit<T, "name" | "onResume" | "persistent" | "runtime" | "signal"> & VercelSandboxInternalCreateOptions : never;
8
8
  /**
9
9
  * Options accepted by `vercel(opts)`. Forwarded to Vercel
10
10
  * Sandbox creation for every fresh sandbox the framework creates
@@ -21,6 +21,9 @@ type VercelSandboxAuthorCreateOptions<T> = T extends unknown ? Omit<T, "name" |
21
21
  * are excluded: the framework owns those and overrides any
22
22
  * author-supplied values.
23
23
  *
24
+ * `runtime` is excluded as well: eve always boots its sandboxes from the
25
+ * published eve image, which is mutually exclusive with a stock runtime.
26
+ *
24
27
  * `source` is honored only on the template create at prewarm time, so
25
28
  * an author-supplied snapshot, git revision, or tarball becomes the
26
29
  * base layer for the template. Framework setup, bootstrap, and seed
@@ -1 +1 @@
1
- import{z}from"#compiled/zod/index.js";import{createRemoteJWKSet,jwtVerify}from"#compiled/jose/index.js";import{areTokenClaimMatchersSatisfied,createJwtAuthenticatedCallerPrincipal}from"#runtime/governance/auth/token-claims.js";const oidcDiscoveryDocumentSchema=z.object({issuer:z.string().optional(),jwks_uri:z.string().url()}).passthrough(),oidcDiscoveryDocumentCache=new Map,oidcJwksCache=new Map;async function authenticateOidcStrategy(e){let t;try{t=await getOidcRemoteJwks(e.strategy)}catch(e){return{kind:`misconfigured`,message:`Failed to load OIDC discovery metadata. ${e instanceof Error?e.message:`Unknown discovery failure.`}`}}try{let a=await jwtVerify(e.token,t,{audience:[...e.strategy.audiences],clockTolerance:e.strategy.clockSkewSeconds,issuer:e.strategy.issuer});if(e.strategy.acceptCurrentVercelProject&&e.strategy.issuer.startsWith(`https://oidc.vercel.com/`)&&a.payload.external_sub!==void 0)return typeof a.payload.external_sub!=`string`||a.payload.external_sub.length===0||!currentVercelProjectMatches({payload:a.payload,strategy:e.strategy})||!currentVercelEnvironmentMatches({payload:a.payload,strategy:e.strategy})?{kind:`caller-not-allowed`}:{kind:`authenticated`,principal:createJwtAuthenticatedCallerPrincipal({authenticator:`oidc`,issuerClaims:[`external_iss`,`connector_id`],payload:a.payload,principalType:`user`,subjectClaim:`external_sub`})};if(e.strategy.acceptCurrentVercelProject&&e.strategy.issuer.startsWith(`https://oidc.vercel.com/`)&&a.payload.user_id!==void 0){if(typeof a.payload.user_id!=`string`||a.payload.user_id.length===0||a.payload.environment!==`development`||!currentVercelProjectMatches({payload:a.payload,strategy:e.strategy}))return{kind:`caller-not-allowed`};if(currentVercelEnvironmentMatches({payload:a.payload,strategy:e.strategy}))return{kind:`authenticated`,principal:createJwtAuthenticatedCallerPrincipal({authenticator:`oidc`,payload:a.payload,principalType:`user`,subjectClaim:`user_id`})};if(e.strategy.currentVercelProject?.environment!==`preview`)return{kind:`caller-not-allowed`}}if(typeof a.payload.sub!=`string`||a.payload.sub.length===0)return{kind:`not-authenticated`};let o=e.strategy.acceptCurrentVercelProject&&isCurrentVercelProjectToken({issuer:e.strategy.issuer,payload:a.payload,strategy:e.strategy}),s=o&&isCurrentVercelEnvironmentToken({payload:a.payload,strategy:e.strategy});return!o&&!areTokenClaimMatchersSatisfied(a.payload,e.strategy)?{kind:`caller-not-allowed`}:{kind:`authenticated`,principal:createJwtAuthenticatedCallerPrincipal({authenticator:`oidc`,payload:a.payload,principalType:s?`runtime`:`service`})}}catch{return{kind:`not-authenticated`}}}async function getOidcRemoteJwks(e){let n=await getOidcDiscoveryDocument(e.discoveryUrl),r=oidcJwksCache.get(n.jwks_uri);if(r!==void 0)return r;let i=createRemoteJWKSet(new URL(n.jwks_uri));return oidcJwksCache.set(n.jwks_uri,i),i}async function getOidcDiscoveryDocument(e){let t=oidcDiscoveryDocumentCache.get(e);if(t!==void 0)return await t;let n=fetch(e,{headers:{accept:`application/json`}}).then(async e=>{if(!e.ok)throw Error(`Discovery route returned HTTP ${e.status}.`);return oidcDiscoveryDocumentSchema.parse(await e.json())}).catch(t=>{throw oidcDiscoveryDocumentCache.delete(e),t});return oidcDiscoveryDocumentCache.set(e,n),await n}function isCurrentVercelProjectToken(e){if(!e.issuer.startsWith(`https://oidc.vercel.com`))return!1;let t=e.strategy.currentVercelProject;return t===void 0?!1:typeof e.payload.project_id==`string`&&e.payload.project_id===t.projectId}function currentVercelProjectMatches(e){let t=e.strategy.currentVercelProject;return t===void 0?!1:typeof e.payload.project_id==`string`&&e.payload.project_id===t.projectId}function isCurrentVercelEnvironmentToken(e){let t=e.strategy.currentVercelProject?.environment;return t===void 0||t.length===0?!1:typeof e.payload.environment==`string`&&e.payload.environment===t}function currentVercelEnvironmentMatches(e){let t=e.strategy.currentVercelProject?.environment;return t===void 0||t.length===0?!1:typeof e.payload.environment==`string`&&e.payload.environment===t}export{authenticateOidcStrategy};
1
+ import{z}from"#compiled/zod/index.js";import{createRemoteJWKSet,jwtVerify}from"#compiled/jose/index.js";import{areTokenClaimMatchersSatisfied,createJwtAuthenticatedCallerPrincipal}from"#runtime/governance/auth/token-claims.js";const oidcDiscoveryDocumentSchema=z.object({issuer:z.string().optional(),jwks_uri:z.string().url()}).passthrough(),oidcDiscoveryDocumentCache=new Map,oidcJwksCache=new Map;async function authenticateOidcStrategy(e){let t;try{t=await getOidcRemoteJwks(e.strategy)}catch(e){return{kind:`misconfigured`,message:`Failed to load OIDC discovery metadata. ${e instanceof Error?e.message:`Unknown discovery failure.`}`}}try{let a=await jwtVerify(e.token,t,{audience:[...e.strategy.audiences],clockTolerance:e.strategy.clockSkewSeconds,issuer:e.strategy.issuer});if(e.strategy.acceptCurrentVercelProject&&e.strategy.issuer.startsWith(`https://oidc.vercel.com/`)&&a.payload.external_sub!==void 0)return typeof a.payload.external_sub!=`string`||a.payload.external_sub.length===0||!currentVercelProjectMatches({payload:a.payload,strategy:e.strategy})||!currentVercelEnvironmentMatches({payload:a.payload,strategy:e.strategy})?{kind:`caller-not-allowed`}:{kind:`authenticated`,principal:createJwtAuthenticatedCallerPrincipal({authenticator:`oidc`,issuerClaims:[`external_iss`,`connector_id`],payload:a.payload,principalType:`user`,subjectClaim:`external_sub`})};if(e.strategy.acceptCurrentVercelProject&&e.strategy.issuer.startsWith(`https://oidc.vercel.com/`)&&a.payload.user_id!==void 0){if(typeof a.payload.user_id!=`string`||a.payload.user_id.length===0||a.payload.environment!==`development`||!currentVercelProjectMatches({payload:a.payload,strategy:e.strategy}))return{kind:`caller-not-allowed`};if(currentVercelEnvironmentMatches({payload:a.payload,strategy:e.strategy}))return{kind:`authenticated`,principal:createJwtAuthenticatedCallerPrincipal({authenticator:`oidc`,payload:a.payload,principalType:`user`,subjectClaim:`user_id`})}}if(typeof a.payload.sub!=`string`||a.payload.sub.length===0)return{kind:`not-authenticated`};let o=e.strategy.acceptCurrentVercelProject&&isCurrentVercelProjectToken({issuer:e.strategy.issuer,payload:a.payload,strategy:e.strategy}),s=o&&isCurrentVercelEnvironmentToken({payload:a.payload,strategy:e.strategy});return!o&&!areTokenClaimMatchersSatisfied(a.payload,e.strategy)?{kind:`caller-not-allowed`}:{kind:`authenticated`,principal:createJwtAuthenticatedCallerPrincipal({authenticator:`oidc`,payload:a.payload,principalType:s?`runtime`:`service`})}}catch{return{kind:`not-authenticated`}}}async function getOidcRemoteJwks(e){let n=await getOidcDiscoveryDocument(e.discoveryUrl),r=oidcJwksCache.get(n.jwks_uri);if(r!==void 0)return r;let i=createRemoteJWKSet(new URL(n.jwks_uri));return oidcJwksCache.set(n.jwks_uri,i),i}async function getOidcDiscoveryDocument(e){let t=oidcDiscoveryDocumentCache.get(e);if(t!==void 0)return await t;let n=fetch(e,{headers:{accept:`application/json`}}).then(async e=>{if(!e.ok)throw Error(`Discovery route returned HTTP ${e.status}.`);return oidcDiscoveryDocumentSchema.parse(await e.json())}).catch(t=>{throw oidcDiscoveryDocumentCache.delete(e),t});return oidcDiscoveryDocumentCache.set(e,n),await n}function isCurrentVercelProjectToken(e){if(!e.issuer.startsWith(`https://oidc.vercel.com`))return!1;let t=e.strategy.currentVercelProject;return t===void 0?!1:typeof e.payload.project_id==`string`&&e.payload.project_id===t.projectId}function currentVercelProjectMatches(e){let t=e.strategy.currentVercelProject;return t===void 0?!1:typeof e.payload.project_id==`string`&&e.payload.project_id===t.projectId}function isCurrentVercelEnvironmentToken(e){let t=e.strategy.currentVercelProject?.environment;return t===void 0||t.length===0?!1:typeof e.payload.environment==`string`&&e.payload.environment===t}function currentVercelEnvironmentMatches(e){let t=e.strategy.currentVercelProject?.environment;return t===void 0||t.length===0?!1:typeof e.payload.environment==`string`&&e.payload.environment===t}export{authenticateOidcStrategy};
@@ -10,14 +10,18 @@ export interface LinkProjectDeps {
10
10
  unresolvedProject: typeof unresolvedProject;
11
11
  }
12
12
  export interface LinkProjectOptions {
13
- /** Streams link progress and command output. The box never prompts through it. */
13
+ /** Streams link progress and, in interactive runs, may confirm ambiguous framework detection. */
14
14
  prompter: Prompter;
15
+ /** Headless runs must not ask follow-up questions after the plan is fixed. */
16
+ headless?: boolean;
15
17
  deps?: LinkProjectDeps;
16
18
  }
17
19
  /**
18
20
  * Executes the resolved Vercel project plan after scaffolding, once the project
19
- * directory exists. Gather prompts for nothing every decision was made in the
20
- * resolve-provisioning box.
21
+ * directory exists. Gather prompts for nothing: the team/project decision was
22
+ * made in the resolve-provisioning box. Interactive runs may still confirm
23
+ * ambiguous host framework detections; headless runs resolve those
24
+ * deterministically inside `linkProject`.
21
25
  *
22
26
  * The plan is authoritative: the box always re-links to the planned project so
23
27
  * a stale or mismatched `.vercel` link can't silently win. Re-linking the same
@@ -1 +1 @@
1
- import{detectProjectResolution,mergeProjectResolution}from"../project-resolution.js";import{requireProjectPath}from"../state.js";import{linkProject,unresolvedProject}from"../vercel-project.js";import{createPromptCommandOutput}from"#setup/cli/index.js";function linkVercelProject(a){let o=a.deps??{linkProject,detectProjectResolution,unresolvedProject};return{id:`link-project`,shouldRun(e){return e.vercelProject.kind!==`none`},async gather(){return null},async perform({state:e,signal:t}){let r=e.vercelProject;if(r.kind===`none`)return o.unresolvedProject();let i=requireProjectPath(e),s=createPromptCommandOutput(a.prompter.log),c=await o.linkProject(a.prompter,i,r,s,{signal:t});if(t?.throwIfAborted(),!c)throw Error("Vercel project provisioning did not complete. Run `vercel link` manually, or re-run and choose not to deploy to Vercel.");let l=await o.detectProjectResolution(i,{signal:t});if(l.kind===`unresolved`)throw Error(`Linked the directory, but could not resolve the Vercel project from its link metadata.`);if(l.projectId!==c.projectId)throw Error(`The linked project does not match the selected project: expected ${c.projectId}, found ${l.projectId}.`);return l},apply(e,n){return{...e,project:mergeProjectResolution(e.project,n)}}}}export{linkVercelProject};
1
+ import{detectProjectResolution,mergeProjectResolution}from"../project-resolution.js";import{requireProjectPath}from"../state.js";import{linkProject,unresolvedProject}from"../vercel-project.js";import{createPromptCommandOutput}from"#setup/cli/index.js";function linkVercelProject(a){let o=a.deps??{linkProject,detectProjectResolution,unresolvedProject};return{id:`link-project`,shouldRun(e){return e.vercelProject.kind!==`none`},async gather(){return null},async perform({state:e,signal:t}){let r=e.vercelProject;if(r.kind===`none`)return o.unresolvedProject();let i=requireProjectPath(e),s=createPromptCommandOutput(a.prompter.log),c=await o.linkProject(a.prompter,i,r,s,a.headless?{signal:t,headless:!0}:{signal:t});if(t?.throwIfAborted(),!c)throw Error("Vercel project provisioning did not complete. Run `vercel link` manually, or re-run and choose not to deploy to Vercel.");let l=await o.detectProjectResolution(i,{signal:t});if(l.kind===`unresolved`)throw Error(`Linked the directory, but could not resolve the Vercel project from its link metadata.`);if(l.projectId!==c.projectId)throw Error(`The linked project does not match the selected project: expected ${c.projectId}, found ${l.projectId}.`);return l},apply(e,n){return{...e,project:mergeProjectResolution(e.project,n)}}}}export{linkVercelProject};
@@ -1 +1 @@
1
- import{headlessAsker,interactiveAsker}from"./ask.js";import{addChannels}from"./boxes/add-channels.js";import{selectConnections}from"./boxes/select-connections.js";import{addConnections}from"./boxes/add-connections.js";import{detectAiGateway}from"./boxes/detect-ai-gateway.js";import{applyAiGatewayCredential}from"./boxes/apply-ai-gateway-credential.js";import{deployProject}from"./boxes/deploy-project.js";import{linkVercelProject}from"./boxes/link-project.js";import{oneShotNextSteps}from"./boxes/one-shot-next-steps.js";import{preflight}from"./boxes/preflight.js";import{resolveProvisioning}from"./boxes/resolve-provisioning.js";import{resolveTarget}from"./boxes/resolve-target.js";import{scaffold}from"./boxes/scaffold.js";import{selectChannels}from"./boxes/select-channels.js";import{selectChat}from"./boxes/select-chat.js";import{selectModel}from"./boxes/select-model.js";import{selectSetupMode}from"./boxes/select-setup-mode.js";import{resolve}from"node:path";function onlyWhen(e,t){return{...t,shouldRun:n=>e(n)&&(t.shouldRun?.(n)??!0)}}function completeSetupOnly(e){return onlyWhen(e=>e.setupMode===`complete`,e)}function composeOnboardingBoxes(r){let i=r.headless?{headless:!0,project:r.provisioning?.project??{},aiGateway:r.provisioning?.aiGateway??{}}:{headless:!1},a=r.headless?headlessAsker():interactiveAsker(r.prompter);return[resolveTarget({asker:a,notify:e=>r.prompter.note(e),presetName:r.presetName,targetDirectory:r.targetDirectory,inPlace:r.inPlace,resumeExisting:r.headless}),selectSetupMode({asker:a,presetMode:r.presetMode,presetModel:r.presetModel}),...[selectModel({asker:a,presetModel:r.presetModel}),selectChannels({asker:a,presetChannels:r.presetChannels,variant:`onboarding`}),selectConnections({asker:a,presetConnections:r.presetConnections,headless:r.headless}),resolveProvisioning({asker:a,prompter:r.prompter,targetDirectory:r.targetDirectory,mode:i})].map(completeSetupOnly),preflight({cwd:resolve(r.targetDirectory??process.cwd()),headless:r.headless}),scaffold({prompter:r.prompter,evePackage:r.evePackage,targetDirectory:r.targetDirectory,overwriteExisting:r.overwriteExisting,headless:r.headless}),...[detectAiGateway(),linkVercelProject({prompter:r.prompter}),applyAiGatewayCredential({prompter:r.prompter}),addChannels({asker:a,prompter:r.prompter,evePackage:r.evePackage,presetCreateSlackbot:r.presetCreateSlackbot,headless:r.headless,slackbotFailure:`warn-and-continue`}),addConnections({prompter:r.prompter})].map(completeSetupOnly),completeSetupOnly(onlyWhen(e=>e.slackScaffolded,deployProject({prompter:r.prompter,skip:r.presetNoDeploy,headless:r.headless}))),completeSetupOnly(selectChat({asker:a,presetPreference:r.presetChatPreference})),oneShotNextSteps({prompter:r.prompter})]}export{composeOnboardingBoxes};
1
+ import{headlessAsker,interactiveAsker}from"./ask.js";import{addChannels}from"./boxes/add-channels.js";import{selectConnections}from"./boxes/select-connections.js";import{addConnections}from"./boxes/add-connections.js";import{detectAiGateway}from"./boxes/detect-ai-gateway.js";import{applyAiGatewayCredential}from"./boxes/apply-ai-gateway-credential.js";import{deployProject}from"./boxes/deploy-project.js";import{linkVercelProject}from"./boxes/link-project.js";import{oneShotNextSteps}from"./boxes/one-shot-next-steps.js";import{preflight}from"./boxes/preflight.js";import{resolveProvisioning}from"./boxes/resolve-provisioning.js";import{resolveTarget}from"./boxes/resolve-target.js";import{scaffold}from"./boxes/scaffold.js";import{selectChannels}from"./boxes/select-channels.js";import{selectChat}from"./boxes/select-chat.js";import{selectModel}from"./boxes/select-model.js";import{selectSetupMode}from"./boxes/select-setup-mode.js";import{resolve}from"node:path";function onlyWhen(e,t){return{...t,shouldRun:n=>e(n)&&(t.shouldRun?.(n)??!0)}}function completeSetupOnly(e){return onlyWhen(e=>e.setupMode===`complete`,e)}function composeOnboardingBoxes(r){let i=r.headless?{headless:!0,project:r.provisioning?.project??{},aiGateway:r.provisioning?.aiGateway??{}}:{headless:!1},a=r.headless?headlessAsker():interactiveAsker(r.prompter);return[resolveTarget({asker:a,notify:e=>r.prompter.note(e),presetName:r.presetName,targetDirectory:r.targetDirectory,inPlace:r.inPlace,resumeExisting:r.headless}),selectSetupMode({asker:a,presetMode:r.presetMode,presetModel:r.presetModel}),...[selectModel({asker:a,presetModel:r.presetModel}),selectChannels({asker:a,presetChannels:r.presetChannels,variant:`onboarding`}),selectConnections({asker:a,presetConnections:r.presetConnections,headless:r.headless}),resolveProvisioning({asker:a,prompter:r.prompter,targetDirectory:r.targetDirectory,mode:i})].map(completeSetupOnly),preflight({cwd:resolve(r.targetDirectory??process.cwd()),headless:r.headless}),scaffold({prompter:r.prompter,evePackage:r.evePackage,targetDirectory:r.targetDirectory,overwriteExisting:r.overwriteExisting,headless:r.headless}),...[detectAiGateway(),linkVercelProject({prompter:r.prompter,headless:r.headless}),applyAiGatewayCredential({prompter:r.prompter}),addChannels({asker:a,prompter:r.prompter,evePackage:r.evePackage,presetCreateSlackbot:r.presetCreateSlackbot,headless:r.headless,slackbotFailure:`warn-and-continue`}),addConnections({prompter:r.prompter})].map(completeSetupOnly),completeSetupOnly(onlyWhen(e=>e.slackScaffolded,deployProject({prompter:r.prompter,skip:r.presetNoDeploy,headless:r.headless}))),completeSetupOnly(selectChat({asker:a,presetPreference:r.presetChatPreference})),oneShotNextSteps({prompter:r.prompter})]}export{composeOnboardingBoxes};
@@ -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.17.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";
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.18.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";
2
2
 
3
3
  export default defineAgent({
4
4
  model: "__EVE_INIT_MODEL__",
@@ -0,0 +1,10 @@
1
+ import { createPromptCommandOutput } from "#setup/cli/index.js";
2
+ import type { Prompter } from "./prompter.js";
3
+ import { type VercelProjectOperationOptions } from "./vercel-project-api.js";
4
+ export interface CreatedProjectFrameworkOptions extends VercelProjectOperationOptions {
5
+ /** Detects whether project sources already use the eve integration for a host framework. */
6
+ detectFrameworkIntegrationImport?: (projectRoot: string, importSpecifier: string) => Promise<boolean>;
7
+ /** Never prompt; ambiguous host framework detections fall back to the eve preset. */
8
+ headless?: boolean;
9
+ }
10
+ export declare function ensureCreatedProjectFramework(prompter: Prompter, projectRoot: string, team: string, projectId: string, onOutput: ReturnType<typeof createPromptCommandOutput>, options: CreatedProjectFrameworkOptions): Promise<void>;
@@ -0,0 +1 @@
1
+ import{object,string}from"../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/classic/schemas.js";import"../node_modules/.pnpm/zod@4.4.3/node_modules/zod/index.js";import{isForbiddenApiFailure,normalizeVercelApiResult}from"./vercel-api-failure.js";import{VERCEL_PROJECT_REQUEST_TIMEOUT_MS,parseVercelJson,requireVercelTeamAccess}from"./vercel-project-api.js";import{extname,join}from"node:path";import*as fs from"node:fs/promises";import{captureVercel}from"#setup/primitives/index.js";import"#setup/cli/index.js";const VercelProjectFrameworkSchema=object({framework:string().min(1).nullish()}),EVE_FRAMEWORK_INTEGRATIONS={nextjs:{label:`Next.js`,importSpecifier:`eve/next`},nuxt:{label:`Nuxt`,importSpecifier:`eve/nuxt`},nuxtjs:{label:`Nuxt`,importSpecifier:`eve/nuxt`},sveltekit:{label:`SvelteKit`,importSpecifier:`eve/sveltekit`}},FRAMEWORK_INTEGRATION_SOURCE_EXTENSIONS=new Set([`.cjs`,`.cts`,`.js`,`.json`,`.jsx`,`.mjs`,`.mts`,`.svelte`,`.ts`,`.tsx`,`.vue`]),FRAMEWORK_INTEGRATION_IGNORED_DIRECTORIES=new Set([`.eve`,`.git`,`.next`,`.nuxt`,`.output`,`.svelte-kit`,`.turbo`,`.vercel`,`build`,`coverage`,`dist`,`node_modules`]);function parseProjectFramework(e,t){let n=VercelProjectFrameworkSchema.safeParse(parseVercelJson(e,t));if(!n.success)throw Error(`Could not read Vercel project framework from ${t}.`);return n.data.framework??void 0}async function fetchProjectFramework(e,t,a,s){let c=normalizeVercelApiResult(await captureVercel([`api`,`/v9/projects/${a}`,`--scope`,t,`--raw`],{cwd:e,signal:s.signal,timeoutMs:VERCEL_PROJECT_REQUEST_TIMEOUT_MS}));if(c.ok)return parseProjectFramework(c.stdout,`project ${a}`);throw isForbiddenApiFailure(c.failure)&&requireVercelTeamAccess(c.failure),Error(`Could not inspect Vercel project "${a}". ${c.failure.message}`)}async function setProjectFramework(e,t,a,s,c,l){let u=normalizeVercelApiResult(await captureVercel([`api`,`/v9/projects/${a}`,`--scope`,t,`--method`,`PATCH`,`--raw-field`,`framework=${s}`,`--raw`],{cwd:e,onOutput:c,signal:l.signal,timeoutMs:VERCEL_PROJECT_REQUEST_TIMEOUT_MS}));if(!u.ok)throw isForbiddenApiFailure(u.failure)&&requireVercelTeamAccess(u.failure),Error(`Could not set Vercel project "${a}" framework to ${s}. ${u.failure.message}`)}async function confirmDetectedFramework(e,t,n){return await e.select({message:`Vercel detected ${n.label}. Is this project using ${n.importSpecifier}?`,options:[{value:!0,label:`Yes, keep ${t}`,hint:`Use this for a host app that integrates eve through ${n.importSpecifier}.`},{value:!1,label:`No, switch to eve`,hint:`Use this for a standalone eve agent.`}]})?`keep`:`switch-to-eve`}function sourceMentionsPackageSpecifier(e,t){return e.includes(`"${t}"`)||e.includes(`'${t}'`)||e.includes(`\`${t}\``)}async function directoryContainsPackageSpecifier(e,t){let n;try{n=await fs.readdir(e,{encoding:`utf8`,withFileTypes:!0})}catch{return!1}for(let r of n){let n=join(e,r.name);if(r.isDirectory()){if(FRAMEWORK_INTEGRATION_IGNORED_DIRECTORIES.has(r.name))continue;if(await directoryContainsPackageSpecifier(n,t))return!0;continue}if(!(!r.isFile()||!FRAMEWORK_INTEGRATION_SOURCE_EXTENSIONS.has(extname(r.name))))try{if(sourceMentionsPackageSpecifier(await fs.readFile(n,`utf8`),t))return!0}catch{continue}}return!1}async function detectFrameworkIntegrationImport(e,t){return directoryContainsPackageSpecifier(e,t)}async function resolveDetectedFrameworkAction(e,t,n,r){let i=EVE_FRAMEWORK_INTEGRATIONS[n];return i===void 0?`switch-to-eve`:await(r.detectFrameworkIntegrationImport??detectFrameworkIntegrationImport)(t,i.importSpecifier)?`keep`:r.headless?`switch-to-eve`:confirmDetectedFramework(e,n,i)}async function ensureCreatedProjectFramework(e,t,n,r,i,a){let o=await fetchProjectFramework(t,n,r,a);o!==`eve`&&(o===void 0?`switch-to-eve`:await resolveDetectedFrameworkAction(e,t,o,a))===`switch-to-eve`&&await setProjectFramework(t,n,r,`eve`,i,a)}export{ensureCreatedProjectFramework};
@@ -4,6 +4,7 @@ import { type ProjectResolution } from "./project-resolution.js";
4
4
  import type { Prompter } from "./prompter.js";
5
5
  import type { ResolvedVercelProjectSpec, VercelProjectIdentity } from "./state.js";
6
6
  import { type VercelProjectOperationOptions } from "./vercel-project-api.js";
7
+ import { type CreatedProjectFrameworkOptions } from "./vercel-project-framework.js";
7
8
  export interface PickProjectOptions extends VercelProjectOperationOptions {
8
9
  /** Whether an empty project list may fall back to entering a name to create. */
9
10
  allowCreateWhenEmpty?: boolean;
@@ -12,6 +13,8 @@ export interface PickTeamOptions extends VercelProjectOperationOptions {
12
13
  /** Builds the team selector heading from the current team's display name. */
13
14
  selectMessage?: (currentTeam: string) => string;
14
15
  }
16
+ export interface LinkProjectOperationOptions extends CreatedProjectFrameworkOptions {
17
+ }
15
18
  export declare function unresolvedProject(): ProjectResolution;
16
19
  /** Resolves the linked project id from a resolution, if any. */
17
20
  export declare function projectIdFromResolution(project: ProjectResolution): string | undefined;
@@ -86,7 +89,9 @@ export declare function pickNewProjectName(prompter: Prompter, projectRoot: stri
86
89
  /**
87
90
  * Ensures the concrete project exists (creating it for a `new` plan) and links
88
91
  * this directory to it. Acts on a fully-resolved spec — never prompts for a
89
- * team or project. Returns the linked project, or undefined if `vercel link`
90
- * did not complete.
92
+ * team or project. A newly created project keeps a detected host framework
93
+ * when the matching eve integration import is present; otherwise missing,
94
+ * unsupported, or rejected framework detections are switched back to eve.
95
+ * Returns the linked project, or undefined if `vercel link` did not complete.
91
96
  */
92
- export declare function linkProject(prompter: Prompter, projectRoot: string, spec: ResolvedVercelProjectSpec, onOutput: ReturnType<typeof createPromptCommandOutput>, options?: VercelProjectOperationOptions): Promise<VercelProjectIdentity | undefined>;
97
+ export declare function linkProject(prompter: Prompter, projectRoot: string, spec: ResolvedVercelProjectSpec, onOutput: ReturnType<typeof createPromptCommandOutput>, options?: LinkProjectOperationOptions): Promise<VercelProjectIdentity | undefined>;
Binary file
package/docs/sandbox.mdx CHANGED
@@ -96,7 +96,7 @@ import { defineSandbox } from "eve/sandbox";
96
96
  import { vercel } from "eve/sandbox/vercel";
97
97
 
98
98
  export default defineSandbox({
99
- backend: vercel({ runtime: "node24", resources: { vcpus: 2 } }),
99
+ backend: vercel({ resources: { vcpus: 2 } }),
100
100
  revalidationKey: () => "repo-bootstrap-v1",
101
101
  async bootstrap({ use }) {
102
102
  const sandbox = await use();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eve",
3
- "version": "0.17.2",
3
+ "version": "0.18.1",
4
4
  "private": false,
5
5
  "description": "Filesystem-first framework for durable backend AI agents that run anywhere.",
6
6
  "keywords": [
@@ -285,7 +285,7 @@
285
285
  "@types/react-test-renderer": "19.1.0",
286
286
  "@vercel/detect-agent": "1.2.3",
287
287
  "@vercel/oidc": "3.5.0",
288
- "@vercel/sandbox": "2.2.1",
288
+ "@vercel/sandbox": "2.3.0",
289
289
  "@vercel/sdk": "1.28.1",
290
290
  "@workflow/core": "5.0.0-beta.26",
291
291
  "@workflow/errors": "5.0.0-beta.8",
@@ -321,25 +321,15 @@
321
321
  },
322
322
  "peerDependencies": {
323
323
  "@opentelemetry/api": "^1.0.0",
324
- "@sveltejs/kit": "^2.0.0",
325
324
  "ai": "^7.0.0",
326
325
  "braintrust": "^3.0.0",
327
326
  "just-bash": "^3.0.0",
328
- "microsandbox": "^0.5.0",
329
- "next": "^16.0.0",
330
- "nuxt": "^4.0.0",
331
- "react": "^19.0.0",
332
- "svelte": "^5.0.0",
333
- "vite": "^8.0.0",
334
- "vue": "^3.5.0"
327
+ "microsandbox": "^0.5.0"
335
328
  },
336
329
  "peerDependenciesMeta": {
337
330
  "@opentelemetry/api": {
338
331
  "optional": true
339
332
  },
340
- "@sveltejs/kit": {
341
- "optional": true
342
- },
343
333
  "braintrust": {
344
334
  "optional": true
345
335
  },
@@ -348,24 +338,6 @@
348
338
  },
349
339
  "microsandbox": {
350
340
  "optional": true
351
- },
352
- "next": {
353
- "optional": true
354
- },
355
- "nuxt": {
356
- "optional": true
357
- },
358
- "react": {
359
- "optional": true
360
- },
361
- "svelte": {
362
- "optional": true
363
- },
364
- "vite": {
365
- "optional": true
366
- },
367
- "vue": {
368
- "optional": true
369
341
  }
370
342
  },
371
343
  "engines": {