eve 0.15.5 → 0.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (107) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/dist/src/cli/commands/init.js +1 -1
  3. package/dist/src/cli/dev/tui/agent-header.js +1 -1
  4. package/dist/src/cli/dev/tui/blocks.js +8 -8
  5. package/dist/src/cli/dev/tui/prompt-command-handler.js +1 -1
  6. package/dist/src/cli/dev/tui/prompt-commands.d.ts +1 -1
  7. package/dist/src/cli/dev/tui/prompt-commands.js +1 -1
  8. package/dist/src/cli/dev/tui/runner.d.ts +10 -3
  9. package/dist/src/cli/dev/tui/runner.js +1 -1
  10. package/dist/src/cli/dev/tui/setup-commands.d.ts +9 -1
  11. package/dist/src/cli/dev/tui/setup-commands.js +2 -2
  12. package/dist/src/cli/dev/tui/setup-flow.d.ts +8 -1
  13. package/dist/src/cli/dev/tui/setup-issues.d.ts +2 -14
  14. package/dist/src/cli/dev/tui/setup-issues.js +1 -1
  15. package/dist/src/cli/dev/tui/setup-panel.d.ts +14 -8
  16. package/dist/src/cli/dev/tui/setup-panel.js +3 -3
  17. package/dist/src/cli/dev/tui/terminal-renderer.js +6 -6
  18. package/dist/src/cli/dev/tui/tui-prompter.js +1 -1
  19. package/dist/src/cli/dev/tui/tui.d.ts +2 -3
  20. package/dist/src/cli/dev/tui/tui.js +1 -1
  21. package/dist/src/cli/dev/ui-options.d.ts +21 -0
  22. package/dist/src/cli/dev/ui-options.js +1 -0
  23. package/dist/src/cli/run.d.ts +6 -42
  24. package/dist/src/cli/run.js +2 -2
  25. package/dist/src/compiled/.vendor-stamp.json +1 -1
  26. package/dist/src/compiled/@ai-sdk/mcp/index.d.ts +71 -1
  27. package/dist/src/compiled/@ai-sdk/mcp/index.js +1 -1
  28. package/dist/src/harness/emission.d.ts +3 -3
  29. package/dist/src/harness/emission.js +1 -1
  30. package/dist/src/harness/stream-actions.d.ts +17 -0
  31. package/dist/src/harness/stream-actions.js +1 -0
  32. package/dist/src/internal/application/package.js +1 -1
  33. package/dist/src/internal/nitro/host/configure-nitro-routes.js +2 -2
  34. package/dist/src/internal/nitro/host/dev-authored-source-watcher.d.ts +1 -0
  35. package/dist/src/internal/nitro/host/dev-authored-source-watcher.js +1 -1
  36. package/dist/src/internal/nitro/host/start-development-server.d.ts +8 -0
  37. package/dist/src/internal/nitro/host/start-development-server.js +2 -2
  38. package/dist/src/internal/nitro/host.d.ts +1 -1
  39. package/dist/src/internal/nitro/host.js +1 -1
  40. package/dist/src/internal/nitro/routes/channel-dispatch.js +1 -1
  41. package/dist/src/internal/nitro/routes/dev-runtime-artifacts.d.ts +0 -3
  42. package/dist/src/internal/nitro/routes/dev-runtime-artifacts.js +1 -1
  43. package/dist/src/internal/nitro/routes/info.js +1 -1
  44. package/dist/src/internal/vercel/project-link.d.ts +10 -0
  45. package/dist/src/internal/vercel/project-link.js +1 -0
  46. package/dist/src/public/channels/auth.d.ts +26 -13
  47. package/dist/src/public/channels/auth.js +1 -1
  48. package/dist/src/runtime/agent/mock-model-adapter.d.ts +3 -2
  49. package/dist/src/runtime/agent/mock-model-adapter.js +1 -1
  50. package/dist/src/runtime/connections/principal.d.ts +2 -0
  51. package/dist/src/runtime/connections/principal.js +1 -1
  52. package/dist/src/runtime/connections/types.d.ts +4 -1
  53. package/dist/src/runtime/framework-channels/index.d.ts +1 -6
  54. package/dist/src/runtime/framework-channels/index.js +1 -1
  55. package/dist/src/runtime/governance/auth/oidc.js +1 -1
  56. package/dist/src/runtime/governance/auth/types.d.ts +14 -10
  57. package/dist/src/runtime/governance/auth/vercel-oidc-project.d.ts +12 -0
  58. package/dist/src/runtime/governance/auth/vercel-oidc-project.js +1 -0
  59. package/dist/src/services/dev-client/client-options.d.ts +5 -0
  60. package/dist/src/services/dev-client/client-options.js +1 -1
  61. package/dist/src/services/dev-client/request-headers.d.ts +8 -0
  62. package/dist/src/services/dev-client/request-headers.js +1 -1
  63. package/dist/src/services/dev-client/runtime-artifacts.d.ts +1 -0
  64. package/dist/src/services/dev-client/runtime-artifacts.js +1 -1
  65. package/dist/src/services/dev-client.d.ts +8 -0
  66. package/dist/src/services/dev-client.js +1 -1
  67. package/dist/src/setup/boxes/add-connections.d.ts +10 -8
  68. package/dist/src/setup/boxes/add-connections.js +1 -1
  69. package/dist/src/setup/boxes/resolve-provisioning.d.ts +1 -0
  70. package/dist/src/setup/boxes/resolve-provisioning.js +1 -1
  71. package/dist/src/setup/cli/channel-setup-prompter.d.ts +9 -2
  72. package/dist/src/setup/cli/channel-setup-prompter.js +1 -1
  73. package/dist/src/setup/cli/index.d.ts +1 -1
  74. package/dist/src/setup/cli/prompt-ui.d.ts +2 -0
  75. package/dist/src/setup/cli/select-state.js +1 -1
  76. package/dist/src/setup/connection-connector.d.ts +26 -52
  77. package/dist/src/setup/connection-connector.js +2 -1
  78. package/dist/src/setup/flows/channels.js +1 -1
  79. package/dist/src/setup/flows/connections.d.ts +36 -0
  80. package/dist/src/setup/flows/connections.js +3 -0
  81. package/dist/src/setup/flows/link.d.ts +1 -0
  82. package/dist/src/setup/flows/link.js +1 -1
  83. package/dist/src/setup/project-resolution.d.ts +2 -8
  84. package/dist/src/setup/project-resolution.js +1 -1
  85. package/dist/src/setup/prompter.d.ts +2 -0
  86. package/dist/src/setup/scaffold/connections/catalog.d.ts +10 -5
  87. package/dist/src/setup/scaffold/connections/catalog.js +1 -1
  88. package/dist/src/setup/scaffold/create/project.js +11 -11
  89. package/dist/src/setup/scaffold/create/web-template.d.ts +1 -1
  90. package/dist/src/setup/scaffold/create/web-template.js +2 -2
  91. package/dist/src/setup/scaffold/index.d.ts +1 -1
  92. package/dist/src/setup/scaffold/index.js +1 -1
  93. package/dist/src/setup/scaffold/update/connections.d.ts +6 -0
  94. package/dist/src/setup/scaffold/update/connections.js +3 -3
  95. package/docs/channels/eve.mdx +3 -3
  96. package/docs/concepts/sessions-runs-and-streaming.md +1 -1
  97. package/docs/guides/auth-and-route-protection.md +5 -5
  98. package/docs/guides/dev-tui.md +11 -4
  99. package/docs/guides/frontend/nextjs.mdx +2 -2
  100. package/docs/guides/frontend/nuxt.mdx +2 -2
  101. package/docs/guides/frontend/sveltekit.mdx +2 -2
  102. package/docs/reference/cli.md +3 -1
  103. package/docs/tutorial/ship-it.mdx +1 -1
  104. package/docs/tutorial/team-playbooks.mdx +1 -1
  105. package/package.json +2 -2
  106. package/dist/src/internal/nitro/host/dev-rebuild-registry.d.ts +0 -5
  107. package/dist/src/internal/nitro/host/dev-rebuild-registry.js +0 -1
@@ -1 +1 @@
1
- import{createLogger}from"#internal/logging.js";import{decodeJwt}from"#compiled/jose/index.js";import{authenticateHttpBasicStrategy}from"#runtime/governance/auth/http-basic.js";import{authenticateJwtEcdsaStrategy}from"#runtime/governance/auth/jwt-ecdsa.js";import{authenticateJwtHmacStrategy}from"#runtime/governance/auth/jwt-hmac.js";import{authenticateOidcStrategy}from"#runtime/governance/auth/oidc.js";import{createRuntimeSessionAuthContext}from"#runtime/governance/auth/types.js";import{createRuntimeIpAllowList,isRuntimeIpAllowed}from"#runtime/governance/network/ip-allow-list.js";const vercelOidcLog=createLogger(`auth.vercel-oidc`);function verifyHttpBasic(e,t){if(e===null)return{ok:!1};let r=authenticateHttpBasicStrategy({authorization:e,strategy:{kind:`http-basic`,password:t.password,username:t.username}});return r.kind===`authenticated`?{ok:!0,sessionAuth:createRuntimeSessionAuthContext(r.principal)}:{ok:!1}}async function verifyJwtHmac(e,t){if(e===null||e.length===0)return{ok:!1};let n=await authenticateJwtHmacStrategy({strategy:{algorithm:t.algorithm,audiences:[...t.audiences],clockSkewSeconds:t.clockSkewSeconds??30,issuer:t.issuer,kind:`jwt-hmac`,secret:t.secret,...t.claims===void 0?{}:{claims:t.claims},...t.subjects===void 0?{}:{subjects:t.subjects}},token:e});return n.kind===`authenticated`?{ok:!0,sessionAuth:createRuntimeSessionAuthContext(n.principal)}:{ok:!1}}async function verifyJwtEcdsa(e,t){if(e===null||e.length===0)return{ok:!1};let n=await authenticateJwtEcdsaStrategy({strategy:{algorithm:t.algorithm,audiences:[...t.audiences],clockSkewSeconds:t.clockSkewSeconds??30,issuer:t.issuer,kind:`jwt-ecdsa`,publicKey:t.publicKey,...t.claims===void 0?{}:{claims:t.claims},...t.subjects===void 0?{}:{subjects:t.subjects}},token:e});return n.kind===`authenticated`?{ok:!0,sessionAuth:createRuntimeSessionAuthContext(n.principal)}:{ok:!1}}async function verifyOidc(e,t){let n=await runOidcVerification(e,{...t,acceptCurrentVercelProject:!1});return n.kind===`authenticated`?{ok:!0,sessionAuth:createRuntimeSessionAuthContext(n.principal)}:{ok:!1}}async function runOidcVerification(e,t){return e===null||e.length===0?{kind:`not-authenticated`}:await authenticateOidcStrategy({strategy:{acceptCurrentVercelProject:t.acceptCurrentVercelProject,audiences:[...t.audiences],clockSkewSeconds:t.clockSkewSeconds??30,discoveryUrl:t.discoveryUrl??`${t.issuer.replace(/\/$/,``)}/.well-known/openid-configuration`,issuer:t.issuer,kind:`oidc`,...t.claims===void 0?{}:{claims:t.claims},...t.subjects===void 0?{}:{subjects:t.subjects}},token:e})}function extractBearerToken(e){if(e===null)return null;let t=/^Bearer\s+(.+)$/i.exec(e)?.[1]?.trim();return t===void 0||t.length===0?null:t}function createIpAllowList(e){return createRuntimeIpAllowList(e)}function isIpAllowed(e,t){return e===null?!1:isRuntimeIpAllowed(e,t)}function createUnauthorizedResponse(e={}){let t=e.status??401,n=e.code??(t===403?`forbidden`:`unauthorized`),r=e.message??(t===403?`Forbidden.`:`Authorization is required for this route.`),i=e.challenges??[],a=new Headers({"cache-control":`no-store`});for(let e of i)a.append(`www-authenticate`,formatChallenge(e));return Response.json({code:n,error:r,ok:!1},{headers:a,status:t})}function formatChallenge(e){if(e.parameters===void 0||Object.keys(e.parameters).length===0)return e.scheme;let t=Object.entries(e.parameters).map(([e,t])=>`${e}="${escapeChallengeValue(t)}"`).join(`, `);return`${e.scheme} ${t}`}function escapeChallengeValue(e){return e.replaceAll(`\\`,`\\\\`).replaceAll(`"`,`\\"`)}var UnauthenticatedError=class extends Error{response;constructor(e={}){super(e.message??`Authorization is required for this route.`),this.name=`UnauthenticatedError`,this.response=createUnauthorizedResponse({...e,status:401})}},ForbiddenError=class extends Error{response;constructor(e={}){super(e.message??`Forbidden.`),this.name=`ForbiddenError`,this.response=createUnauthorizedResponse({...e,status:403})}};async function routeAuth(e,t){let n=Array.isArray(t)?t:[t];try{for(let t of n){let n=await t(e);if(n)return n}}catch(e){if(typeof e==`object`&&e&&`response`in e&&e.response instanceof Response)return e.response;throw e}return createUnauthorizedResponse({challenges:[{scheme:`Bearer`}]})}function placeholderAuth(){return()=>{if(process.env.VERCEL_ENV!==`production`)return null;throw new UnauthenticatedError({code:`eve_production_auth_not_configured`,message:`Production auth is not configured. Replace placeholderAuth() in agent/channels/eve.ts with your app's auth provider.`})}}function none(){return()=>ANONYMOUS_SESSION_AUTH_CONTEXT}function localDev(){return e=>process.env.VERCEL&&process.env.VERCEL_ENV===`development`||isLoopbackRequest(e)?LOCAL_DEV_SESSION_AUTH_CONTEXT:null}const LOOPBACK_HOSTNAMES=new Set([`localhost`,`[::1]`]),LOOPBACK_IPV4_PREFIX=/^127\./;function isLoopbackRequest(e){let t;try{t=new URL(e.url).hostname}catch{return!1}return!!(LOOPBACK_HOSTNAMES.has(t)||LOOPBACK_IPV4_PREFIX.test(t)||t.endsWith(`.localhost`))}const ANONYMOUS_SESSION_AUTH_CONTEXT={attributes:{},authenticator:`none`,principalId:`anonymous`,principalType:`anonymous`},LOCAL_DEV_SESSION_AUTH_CONTEXT={attributes:{},authenticator:`local-dev`,principalId:`local-dev`,principalType:`local-dev`};async function verifyVercelOidc(e,t={}){if(e===null||e.length===0)return{ok:!1};let n=decodeUnverifiedJwtClaims(e);if(n===null)return vercelOidcLog.debug(`Rejected token that failed to decode as a JWT.`),{ok:!1};if(!n.issuer.startsWith(`https://oidc.vercel.com/`))return vercelOidcLog.debug(`Rejected token whose issuer is not a Vercel OIDC issuer.`,{issuer:n.issuer}),{ok:!1};if(n.audiences.length===0)return vercelOidcLog.debug(`Rejected token with no audience claim.`,{issuer:n.issuer}),{ok:!1};if(!n.audiences.some(e=>e.startsWith(`https://vercel.com/`)))return vercelOidcLog.debug(`Rejected token whose audience is not a Vercel audience.`,{audiences:n.audiences,issuer:n.issuer}),{ok:!1};let r=await runOidcVerification(e,{acceptCurrentVercelProject:!0,audiences:n.audiences,issuer:n.issuer,subjects:t.subjects??[]});return r.kind===`authenticated`?(vercelOidcLog.debug(`Accepted Vercel OIDC token.`,{issuer:n.issuer,principalType:r.principal.principalType,subject:r.principal.subject}),{ok:!0,sessionAuth:createRuntimeSessionAuthContext(r.principal)}):(vercelOidcLog.debug(`Rejected Vercel OIDC token after verification.`,{audiences:n.audiences,issuer:n.issuer,reason:r.kind,subjectsConfigured:(t.subjects??[]).length>0,...r.kind===`misconfigured`?{detail:r.message}:{}}),{ok:!1})}function vercelSubject(e){assertVercelSubjectSegment(`teamSlug`,e.teamSlug),assertVercelSubjectSegment(`projectName`,e.projectName);let t=e.environment??`production`;if(t!==`production`&&t!==`preview`&&t!==`development`&&t!==`*`)throw Error(`vercelSubject: invalid environment ${JSON.stringify(t)}; expected "production", "preview", "development", or "*".`);return`owner:${e.teamSlug}:project:${e.projectName}:environment:${t}`}function assertVercelSubjectSegment(e,t){if(t.length===0)throw Error(`vercelSubject: ${e} must be a non-empty string.`);if(t.includes(`*`)||t.includes(`:`))throw Error(`vercelSubject: ${e} ${JSON.stringify(t)} may not contain ${t.includes(`:`)?`':'`:`'*'`}. Hand-write the subject string when wildcards are intentional.`)}function vercelOidc(e={}){return async t=>{let n=await verifyVercelOidc(extractBearerToken(t.headers.get(`authorization`)),e);return n.ok?n.sessionAuth:null}}function httpBasic(e){return t=>{let n=verifyHttpBasic(t.headers.get(`authorization`),e);return n.ok?n.sessionAuth:null}}function jwtHmac(e){return async t=>{let n=await verifyJwtHmac(extractBearerToken(t.headers.get(`authorization`)),e);return n.ok?n.sessionAuth:null}}function jwtEcdsa(e){return async t=>{let n=await verifyJwtEcdsa(extractBearerToken(t.headers.get(`authorization`)),e);return n.ok?n.sessionAuth:null}}function oidc(e){return async t=>{let n=await verifyOidc(extractBearerToken(t.headers.get(`authorization`)),e);return n.ok?n.sessionAuth:null}}function decodeUnverifiedJwtClaims(e){let n;try{n=decodeJwt(e)}catch{return null}return typeof n.iss!=`string`||n.iss.length===0?null:{audiences:typeof n.aud==`string`?[n.aud]:Array.isArray(n.aud)?n.aud.filter(e=>typeof e==`string`):[],issuer:n.iss}}export{ForbiddenError,UnauthenticatedError,createIpAllowList,createUnauthorizedResponse,extractBearerToken,httpBasic,isIpAllowed,jwtEcdsa,jwtHmac,localDev,none,oidc,placeholderAuth,routeAuth,vercelOidc,vercelSubject,verifyHttpBasic,verifyJwtEcdsa,verifyJwtHmac,verifyOidc,verifyVercelOidc};
1
+ import{createLogger}from"#internal/logging.js";import{resolveVercelOidcCurrentProject}from"#runtime/governance/auth/vercel-oidc-project.js";import{decodeJwt}from"#compiled/jose/index.js";import{authenticateHttpBasicStrategy}from"#runtime/governance/auth/http-basic.js";import{authenticateJwtEcdsaStrategy}from"#runtime/governance/auth/jwt-ecdsa.js";import{authenticateJwtHmacStrategy}from"#runtime/governance/auth/jwt-hmac.js";import{authenticateOidcStrategy}from"#runtime/governance/auth/oidc.js";import{createRuntimeSessionAuthContext}from"#runtime/governance/auth/types.js";import{createRuntimeIpAllowList,isRuntimeIpAllowed}from"#runtime/governance/network/ip-allow-list.js";const vercelOidcLog=createLogger(`auth.vercel-oidc`);function verifyHttpBasic(e,t){if(e===null)return{ok:!1};let n=authenticateHttpBasicStrategy({authorization:e,strategy:{kind:`http-basic`,password:t.password,username:t.username}});return n.kind===`authenticated`?{ok:!0,sessionAuth:createRuntimeSessionAuthContext(n.principal)}:{ok:!1}}async function verifyJwtHmac(e,t){if(e===null||e.length===0)return{ok:!1};let n=await authenticateJwtHmacStrategy({strategy:{algorithm:t.algorithm,audiences:[...t.audiences],clockSkewSeconds:t.clockSkewSeconds??30,issuer:t.issuer,kind:`jwt-hmac`,secret:t.secret,...t.claims===void 0?{}:{claims:t.claims},...t.subjects===void 0?{}:{subjects:t.subjects}},token:e});return n.kind===`authenticated`?{ok:!0,sessionAuth:createRuntimeSessionAuthContext(n.principal)}:{ok:!1}}async function verifyJwtEcdsa(e,t){if(e===null||e.length===0)return{ok:!1};let n=await authenticateJwtEcdsaStrategy({strategy:{algorithm:t.algorithm,audiences:[...t.audiences],clockSkewSeconds:t.clockSkewSeconds??30,issuer:t.issuer,kind:`jwt-ecdsa`,publicKey:t.publicKey,...t.claims===void 0?{}:{claims:t.claims},...t.subjects===void 0?{}:{subjects:t.subjects}},token:e});return n.kind===`authenticated`?{ok:!0,sessionAuth:createRuntimeSessionAuthContext(n.principal)}:{ok:!1}}async function verifyOidc(e,t){let n=await runOidcVerification(e,{...t,acceptCurrentVercelProject:!1,currentVercelProject:void 0});return n.kind===`authenticated`?{ok:!0,sessionAuth:createRuntimeSessionAuthContext(n.principal)}:{ok:!1}}async function runOidcVerification(e,t){if(e===null||e.length===0)return{kind:`not-authenticated`};let n={acceptCurrentVercelProject:t.acceptCurrentVercelProject,audiences:[...t.audiences],clockSkewSeconds:t.clockSkewSeconds??30,discoveryUrl:t.discoveryUrl??`${t.issuer.replace(/\/$/,``)}/.well-known/openid-configuration`,issuer:t.issuer,kind:`oidc`,...t.claims===void 0?{}:{claims:t.claims},...t.subjects===void 0?{}:{subjects:t.subjects}};return await authenticateOidcStrategy({strategy:t.currentVercelProject===void 0?n:{...n,currentVercelProject:t.currentVercelProject},token:e})}function extractBearerToken(e){if(e===null)return null;let t=/^Bearer\s+(.+)$/i.exec(e)?.[1]?.trim();return t===void 0||t.length===0?null:t}function createIpAllowList(e){return createRuntimeIpAllowList(e)}function isIpAllowed(e,t){return e===null?!1:isRuntimeIpAllowed(e,t)}function createUnauthorizedResponse(e={}){let t=e.status??401,n=e.code??(t===403?`forbidden`:`unauthorized`),r=e.message??(t===403?`Forbidden.`:`Authorization is required for this route.`),i=e.challenges??[],a=new Headers({"cache-control":`no-store`});for(let e of i)a.append(`www-authenticate`,formatChallenge(e));return Response.json({code:n,error:r,ok:!1},{headers:a,status:t})}function formatChallenge(e){if(e.parameters===void 0||Object.keys(e.parameters).length===0)return e.scheme;let t=Object.entries(e.parameters).map(([e,t])=>`${e}="${escapeChallengeValue(t)}"`).join(`, `);return`${e.scheme} ${t}`}function escapeChallengeValue(e){return e.replaceAll(`\\`,`\\\\`).replaceAll(`"`,`\\"`)}var UnauthenticatedError=class extends Error{response;constructor(e={}){super(e.message??`Authorization is required for this route.`),this.name=`UnauthenticatedError`,this.response=createUnauthorizedResponse({...e,status:401})}},ForbiddenError=class extends Error{response;constructor(e={}){super(e.message??`Forbidden.`),this.name=`ForbiddenError`,this.response=createUnauthorizedResponse({...e,status:403})}};async function routeAuth(e,t){let n=Array.isArray(t)?t:[t];try{for(let t of n){let n=await t(e);if(n)return n}}catch(e){if(typeof e==`object`&&e&&`response`in e&&e.response instanceof Response)return e.response;throw e}return createUnauthorizedResponse({challenges:[{scheme:`Bearer`}]})}function placeholderAuth(){return()=>{if(process.env.VERCEL_ENV!==`production`)return null;throw new UnauthenticatedError({code:`eve_production_auth_not_configured`,message:`Production auth is not configured. Replace placeholderAuth() in agent/channels/eve.ts with your app's auth provider.`})}}function none(){return()=>ANONYMOUS_SESSION_AUTH_CONTEXT}function localDev(){return e=>process.env.VERCEL&&process.env.VERCEL_ENV===`development`||isLoopbackRequest(e)?LOCAL_DEV_SESSION_AUTH_CONTEXT:null}const LOOPBACK_HOSTNAMES=new Set([`localhost`,`[::1]`]),LOOPBACK_IPV4_PREFIX=/^127\./;function isLoopbackRequest(e){let t;try{t=new URL(e.url).hostname}catch{return!1}return!!(LOOPBACK_HOSTNAMES.has(t)||LOOPBACK_IPV4_PREFIX.test(t)||t.endsWith(`.localhost`))}const ANONYMOUS_SESSION_AUTH_CONTEXT={attributes:{},authenticator:`none`,principalId:`anonymous`,principalType:`anonymous`},LOCAL_DEV_SESSION_AUTH_CONTEXT={attributes:{},authenticator:`local-dev`,principalId:`local-dev`,principalType:`local-dev`};async function verifyVercelOidc(e,t={}){if(e===null||e.length===0)return{ok:!1};let n=decodeUnverifiedJwtClaims(e);if(n===null)return vercelOidcLog.debug(`Rejected token that failed to decode as a JWT.`),{ok:!1};if(!n.issuer.startsWith(`https://oidc.vercel.com/`))return vercelOidcLog.debug(`Rejected token whose issuer is not a Vercel OIDC issuer.`,{issuer:n.issuer}),{ok:!1};if(n.audiences.length===0)return vercelOidcLog.debug(`Rejected token with no audience claim.`,{issuer:n.issuer}),{ok:!1};if(!n.audiences.some(e=>e.startsWith(`https://vercel.com/`)))return vercelOidcLog.debug(`Rejected token whose audience is not a Vercel audience.`,{audiences:n.audiences,issuer:n.issuer}),{ok:!1};let r=resolveCurrentVercelProject(t),i=await runOidcVerification(e,{acceptCurrentVercelProject:!0,audiences:n.audiences,currentVercelProject:r,issuer:n.issuer,subjects:t.subjects??[]});return i.kind===`authenticated`?(vercelOidcLog.debug(`Accepted Vercel OIDC token.`,{issuer:n.issuer,principalType:i.principal.principalType,subject:i.principal.subject}),{ok:!0,sessionAuth:createRuntimeSessionAuthContext(i.principal)}):(vercelOidcLog.debug(`Rejected Vercel OIDC token after verification.`,{audiences:n.audiences,issuer:n.issuer,reason:i.kind,subjectsConfigured:(t.subjects??[]).length>0,...i.kind===`misconfigured`?{detail:i.message}:{}}),{ok:!1})}function resolveCurrentVercelProject(e){if(e.currentVercelProject!==void 0)return e.currentVercelProject;let t=process.env.VERCEL_PROJECT_ID?.trim();if(t===void 0||t.length===0)return;let n=process.env.VERCEL_TARGET_ENV?.trim()||process.env.VERCEL_ENV?.trim();return n===void 0||n.length===0?{projectId:t}:{environment:n,projectId:t}}function vercelSubject(e){assertVercelSubjectSegment(`teamSlug`,e.teamSlug),assertVercelSubjectSegment(`projectName`,e.projectName);let t=e.environment??`production`;if(t!==`production`&&t!==`preview`&&t!==`development`&&t!==`*`)throw Error(`vercelSubject: invalid environment ${JSON.stringify(t)}; expected "production", "preview", "development", or "*".`);return`owner:${e.teamSlug}:project:${e.projectName}:environment:${t}`}function assertVercelSubjectSegment(e,t){if(t.length===0)throw Error(`vercelSubject: ${e} must be a non-empty string.`);if(t.includes(`*`)||t.includes(`:`))throw Error(`vercelSubject: ${e} ${JSON.stringify(t)} may not contain ${t.includes(`:`)?`':'`:`'*'`}. Hand-write the subject string when wildcards are intentional.`)}function vercelOidc(e={}){return async n=>{let r=extractBearerToken(n.headers.get(`authorization`)),i=e.currentVercelProject??(r!==null&&isLocalDevelopmentVercelOidcRequest(n)?await resolveVercelOidcCurrentProject(n):void 0),a=await verifyVercelOidc(r,i===void 0?e:{...e,currentVercelProject:i});return a.ok?a.sessionAuth:null}}function isLocalDevelopmentVercelOidcRequest(e){return process.env.VERCEL_ENV===`development`?!0:process.env.VERCEL_ENV===`preview`||process.env.VERCEL_ENV===`production`?!1:isLoopbackRequest(e)}function httpBasic(e){return t=>{let n=verifyHttpBasic(t.headers.get(`authorization`),e);return n.ok?n.sessionAuth:null}}function jwtHmac(e){return async t=>{let n=await verifyJwtHmac(extractBearerToken(t.headers.get(`authorization`)),e);return n.ok?n.sessionAuth:null}}function jwtEcdsa(e){return async t=>{let n=await verifyJwtEcdsa(extractBearerToken(t.headers.get(`authorization`)),e);return n.ok?n.sessionAuth:null}}function oidc(e){return async t=>{let n=await verifyOidc(extractBearerToken(t.headers.get(`authorization`)),e);return n.ok?n.sessionAuth:null}}function decodeUnverifiedJwtClaims(e){let t;try{t=decodeJwt(e)}catch{return null}return typeof t.iss!=`string`||t.iss.length===0?null:{audiences:typeof t.aud==`string`?[t.aud]:Array.isArray(t.aud)?t.aud.filter(e=>typeof e==`string`):[],issuer:t.iss}}export{ForbiddenError,UnauthenticatedError,createIpAllowList,createUnauthorizedResponse,extractBearerToken,httpBasic,isIpAllowed,isLoopbackRequest,jwtEcdsa,jwtHmac,localDev,none,oidc,placeholderAuth,routeAuth,vercelOidc,vercelSubject,verifyHttpBasic,verifyJwtEcdsa,verifyJwtHmac,verifyOidc,verifyVercelOidc};
@@ -3,8 +3,9 @@ import { type RuntimeModelReference } from "#runtime/agent/bootstrap.js";
3
3
  /**
4
4
  * Returns true when authored runtime models should resolve through the
5
5
  * dedicated deterministic mock adapter. The adapter is internal to the test
6
- * tiers: it activates only under `NODE_ENV=test`, keeping the unit,
7
- * integration, and scenario suites deterministic and credential-free.
6
+ * tiers: unit, integration, and scenario tests activate it through
7
+ * `NODE_ENV=test`; spawned smoke servers use the explicit opt-in environment
8
+ * variable so their package-manager build keeps its normal environment.
8
9
  */
9
10
  export declare function shouldMockAuthoredRuntimeModels(): boolean;
10
11
  /**
@@ -1,4 +1,4 @@
1
- import{z}from"#compiled/zod/index.js";import{LOAD_SKILL_TOOL_NAME}from"#runtime/skills/fragment-context.js";import{MockLanguageModelV3}from"ai/test";import{FINAL_OUTPUT_TOOL_NAME}from"#runtime/framework-tools/final-output.js";import{BOOTSTRAP_RUNTIME_MODEL_ID,BOOTSTRAP_RUNTIME_SYSTEM_PROMPT}from"#runtime/agent/bootstrap.js";import{createBootstrapGenerateResult,createBootstrapStreamResult,estimateTokenCount,getLastUserPromptText,getPromptContentText,getPromptText}from"#runtime/agent/bootstrap-model-utils.js";import{createMockAuthoredToolInput,formatToolOutput,resolveMockFixtureToken,resolveWeatherCity}from"#runtime/agent/mock-model-fixtures.js";import{findRelevantSkill,getActivatedSkillIds,getAvailableSkills}from"#runtime/agent/mock-model-skill-selection.js";import{createJsonSchemaSample}from"#runtime/agent/mock-structured-output.js";const authoredRuntimeModelMocks=new Map,bootstrapWeatherPayloadSchema=z.object({city:z.string(),condition:z.string(),summary:z.string(),temperatureF:z.number().finite()}).strict();function shouldMockAuthoredRuntimeModels(){return process.env.NODE_ENV===`test`}function createMockAuthoredRuntimeModel(e){let t=authoredRuntimeModelMocks.get(e.id);if(t!==void 0)return t;let r=new MockLanguageModelV3({modelId:e.id,provider:`eve-runtime-mock`,doGenerate:async t=>createMockModelResult(t,e.id),doStream:async t=>createBootstrapStreamResult(createMockModelResult(t,e.id))});return authoredRuntimeModelMocks.set(e.id,r),r}function createMockModelResult(e,t){let n=getLastAuthoredToolResult(e.prompt);if(n!==null){let r=createFollowUpToolCallResult({modelId:t,options:e,result:n});if(r!==null)return r}else{let n=createSkillLoadResult(e.prompt,t)??createAuthoredToolCallResult(e,t);if(n!==null)return n}let r=createFinalOutputResult(e,t);if(r!==null)return r;let i=n===null?createAssistantMessage(e.prompt):formatToolResultReply(n,e.prompt);return createBootstrapGenerateResult({inputTokens:estimateTokenCount(getPromptText(e.prompt)),modelId:t,outputTokens:estimateTokenCount(i),text:i})}function createFinalOutputResult(e,t){let n=getAvailableTools(e).find(e=>e.name===FINAL_OUTPUT_TOOL_NAME);if(n===void 0)return null;let i=createJsonSchemaSample(n.inputSchema);return createToolCallGenerateResult({input:i,inputTokens:estimateTokenCount(getPromptText(e.prompt)),modelId:t,outputTokens:estimateTokenCount(JSON.stringify(i)),toolCallId:createToolCallId(FINAL_OUTPUT_TOOL_NAME),toolName:FINAL_OUTPUT_TOOL_NAME})}function resolveMockAuthoredRuntimeModel(e){return!shouldMockAuthoredRuntimeModels()||e.id===BOOTSTRAP_RUNTIME_MODEL_ID?null:createMockAuthoredRuntimeModel(e)}function createSkillLoadResult(e,n){let r=getLastUserPromptText(e);if(r===null||getActivatedSkillIds(e).length>0)return null;let i=findRelevantSkill(getAvailableSkills(e),r);return i===null?null:createToolCallGenerateResult({input:{skill:i.name},inputTokens:estimateTokenCount(getPromptText(e)),modelId:n,outputTokens:estimateTokenCount(i.name),toolCallId:`call_load_skill`,toolName:LOAD_SKILL_TOOL_NAME})}function createAuthoredToolCallResult(e,t){let n=getLastUserPromptText(e.prompt);if(n===null)return null;let r=findRelevantTool(getAvailableTools(e),n);if(r===null)return null;let i=createMockAuthoredToolInput(r,n,resolveWeatherCity(n));return createToolCallGenerateResult({input:i,inputTokens:estimateTokenCount(getPromptText(e.prompt)),modelId:t,outputTokens:estimateTokenCount(Object.values(i).join(` `)),toolCallId:createToolCallId(r.name),toolName:r.name})}function createFollowUpToolCallResult(e){let t=findNextExplicitToolAfterResult({previousToolName:e.result.toolName,prompt:e.options.prompt,tools:getAvailableTools(e.options)});if(t===null)return null;let n=createFollowUpToolInput(e.result.output);return n===null?null:createToolCallGenerateResult({input:n,inputTokens:estimateTokenCount(getPromptText(e.options.prompt)),modelId:e.modelId,outputTokens:estimateTokenCount(Object.values(n).join(` `)),toolCallId:createToolCallId(t.name),toolName:t.name})}function createAssistantMessage(e){let t=getLastUserPromptText(e)??`Hello from eve`,n=getSystemPromptLabels(e),r=resolveSystemProbe(e),i=resolveMockFixtureToken(e);return i===null?n.length>0?r===null?`Bootstrap reply [${n.join(`, `)}]: ${t}`:`Bootstrap reply [${n.join(`, `)}; probe=${r}]: ${t}`:r===null?`Bootstrap reply: ${t}`:`Bootstrap reply [probe=${r}]: ${t}`:i}function formatToolResultReply(e,t){if(e.isError)return`Local weather tool failed: ${formatToolOutput(e.output)}`;if(isWeatherPayload(e.output))return`Used local weather tool for ${e.output.city}: ${e.output.condition}, ${e.output.temperatureF}F. ${e.output.summary}`;let n=getLastUserPromptText(t)??`Hello from eve`;return`Used ${e.toolName} for "${n}": ${formatToolOutput(e.output)}`}function createToolCallGenerateResult(e){return{content:[{input:JSON.stringify(e.input),toolCallId:e.toolCallId,toolName:e.toolName,type:`tool-call`}],finishReason:{raw:void 0,unified:`tool-calls`},response:{id:`bootstrap-response`,modelId:e.modelId,timestamp:new Date(`2026-03-16T00:00:00.000Z`)},usage:{inputTokens:{cacheRead:0,cacheWrite:0,noCache:e.inputTokens,total:e.inputTokens},outputTokens:{reasoning:0,text:e.outputTokens,total:e.outputTokens}},warnings:[]}}function getAvailableTools(e){return(e.tools??[]).flatMap(e=>e.type===`function`?[{description:e.description,inputSchema:`inputSchema`in e?e.inputSchema:void 0,name:e.name,outputSchema:`outputSchema`in e?e.outputSchema:void 0}]:[])}function getLastAuthoredToolResult(e){for(let n of[...e].reverse()){if(n.role===`user`)return null;if(!(n.role!==`tool`&&n.role!==`assistant`)){for(let e of[...n.content].reverse())if(!(typeof e==`string`||e.type!==`tool-result`)&&e.toolName!==LOAD_SKILL_TOOL_NAME)return{isError:e.output.type===`error-json`||e.output.type===`error-text`||e.output.type===`execution-denied`,output:e.output.type===`execution-denied`?{reason:e.output.reason??null,type:e.output.type}:e.output.value,toolCallId:e.toolCallId,toolName:e.toolName}}}return null}function findNextExplicitToolAfterResult(e){let t=getLastUserPromptText(e.prompt);if(t===null)return null;let n=normalizeText(t),r=n.indexOf(normalizeText(e.previousToolName));return r<0?null:e.tools.filter(t=>t.name!==e.previousToolName).flatMap(e=>{let t=n.indexOf(normalizeText(e.name),r+1);return t<0?[]:[{index:t,tool:e}]}).sort((e,t)=>e.index-t.index)[0]?.tool??null}function createFollowUpToolInput(e){return isRecord(e)&&typeof e.stepKey==`string`?{stepKey:e.stepKey}:null}function getSystemPromptLabels(e){let t=e.filter(e=>e.role===`system`);if(t.length===0)return[];let n=t.flatMap(e=>{let t=getPromptContentText(e.content);if(t.startsWith(`Available skills
1
+ import{z}from"#compiled/zod/index.js";import{LOAD_SKILL_TOOL_NAME}from"#runtime/skills/fragment-context.js";import{MockLanguageModelV3}from"ai/test";import{FINAL_OUTPUT_TOOL_NAME}from"#runtime/framework-tools/final-output.js";import{BOOTSTRAP_RUNTIME_MODEL_ID,BOOTSTRAP_RUNTIME_SYSTEM_PROMPT}from"#runtime/agent/bootstrap.js";import{createBootstrapGenerateResult,createBootstrapStreamResult,estimateTokenCount,getLastUserPromptText,getPromptContentText,getPromptText}from"#runtime/agent/bootstrap-model-utils.js";import{createMockAuthoredToolInput,formatToolOutput,resolveMockFixtureToken,resolveWeatherCity}from"#runtime/agent/mock-model-fixtures.js";import{findRelevantSkill,getActivatedSkillIds,getAvailableSkills}from"#runtime/agent/mock-model-skill-selection.js";import{createJsonSchemaSample}from"#runtime/agent/mock-structured-output.js";const authoredRuntimeModelMocks=new Map,bootstrapWeatherPayloadSchema=z.object({city:z.string(),condition:z.string(),summary:z.string(),temperatureF:z.number().finite()}).strict();function shouldMockAuthoredRuntimeModels(){return process.env.NODE_ENV===`test`||process.env.EVE_MOCK_AUTHORED_MODELS===`1`}function createMockAuthoredRuntimeModel(e){let t=authoredRuntimeModelMocks.get(e.id);if(t!==void 0)return t;let r=new MockLanguageModelV3({modelId:e.id,provider:`eve-runtime-mock`,doGenerate:async t=>createMockModelResult(t,e.id),doStream:async t=>createBootstrapStreamResult(createMockModelResult(t,e.id))});return authoredRuntimeModelMocks.set(e.id,r),r}function createMockModelResult(e,t){let n=getLastAuthoredToolResult(e.prompt);if(n!==null){let r=createFollowUpToolCallResult({modelId:t,options:e,result:n});if(r!==null)return r}else{let n=createSkillLoadResult(e.prompt,t)??createAuthoredToolCallResult(e,t);if(n!==null)return n}let r=createFinalOutputResult(e,t);if(r!==null)return r;let i=n===null?createAssistantMessage(e.prompt):formatToolResultReply(n,e.prompt);return createBootstrapGenerateResult({inputTokens:estimateTokenCount(getPromptText(e.prompt)),modelId:t,outputTokens:estimateTokenCount(i),text:i})}function createFinalOutputResult(e,t){let n=getAvailableTools(e).find(e=>e.name===FINAL_OUTPUT_TOOL_NAME);if(n===void 0)return null;let i=createJsonSchemaSample(n.inputSchema);return createToolCallGenerateResult({input:i,inputTokens:estimateTokenCount(getPromptText(e.prompt)),modelId:t,outputTokens:estimateTokenCount(JSON.stringify(i)),toolCallId:createToolCallId(FINAL_OUTPUT_TOOL_NAME),toolName:FINAL_OUTPUT_TOOL_NAME})}function resolveMockAuthoredRuntimeModel(e){return!shouldMockAuthoredRuntimeModels()||e.id===BOOTSTRAP_RUNTIME_MODEL_ID?null:createMockAuthoredRuntimeModel(e)}function createSkillLoadResult(e,n){let r=getLastUserPromptText(e);if(r===null||getActivatedSkillIds(e).length>0)return null;let i=findRelevantSkill(getAvailableSkills(e),r);return i===null?null:createToolCallGenerateResult({input:{skill:i.name},inputTokens:estimateTokenCount(getPromptText(e)),modelId:n,outputTokens:estimateTokenCount(i.name),toolCallId:`call_load_skill`,toolName:LOAD_SKILL_TOOL_NAME})}function createAuthoredToolCallResult(e,t){let n=getLastUserPromptText(e.prompt);if(n===null)return null;let r=findRelevantTool(getAvailableTools(e),n);if(r===null)return null;let i=createMockAuthoredToolInput(r,n,resolveWeatherCity(n));return createToolCallGenerateResult({input:i,inputTokens:estimateTokenCount(getPromptText(e.prompt)),modelId:t,outputTokens:estimateTokenCount(Object.values(i).join(` `)),toolCallId:createToolCallId(r.name),toolName:r.name})}function createFollowUpToolCallResult(e){let t=findNextExplicitToolAfterResult({previousToolName:e.result.toolName,prompt:e.options.prompt,tools:getAvailableTools(e.options)});if(t===null)return null;let n=createFollowUpToolInput(e.result.output);return n===null?null:createToolCallGenerateResult({input:n,inputTokens:estimateTokenCount(getPromptText(e.options.prompt)),modelId:e.modelId,outputTokens:estimateTokenCount(Object.values(n).join(` `)),toolCallId:createToolCallId(t.name),toolName:t.name})}function createAssistantMessage(e){let t=getLastUserPromptText(e)??`Hello from eve`,n=getSystemPromptLabels(e),r=resolveSystemProbe(e),i=resolveMockFixtureToken(e);return i===null?n.length>0?r===null?`Bootstrap reply [${n.join(`, `)}]: ${t}`:`Bootstrap reply [${n.join(`, `)}; probe=${r}]: ${t}`:r===null?`Bootstrap reply: ${t}`:`Bootstrap reply [probe=${r}]: ${t}`:i}function formatToolResultReply(e,t){if(e.isError)return`Local weather tool failed: ${formatToolOutput(e.output)}`;if(isWeatherPayload(e.output))return`Used local weather tool for ${e.output.city}: ${e.output.condition}, ${e.output.temperatureF}F. ${e.output.summary}`;let n=getLastUserPromptText(t)??`Hello from eve`;return`Used ${e.toolName} for "${n}": ${formatToolOutput(e.output)}`}function createToolCallGenerateResult(e){return{content:[{input:JSON.stringify(e.input),toolCallId:e.toolCallId,toolName:e.toolName,type:`tool-call`}],finishReason:{raw:void 0,unified:`tool-calls`},response:{id:`bootstrap-response`,modelId:e.modelId,timestamp:new Date(`2026-03-16T00:00:00.000Z`)},usage:{inputTokens:{cacheRead:0,cacheWrite:0,noCache:e.inputTokens,total:e.inputTokens},outputTokens:{reasoning:0,text:e.outputTokens,total:e.outputTokens}},warnings:[]}}function getAvailableTools(e){return(e.tools??[]).flatMap(e=>e.type===`function`?[{description:e.description,inputSchema:`inputSchema`in e?e.inputSchema:void 0,name:e.name,outputSchema:`outputSchema`in e?e.outputSchema:void 0}]:[])}function getLastAuthoredToolResult(e){for(let n of[...e].reverse()){if(n.role===`user`)return null;if(!(n.role!==`tool`&&n.role!==`assistant`)){for(let e of[...n.content].reverse())if(!(typeof e==`string`||e.type!==`tool-result`)&&e.toolName!==LOAD_SKILL_TOOL_NAME)return{isError:e.output.type===`error-json`||e.output.type===`error-text`||e.output.type===`execution-denied`,output:e.output.type===`execution-denied`?{reason:e.output.reason??null,type:e.output.type}:e.output.value,toolCallId:e.toolCallId,toolName:e.toolName}}}return null}function findNextExplicitToolAfterResult(e){let t=getLastUserPromptText(e.prompt);if(t===null)return null;let n=normalizeText(t),r=n.indexOf(normalizeText(e.previousToolName));return r<0?null:e.tools.filter(t=>t.name!==e.previousToolName).flatMap(e=>{let t=n.indexOf(normalizeText(e.name),r+1);return t<0?[]:[{index:t,tool:e}]}).sort((e,t)=>e.index-t.index)[0]?.tool??null}function createFollowUpToolInput(e){return isRecord(e)&&typeof e.stepKey==`string`?{stepKey:e.stepKey}:null}function getSystemPromptLabels(e){let t=e.filter(e=>e.role===`system`);if(t.length===0)return[];let n=t.flatMap(e=>{let t=getPromptContentText(e.content);if(t.startsWith(`Available skills
2
2
  `))return[];let n=t.split(`
3
3
  `).map(e=>e.trim()).filter(e=>e.length>0),r=[];for(let e of n){if(e===BOOTSTRAP_RUNTIME_SYSTEM_PROMPT||e===`Available skills`)continue;let t=/^System \((.+)\)$/.exec(e);if(t?.[1]){r.push(t[1]);continue}let n=/^Skill \((.+)\)$/.exec(e);n?.[1]&&r.push(n[1])}if(r.length>0)return r;let i=n.find(e=>e!==BOOTSTRAP_RUNTIME_SYSTEM_PROMPT&&e!==`Available skills`);return i===void 0?[]:[i]});return[...new Set(n)]}function findRelevantTool(e,n){let r=normalizeText(n),i=e.find(e=>e.name!==`agent`&&e.name!==LOAD_SKILL_TOOL_NAME&&r.includes(normalizeText(e.name)));return i===void 0?/\b(forecast|temperature|weather|wind|rain|snow)\b/u.test(r)?e.find(e=>/\b(forecast|temperature|weather|wind|rain|snow)\b/u.test(normalizeText(`${e.name} ${e.description??``}`)))??null:null:i}function normalizeText(e){return e.toLowerCase().replace(/[^a-z0-9]+/gu,` `).trim()}function createToolCallId(e){return`call_${e.toLowerCase().replace(/[^a-z0-9]+/gu,`_`).replace(/^_+|_+$/gu,``)||`tool`}`}function resolveSystemProbe(e){let t=e.filter(e=>e.role===`system`).map(e=>getPromptContentText(e.content)).join(`
4
4
  `);return/hmr-probe:\s*([^\n]+)/iu.exec(t)?.[1]?.trim()||null}function isWeatherPayload(e){return bootstrapWeatherPayloadSchema.safeParse(e).success}function isRecord(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}export{createMockAuthoredRuntimeModel,resolveMockAuthoredRuntimeModel,shouldMockAuthoredRuntimeModels};
@@ -20,6 +20,8 @@ import type { AuthorizationDefinition, ConnectionPrincipal } from "#runtime/conn
20
20
  * issuer prefix prevents collisions when the same `id` across
21
21
  * identity providers (for example Slack `U123` vs Google `U123`)
22
22
  * would otherwise alias to the same cache slot.
23
+ * - `{ type: "user", id }` → `"user:${id}"`. This is the native
24
+ * Vercel Connect user projection.
23
25
  */
24
26
  export declare function principalKey(principal: ConnectionPrincipal): string;
25
27
  /**
@@ -1 +1 @@
1
- import{AuthKey}from"#context/keys.js";import{contextStorage}from"#context/container.js";import{ConnectionAuthorizationFailedError}from"#public/connections/errors.js";function principalKey(e){return e.type===`app`?`app`:`user:${e.issuer}:${e.id}`}function resolveConnectionPrincipal(r,i,a=contextStorage.getStore()){if(i.principalType===`app`)return{type:`app`};let o=a?.get(AuthKey);if(o==null||o.principalType!==`user`)throw new ConnectionAuthorizationFailedError(r,{message:buildUserPrincipalRequiredMessage(r,a,o?.principalType),reason:`principal_required`,retryable:!1});return{attributes:o.attributes,id:o.principalId,issuer:o.issuer??o.authenticator,type:`user`}}function buildUserPrincipalRequiredMessage(e,t,n){let r;return r=t===void 0?`it was invoked outside an eve context, so no authenticated user can be resolved.`:n===void 0?`the active session has no authenticated user.`:`the active session is scoped to "${n}", not an authenticated user.`,`Connection "${e}" is user-scoped, but ${r} User-scoped connections require route auth that resolves an authenticated user. If this connection should use credentials shared by the agent instead, configure it as an app-scoped connection.`}export{principalKey,resolveConnectionPrincipal};
1
+ import{AuthKey}from"#context/keys.js";import{contextStorage}from"#context/container.js";import{ConnectionAuthorizationFailedError}from"#public/connections/errors.js";function principalKey(e){return e.type===`app`?`app`:e.issuer===void 0?`user:${e.id}`:`user:${e.issuer}:${e.id}`}function resolveConnectionPrincipal(r,i,a=contextStorage.getStore()){if(i.principalType===`app`)return{type:`app`};let o=a?.get(AuthKey);if(o==null||o.principalType!==`user`)throw new ConnectionAuthorizationFailedError(r,{message:buildUserPrincipalRequiredMessage(r,i,a,o),reason:`principal_required`,retryable:!1});return i.vercelConnect!==void 0&&isVercelDevelopmentUser(o)?{attributes:o.attributes,id:o.subject??o.principalId,type:`user`}:{attributes:o.attributes,id:o.principalId,issuer:o.issuer??o.authenticator,type:`user`}}function isVercelDevelopmentUser(e){return e.authenticator===`oidc`&&e.issuer?.startsWith(`https://oidc.vercel.com/`)===!0&&e.attributes.environment===`development`&&e.subject===e.attributes.user_id}function buildUserPrincipalRequiredMessage(e,t,n,r){let i;return i=n===void 0?`it was invoked outside an eve context, so no authenticated user can be resolved.`:r==null?`the active session has no authenticated user.`:t.vercelConnect!==void 0&&r.authenticator===`local-dev`?`the local request fell back to local development access instead of authenticating a Vercel user. Ensure this directory is linked and the Vercel CLI can mint a Vercel OIDC token, then retry.`:`the active session is scoped to "${r.principalType}", not an authenticated user.`,`Connection "${e}" is user-scoped, but ${i} User-scoped connections require route auth that resolves an authenticated user. If this connection should use credentials shared by the agent instead, configure it as an app-scoped connection.`}export{principalKey,resolveConnectionPrincipal};
@@ -70,13 +70,16 @@ export type ToolFilterDefinition = {
70
70
  * - `{ type: "user", id, issuer }`: per end-user identity; the token
71
71
  * cache keys on `issuer + id` so the same `id` across different
72
72
  * IdPs (Slack `U123` vs Google `U123`) never collides.
73
+ * - `{ type: "user", id }`: Vercel Connect's native user subject, used for a
74
+ * verified Vercel development user. The Vercel OIDC issuer is not forwarded
75
+ * because Connect rejects it.
73
76
  */
74
77
  export type ConnectionPrincipal = {
75
78
  readonly type: "app";
76
79
  } | {
77
80
  readonly type: "user";
78
81
  readonly id: string;
79
- readonly issuer: string;
82
+ readonly issuer?: string;
80
83
  readonly attributes?: Readonly<Record<string, string | readonly string[]>>;
81
84
  };
82
85
  /**
@@ -1,11 +1,6 @@
1
1
  import type { ResolvedChannelDefinition } from "#runtime/types.js";
2
2
  /**
3
- * Framework default for the eve channel. Mirrors verbatim the scaffold
4
- * written by eve into `agent/channels/eve.ts`, so the
5
- * behavior of "no authored file" and "scaffolded file untouched" is
6
- * byte-identical — and the local-dev / Vercel branching lives in a
7
- * single named helper (`localDev`) instead of an env check buried in
8
- * the framework.
3
+ * Framework default for the eve channel.
9
4
  */
10
5
  export declare function getFrameworkChannelDefinitions(): readonly ResolvedChannelDefinition[];
11
6
  export declare function getAllFrameworkChannelNames(): ReadonlySet<string>;
@@ -1 +1 @@
1
- import{localDev,vercelOidc}from"#public/channels/auth.js";import{isHttpRouteDefinition}from"#channel/routes.js";import{eveChannel}from"#public/channels/eve.js";import{getConnectionCallbackChannelDefinitions,getConnectionCallbackChannelNames}from"#runtime/connections/callback-route.js";import{getSessionCallbackChannelDefinitions,getSessionCallbackChannelNames}from"#runtime/session-callback-route.js";function getFrameworkChannelDefinitions(){let r=eveChannel({auth:[localDev(),vercelOidc()]}),i=[];for(let e of r.routes)isHttpRouteDefinition(e)&&i.push({name:`eve`,method:e.method.toUpperCase(),urlPath:e.path,fetch:async(t,n)=>e.handler(t,n),handler:e.handler,adapter:r.adapter,logicalPath:`framework://channels/${e.path}`,sourceId:`eve:framework:${e.method.toLowerCase()}-${e.path}`,sourceKind:`module`});return i.push(...getConnectionCallbackChannelDefinitions(),...getSessionCallbackChannelDefinitions()),i}function getAllFrameworkChannelNames(){return new Set([`eve`,...getConnectionCallbackChannelNames(),...getSessionCallbackChannelNames()])}export{getAllFrameworkChannelNames,getFrameworkChannelDefinitions};
1
+ import{localDev,vercelOidc}from"#public/channels/auth.js";import{isHttpRouteDefinition}from"#channel/routes.js";import{eveChannel}from"#public/channels/eve.js";import{getConnectionCallbackChannelDefinitions,getConnectionCallbackChannelNames}from"#runtime/connections/callback-route.js";import{getSessionCallbackChannelDefinitions,getSessionCallbackChannelNames}from"#runtime/session-callback-route.js";function getFrameworkChannelDefinitions(){let r=eveChannel({auth:[vercelOidc(),localDev()]}),i=[];for(let e of r.routes)isHttpRouteDefinition(e)&&i.push({name:`eve`,method:e.method.toUpperCase(),urlPath:e.path,fetch:async(t,n)=>e.handler(t,n),handler:e.handler,adapter:r.adapter,logicalPath:`framework://channels/${e.path}`,sourceId:`eve:framework:${e.method.toLowerCase()}-${e.path}`,sourceKind:`module`});return i.push(...getConnectionCallbackChannelDefinitions(),...getSessionCallbackChannelDefinitions()),i}function getAllFrameworkChannelNames(){return new Set([`eve`,...getConnectionCallbackChannelNames(),...getSessionCallbackChannelNames()])}export{getAllFrameworkChannelNames,getFrameworkChannelDefinitions};
@@ -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})||!currentVercelEnvironmentMatches({payload:a.payload})?{kind:`caller-not-allowed`}:{kind:`authenticated`,principal:createJwtAuthenticatedCallerPrincipal({authenticator:`oidc`,issuerClaims:[`external_iss`,`connector_id`],payload:a.payload,principalType:`user`,subjectClaim:`external_sub`})};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}),s=o&&isCurrentVercelEnvironmentToken({payload:a.payload});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=process.env.VERCEL_PROJECT_ID?.trim();return t===void 0||t.length===0?!1:typeof e.payload.project_id==`string`&&e.payload.project_id===t}function currentVercelProjectMatches(e){let t=process.env.VERCEL_PROJECT_ID?.trim();return t===void 0||t.length===0?!1:typeof e.payload.project_id==`string`&&e.payload.project_id===t}function isCurrentVercelEnvironmentToken(e){let t=getCurrentVercelEnvironment();return t===void 0||t.length===0?!1:typeof e.payload.environment==`string`&&e.payload.environment===t}function currentVercelEnvironmentMatches(e){let t=getCurrentVercelEnvironment();return t===void 0||t.length===0?!1:typeof e.payload.environment==`string`&&e.payload.environment===t}function getCurrentVercelEnvironment(){return process.env.VERCEL_TARGET_ENV?.trim()||process.env.VERCEL_ENV?.trim()||void 0}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(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};
@@ -22,6 +22,11 @@ export interface ResolvedTokenClaimMatchers {
22
22
  readonly claims?: Readonly<Record<string, readonly string[]>>;
23
23
  readonly subjects?: readonly string[];
24
24
  }
25
+ /** One Vercel project and environment accepted by a Vercel OIDC strategy. */
26
+ export interface CurrentVercelProject {
27
+ readonly environment?: string;
28
+ readonly projectId: string;
29
+ }
25
30
  /**
26
31
  * Resolved HTTP Basic auth strategy.
27
32
  */
@@ -58,27 +63,26 @@ export interface ResolvedJwtEcdsaAuthStrategy extends ResolvedTokenClaimMatchers
58
63
  export interface ResolvedOidcAuthStrategy extends ResolvedTokenClaimMatchers {
59
64
  /**
60
65
  * Vercel-platform extension. When `true` and the token's issuer is
61
- * a Vercel OIDC issuer, tokens minted for the current
62
- * `VERCEL_PROJECT_ID` are accepted unconditionally — in addition to
66
+ * a Vercel OIDC issuer, tokens minted for the configured current project
67
+ * are accepted unconditionally — in addition to
63
68
  * the author-supplied `subjects`/`claims` matchers — so the
64
69
  * deployment's own runtime callers (subagent, internal fetches)
65
- * always authenticate. Tokens that additionally match the current
66
- * `VERCEL_TARGET_ENV` / `VERCEL_ENV` are tagged
70
+ * always authenticate. Tokens that additionally match the configured
71
+ * current environment are tagged
67
72
  * `principalType: "runtime"`; other current-project tokens are
68
73
  * tagged `"service"`.
69
74
  *
70
- * Vercel OIDC tokens with an `external_sub` claim are user tokens.
71
- * They must satisfy the current project/environment constraints when
72
- * those environment variables are configured, and then authenticate as
73
- * `principalType: "user"` with `external_sub` as their subject and
74
- * `external_iss` / `connector_id` as their issuer when present.
75
+ * Vercel OIDC tokens with an `external_sub` claim are user tokens. So are
76
+ * development tokens with a `user_id` claim when the configured environment
77
+ * is `development`. Both must satisfy the current project/environment bind.
75
78
  *
76
- * Set exclusively by `verifyVercelOidc`. The generic public
79
+ * Set exclusively by Vercel-specific verification. The generic public
77
80
  * `verifyOidc` always passes `false`.
78
81
  */
79
82
  readonly acceptCurrentVercelProject: boolean;
80
83
  readonly audiences: readonly string[];
81
84
  readonly clockSkewSeconds: number;
85
+ readonly currentVercelProject?: CurrentVercelProject;
82
86
  readonly discoveryUrl: string;
83
87
  readonly issuer: string;
84
88
  readonly kind: "oidc";
@@ -0,0 +1,12 @@
1
+ import type { CurrentVercelProject } from "#runtime/governance/auth/types.js";
2
+ type VercelOidcProjectResolver = () => CurrentVercelProject | undefined | Promise<CurrentVercelProject | undefined>;
3
+ /**
4
+ * Binds the current local project only to one request. The global symbol makes
5
+ * the binding visible to both Nitro-inlined and disk-imported eve modules.
6
+ */
7
+ export declare function withVercelOidcProjectResolver<T>(input: {
8
+ readonly request: Request;
9
+ readonly resolveCurrentProject: VercelOidcProjectResolver;
10
+ }, callback: () => Promise<T> | T): Promise<T>;
11
+ export declare function resolveVercelOidcCurrentProject(request: Request): Promise<CurrentVercelProject | undefined>;
12
+ export {};
@@ -0,0 +1 @@
1
+ const VERCEL_OIDC_PROJECT_RESOLVERS=Symbol.for(`eve.vercel-oidc-project-resolvers`),globalResolverRegistry=globalThis;globalResolverRegistry[VERCEL_OIDC_PROJECT_RESOLVERS]===void 0&&(globalResolverRegistry[VERCEL_OIDC_PROJECT_RESOLVERS]=new WeakMap);const projectResolvers=globalResolverRegistry[VERCEL_OIDC_PROJECT_RESOLVERS];async function withVercelOidcProjectResolver(e,t){let n=projectResolvers.get(e.request);projectResolvers.set(e.request,e.resolveCurrentProject);try{return await t()}finally{n===void 0?projectResolvers.delete(e.request):projectResolvers.set(e.request,n)}}async function resolveVercelOidcCurrentProject(e){let t=projectResolvers.get(e);return t===void 0?void 0:await t()}export{resolveVercelOidcCurrentProject,withVercelOidcProjectResolver};
@@ -6,6 +6,11 @@ import type { DevelopmentCredentialGate } from "./credential-gate.js";
6
6
  * credentials through this default path.
7
7
  */
8
8
  export declare function resolveDevelopmentClientOptions(serverUrl: string): ClientOptions;
9
+ /** Builds a non-redirecting local client with an explicit per-request bearer source. */
10
+ export declare function resolveLocalDevelopmentClientOptions(input: {
11
+ readonly serverUrl: string;
12
+ readonly token: () => Promise<string>;
13
+ }): ClientOptions;
9
14
  /** Builds non-redirecting client options backed by one verified credential gate. */
10
15
  export declare function resolveRemoteDevelopmentClientOptions(input: {
11
16
  readonly credentials: DevelopmentCredentialGate;
@@ -1 +1 @@
1
- function resolveDevelopmentClientOptions(e){return{host:e}}function resolveRemoteDevelopmentClientOptions(e){let t=new URL(e.serverUrl).origin;if(e.credentials.serverOrigin!==t)throw Error(`Credential gate origin ${e.credentials.serverOrigin} does not match client origin ${t}.`);return{auth:{vercelOidc:{token:()=>e.credentials.resolveToken()}},headers:e.credentials.resolveBypassHeaders,host:e.serverUrl,redirect:`manual`}}export{resolveDevelopmentClientOptions,resolveRemoteDevelopmentClientOptions};
1
+ function resolveDevelopmentClientOptions(e){return{host:e}}function resolveLocalDevelopmentClientOptions(e){return{auth:{bearer:e.token},host:e.serverUrl,redirect:`manual`}}function resolveRemoteDevelopmentClientOptions(e){let t=new URL(e.serverUrl).origin;if(e.credentials.serverOrigin!==t)throw Error(`Credential gate origin ${e.credentials.serverOrigin} does not match client origin ${t}.`);return{auth:{vercelOidc:{token:()=>e.credentials.resolveToken()}},headers:e.credentials.resolveBypassHeaders,host:e.serverUrl,redirect:`manual`}}export{resolveDevelopmentClientOptions,resolveLocalDevelopmentClientOptions,resolveRemoteDevelopmentClientOptions};
@@ -37,6 +37,14 @@ export type DevelopmentOidcTokenResolution = {
37
37
  * first and install the result in a `DevelopmentCredentialGate`.
38
38
  */
39
39
  export declare function resolveDevelopmentOidcToken(input: DevelopmentOidcTarget): Promise<DevelopmentOidcTokenResolution>;
40
+ /**
41
+ * Resolves the current linked project's Vercel OIDC token for a local TUI request.
42
+ *
43
+ * An unavailable token deliberately becomes no bearer, so ordinary local
44
+ * requests still reach `localDev()`; user-scoped Connect requests then report
45
+ * that they need a Vercel user rather than trusting a client-supplied failure.
46
+ */
47
+ export declare function resolveLinkedDevelopmentOidcToken(workspaceRoot: string): Promise<string>;
40
48
  /**
41
49
  * Vercel header used to bypass preview protection for framework-owned routes
42
50
  * during local CLI development. Paired with a Protection Bypass for
@@ -1 +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{toErrorMessage}from"#shared/errors.js";import{getVercelOidcToken}from"#compiled/@vercel/oidc/index.js";const VercelOidcClaimsSchema=object({owner_id:string().min(1),project_id:string().min(1)});async function resolveDevelopmentOidcToken(e){try{let t={team:e.ownerId,project:e.projectId};return e.forceRefresh===!0&&(t.expirationBufferMs=2**53-1),validateDevelopmentOidcToken((await getVercelOidcToken(t)).trim(),e)}catch(e){return{kind:`resolution-failed`,message:toErrorMessage(e)}}}function validateDevelopmentOidcToken(e,t){let n=e.split(`.`)[1];if(!n)return{kind:`malformed-token`,reason:`missing-payload`};let r;try{r=JSON.parse(Buffer.from(n,`base64url`).toString(`utf8`))}catch{return{kind:`malformed-token`,reason:`invalid-json-payload`}}let i=VercelOidcClaimsSchema.safeParse(r);if(!i.success)return{kind:`invalid-claims`,invalidClaims:i.error.issues.map(e=>{let t=e.path[0];return t===`owner_id`||t===`project_id`?t:`claims`})};let a=[];return i.data.owner_id!==t.ownerId&&a.push(`owner_id`),i.data.project_id!==t.projectId&&a.push(`project_id`),a.length>0?{kind:`target-mismatch`,mismatchedClaims:a}:{kind:`resolved`,token:e}}const VERCEL_PROTECTION_BYPASS_HEADER=`x-vercel-protection-bypass`;export{VERCEL_PROTECTION_BYPASS_HEADER,resolveDevelopmentOidcToken};
1
+ import{literal,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{toErrorMessage}from"#shared/errors.js";import{getVercelOidcToken}from"#compiled/@vercel/oidc/index.js";import{readVercelProjectLink}from"#internal/vercel/project-link.js";const VercelOidcClaimsSchema=object({owner_id:string().min(1),project_id:string().min(1)}),LocalDevelopmentUserOidcClaimsSchema=VercelOidcClaimsSchema.extend({environment:literal(`development`),user_id:string().min(1)});async function resolveDevelopmentOidcToken(e){try{let t={team:e.ownerId,project:e.projectId};return e.forceRefresh===!0&&(t.expirationBufferMs=2**53-1),validateDevelopmentOidcToken((await getVercelOidcToken(t)).trim(),e)}catch(e){return{kind:`resolution-failed`,message:toErrorMessage(e)}}}async function resolveLinkedDevelopmentOidcToken(e){let t=await readVercelProjectLink(e);if(t===void 0)return``;let n={ownerId:t.orgId,projectId:t.projectId},r=await resolveDevelopmentOidcToken(n);if(r.kind===`resolved`&&isLocalDevelopmentUserToken(r.token))return r.token;if(r.kind!==`resolved`&&r.kind!==`target-mismatch`)return``;let i=await resolveDevelopmentOidcToken({...n,forceRefresh:!0});return i.kind===`resolved`&&isLocalDevelopmentUserToken(i.token)?i.token:``}function isLocalDevelopmentUserToken(e){let t=decodeOidcPayload(e);return t!==void 0&&LocalDevelopmentUserOidcClaimsSchema.safeParse(t).success}function validateDevelopmentOidcToken(e,t){let n=decodeOidcPayload(e);if(n===void 0)return e.split(`.`)[1]?{kind:`malformed-token`,reason:`invalid-json-payload`}:{kind:`malformed-token`,reason:`missing-payload`};let r=VercelOidcClaimsSchema.safeParse(n);if(!r.success)return{kind:`invalid-claims`,invalidClaims:r.error.issues.map(e=>{let t=e.path[0];return t===`owner_id`||t===`project_id`?t:`claims`})};let i=[];return r.data.owner_id!==t.ownerId&&i.push(`owner_id`),r.data.project_id!==t.projectId&&i.push(`project_id`),i.length>0?{kind:`target-mismatch`,mismatchedClaims:i}:{kind:`resolved`,token:e}}function decodeOidcPayload(e){let t=e.split(`.`)[1];if(t)try{return JSON.parse(Buffer.from(t,`base64url`).toString(`utf8`))}catch{return}}const VERCEL_PROTECTION_BYPASS_HEADER=`x-vercel-protection-bypass`;export{VERCEL_PROTECTION_BYPASS_HEADER,resolveDevelopmentOidcToken,resolveLinkedDevelopmentOidcToken};
@@ -12,5 +12,6 @@ export declare function readDevelopmentRuntimeArtifactsRevision(input: {
12
12
  readonly serverUrl: string;
13
13
  }): Promise<string | undefined>;
14
14
  export declare function rebuildDevelopmentRuntimeArtifacts(input: {
15
+ readonly force?: boolean;
15
16
  readonly serverUrl: string;
16
17
  }): Promise<string | undefined>;
@@ -1 +1 @@
1
- import{EVE_DEV_RUNTIME_ARTIFACTS_REBUILD_ROUTE_PATH,EVE_DEV_RUNTIME_ARTIFACTS_ROUTE_PATH}from"#protocol/routes.js";async function readDevelopmentRuntimeArtifactsRevision(e){try{let n=new URL(EVE_DEV_RUNTIME_ARTIFACTS_ROUTE_PATH,e.serverUrl);return await parseDevelopmentRuntimeArtifactsRevision(await fetch(n))}catch{return}}async function rebuildDevelopmentRuntimeArtifacts(t){try{let n=new URL(EVE_DEV_RUNTIME_ARTIFACTS_REBUILD_ROUTE_PATH,t.serverUrl);return await parseDevelopmentRuntimeArtifactsRevision(await fetch(n,{method:`POST`}))}catch{return}}async function parseDevelopmentRuntimeArtifactsRevision(e){if(!e.ok)return;let t=await e.json();return typeof t.revision==`string`&&t.revision.length>0?t.revision:void 0}export{readDevelopmentRuntimeArtifactsRevision,rebuildDevelopmentRuntimeArtifacts};
1
+ import{EVE_DEV_RUNTIME_ARTIFACTS_REBUILD_ROUTE_PATH,EVE_DEV_RUNTIME_ARTIFACTS_ROUTE_PATH}from"#protocol/routes.js";async function readDevelopmentRuntimeArtifactsRevision(e){try{let n=new URL(EVE_DEV_RUNTIME_ARTIFACTS_ROUTE_PATH,e.serverUrl);return await parseDevelopmentRuntimeArtifactsRevision(await fetch(n))}catch{return}}async function rebuildDevelopmentRuntimeArtifacts(t){try{let n=new URL(EVE_DEV_RUNTIME_ARTIFACTS_REBUILD_ROUTE_PATH,t.serverUrl);return t.force===!0&&n.searchParams.set(`force`,`1`),await parseDevelopmentRuntimeArtifactsRevision(await fetch(n,{method:`POST`}))}catch{return}}async function parseDevelopmentRuntimeArtifactsRevision(e){if(!e.ok)return;let t=await e.json();return typeof t.revision==`string`&&t.revision.length>0?t.revision:void 0}export{readDevelopmentRuntimeArtifactsRevision,rebuildDevelopmentRuntimeArtifacts};
@@ -21,6 +21,14 @@ export interface DevelopmentRuntimeArtifactSessionRefresher {
21
21
  readonly onRuntimeArtifactsChanged?: (change: DevelopmentRuntimeArtifactChange) => void | Promise<void>;
22
22
  readonly session: ClientSession;
23
23
  }): Promise<ClientSession>;
24
+ /**
25
+ * Forces one rebuild after a local setup action wrote authored source.
26
+ */
27
+ refreshAfterSourceChange(input: {
28
+ readonly createSession: () => ClientSession;
29
+ readonly onRuntimeArtifactsChanged?: (change: DevelopmentRuntimeArtifactChange) => void | Promise<void>;
30
+ readonly session: ClientSession;
31
+ }): Promise<ClientSession>;
24
32
  /**
25
33
  * Checks for a runtime-artifact revision change while the UI is idle.
26
34
  */
@@ -1 +1 @@
1
- import{isLocalDevelopmentServerUrl}from"#services/dev-client/local-host.js";import{readDevelopmentRuntimeArtifactsRevision,rebuildDevelopmentRuntimeArtifacts}from"#services/dev-client/runtime-artifacts.js";var LocalDevelopmentRuntimeArtifactSessionRefresher=class{#e;#t;#n;constructor(t){this.#e=isLocalDevelopmentServerUrl(t.serverUrl),this.#t=t.serverUrl}clear(){this.#n=void 0}async refresh(e){return shouldRefreshRuntimeArtifactsForTurn(e)?await this.#r({...e,rebuild:!0}):e.session}async refreshIdle(e){return await this.#r({...e,rebuild:!1})}async#r(e){if(!this.#e)return e.session;let n=(e.rebuild?await rebuildDevelopmentRuntimeArtifacts({serverUrl:this.#t}):void 0)??await readDevelopmentRuntimeArtifactsRevision({serverUrl:this.#t});if(n===void 0)return e.session;let r=e.session,i=this.#n;return i!==void 0&&i!==n&&(r.state.continuationToken!==void 0&&(r=e.createSession()),await e.onRuntimeArtifactsChanged?.({previousRevision:i,revision:n})),this.#n=n,r}};function shouldRefreshRuntimeArtifactsForTurn(e){return e.message!==void 0&&(e.inputResponses?.length??0)===0}function createDevelopmentRuntimeArtifactSessionRefresher(e){return new LocalDevelopmentRuntimeArtifactSessionRefresher(e)}export{createDevelopmentRuntimeArtifactSessionRefresher};
1
+ import{isLocalDevelopmentServerUrl}from"#services/dev-client/local-host.js";import{readDevelopmentRuntimeArtifactsRevision,rebuildDevelopmentRuntimeArtifacts}from"#services/dev-client/runtime-artifacts.js";var LocalDevelopmentRuntimeArtifactSessionRefresher=class{#e;#t;#n;constructor(t){this.#e=isLocalDevelopmentServerUrl(t.serverUrl),this.#t=t.serverUrl}clear(){this.#n=void 0}async refresh(e){return shouldRefreshRuntimeArtifactsForTurn(e)?await this.#r({...e,rebuild:!0}):e.session}async refreshIdle(e){return await this.#r({...e,rebuild:!1})}async refreshAfterSourceChange(e){return await this.#r({...e,force:!0,rebuild:!0,resetActiveSession:!0})}async#r(e){if(!this.#e)return e.session;let n=(e.rebuild?await rebuildDevelopmentRuntimeArtifacts({force:e.force,serverUrl:this.#t}):void 0)??await readDevelopmentRuntimeArtifactsRevision({serverUrl:this.#t});if(n===void 0)return e.session;let r=e.session,i=this.#n,a=i!==void 0&&i!==n;return(a||e.resetActiveSession===!0)&&r.state.continuationToken!==void 0&&(r=e.createSession()),a&&await e.onRuntimeArtifactsChanged?.({previousRevision:i,revision:n}),this.#n=n,r}};function shouldRefreshRuntimeArtifactsForTurn(e){return e.message!==void 0&&(e.inputResponses?.length??0)===0}function createDevelopmentRuntimeArtifactSessionRefresher(e){return new LocalDevelopmentRuntimeArtifactSessionRefresher(e)}export{createDevelopmentRuntimeArtifactSessionRefresher};
@@ -1,24 +1,26 @@
1
- import { ensureConnection } from "#setup/scaffold/index.js";
2
- import { setupConnectionConnector } from "../connection-connector.js";
3
- import { type ProjectResolution } from "../project-resolution.js";
1
+ import { ensureConnection, listAuthoredConnections } from "#setup/scaffold/index.js";
2
+ import { cleanupCreatedConnectionConnector, setupConnectionConnector } from "../connection-connector.js";
3
+ import { readProjectLink, type ProjectResolution } from "../project-resolution.js";
4
4
  import type { Prompter } from "../prompter.js";
5
5
  import { type SetupState } from "../state.js";
6
6
  import type { SetupBox } from "../step.js";
7
7
  /** Injected for tests; defaults to the real scaffold and Connect effects. */
8
8
  export interface AddConnectionsDeps {
9
9
  ensureConnection: typeof ensureConnection;
10
+ listAuthoredConnections: typeof listAuthoredConnections;
11
+ readProjectLink: typeof readProjectLink;
10
12
  setupConnectionConnector: typeof setupConnectionConnector;
13
+ cleanupCreatedConnectionConnector: typeof cleanupCreatedConnectionConnector;
11
14
  }
12
15
  export interface AddConnectionsOptions {
13
- /** Carries the follow-up log lines and `perform`'s progress output. The box never prompts. */
16
+ /** Carries connector selection prompts and provisioning output. */
14
17
  prompter: Prompter;
18
+ signal?: AbortSignal;
15
19
  deps?: AddConnectionsDeps;
16
20
  }
17
21
  /**
18
22
  * THE CONNECTIONS BOX: executes the {@link ConnectionPlan}s the
19
- * select-connections box recorded during the interview. Prompts for nothing
20
- * every decision (slug, protocol, entry, provisioning mode) was resolved at
21
- * selection time — and only runs effects: the file scaffold, the follow-up log
22
- * lines, and the Connect connector provisioning against the linked project.
23
+ * select-connections box recorded during the interview. It scaffolds each file
24
+ * and resolves the concrete Connect connector against the linked project.
23
25
  */
24
26
  export declare function addConnections(options: AddConnectionsOptions): SetupBox<SetupState, null, ProjectResolution>;
@@ -1 +1 @@
1
- import{isProjectResolved,mergeProjectResolution}from"../project-resolution.js";import{hasVercelProject,requireProjectPath}from"../state.js";import{setupConnectionConnector}from"../connection-connector.js";import{projectIdFromResolution}from"../vercel-project.js";import{CONNECT_REQUIRES_VERCEL}from"./select-connections.js";import{ensureConnection}from"#setup/scaffold/index.js";function logFollowUp(e,t){if(t.action===`skipped`){e.warning(`Skipped ${t.slug} (already exists; pass --force to overwrite).`);return}e.success(`Added agent/connections/${t.slug}.ts`),t.envKeysAdded.length>0?e.info(`Set ${t.envKeysAdded.join(`, `)} in .env.local`):t.envKeysRequired.length>0&&e.info(`Set ${t.envKeysRequired.join(`, `)} in your environment`)}function addConnections(a){let o=a.deps??{ensureConnection,setupConnectionConnector};return{id:`add-connections`,shouldRun(e){return e.connectionSelection.length>0},async gather(){return null},async perform({state:t}){let r=a.prompter.log,i=requireProjectPath(t),s=!hasVercelProject(t),c=t.project;for(let n of t.connectionSelection){let t=await o.ensureConnection({projectRoot:i,slug:n.slug,protocol:n.protocol,entry:n.entry});if(logFollowUp(r,t),t.action!==`skipped`)switch(n.provision.kind){case`connect`:await o.setupConnectionConnector({log:r,projectRoot:i,slug:t.slug,service:n.provision.service,connectionFilePath:t.filePath,linkProject:async()=>{if(s)throw Error(CONNECT_REQUIRES_VERCEL);if(!isProjectResolved(c))throw Error(`Expected a linked Vercel project for Connect, but none was resolved.`);return projectIdFromResolution(c)}});break;case`command-hint`:r.info(`Run \`vercel connect create ${n.provision.service} --name ${t.slug}\`, then set the connector UID in agent/connections/${t.slug}.ts.`);break;case`connect-manual`:r.warning(`Could not determine a Connect service for ${t.slug}. Create the connector manually and set its UID in agent/connections/${t.slug}.ts.`);break;case`none`:break}}return c},apply(e,n){return{...e,project:mergeProjectResolution(e.project,n)}}}}export{addConnections};
1
+ import{isProjectResolved,mergeProjectResolution,readProjectLink}from"../project-resolution.js";import{hasVercelProject,requireProjectPath}from"../state.js";import{cleanupCreatedConnectionConnector,setupConnectionConnector}from"../connection-connector.js";import{canonicalConnectorNameForEntry}from"../scaffold/connections/catalog.js";import{projectIdFromResolution}from"../vercel-project.js";import{CONNECT_REQUIRES_VERCEL}from"./select-connections.js";import{ensureConnection,listAuthoredConnections}from"#setup/scaffold/index.js";function logFollowUp(e,t){if(t.action===`skipped`){e.warning(`Skipped ${t.slug} (already exists; pass --force to overwrite).`);return}e.success(`Added agent/connections/${t.slug}.ts`),t.envKeysAdded.length>0?e.info(`Set ${t.envKeysAdded.join(`, `)} in .env.local`):t.envKeysRequired.length>0&&e.info(`Set ${t.envKeysRequired.join(`, `)} in your environment`)}function withConnectorUid(e,t){if(e.auth?.kind!==`connect`)throw Error(`Connection ${e.slug} is not configured for Vercel Connect.`);return{...e,auth:{...e.auth,connector:t}}}function addConnections(e){let s=e.deps??{ensureConnection,listAuthoredConnections,readProjectLink,setupConnectionConnector,cleanupCreatedConnectionConnector};return{id:`add-connections`,shouldRun(e){return e.connectionSelection.length>0},async gather(){return null},async perform({state:t}){let n=e.prompter.log,a=requireProjectPath(t),o=!hasVercelProject(t),c=t.project,l=new Set(await s.listAuthoredConnections(a));for(let r of t.connectionSelection){if(l.has(r.slug)){logFollowUp(n,await s.ensureConnection({projectRoot:a,slug:r.slug,protocol:r.protocol,entry:r.entry}));continue}let t=r.entry,i;switch(r.provision.kind){case`connect`:{let l=canonicalConnectorNameForEntry(r.entry);if(l===void 0)throw Error(`Connection ${r.slug} has no canonical connector name.`);let u=await s.setupConnectionConnector({log:n,prompter:e.prompter,projectRoot:a,slug:r.slug,service:r.provision.service,canonicalConnectorName:l,project:await resolveConnectionProject({noVercel:o,project:c,projectRoot:a,readProjectLink:s.readProjectLink}),signal:e.signal});t=withConnectorUid(t,u.connectorUid),u.kind===`created`&&(i=u.connectorId);break}case`command-hint`:n.info(`Run \`vercel connect create ${r.provision.service} --name ${r.slug}\`, then set the connector UID in agent/connections/${r.slug}.ts.`);break;case`connect-manual`:n.warning(`Could not determine a Connect service for ${r.slug}. Create the connector manually and set its UID in agent/connections/${r.slug}.ts.`);break;case`none`:break}let u;try{u=await s.ensureConnection({projectRoot:a,slug:r.slug,protocol:r.protocol,entry:t})}catch(e){if(i!==void 0)try{await s.cleanupCreatedConnectionConnector({log:n,projectRoot:a,connectorId:i})}catch(t){throw AggregateError([e,t],`${e instanceof Error?e.message:String(e)} ${t instanceof Error?t.message:String(t)}`)}throw e}u.action===`skipped`&&i!==void 0&&await s.cleanupCreatedConnectionConnector({log:n,projectRoot:a,connectorId:i}),logFollowUp(n,u),u.action!==`skipped`&&l.add(u.slug)}return c},apply(e,n){return{...e,project:mergeProjectResolution(e.project,n)}}}}async function resolveConnectionProject(t){if(t.noVercel)throw Error(CONNECT_REQUIRES_VERCEL);if(!isProjectResolved(t.project))throw Error(`Expected a linked Vercel project for Connect, but none was resolved.`);let n=await t.readProjectLink(t.projectRoot);if(n===void 0||n.projectId!==projectIdFromResolution(t.project))throw Error("A linked Vercel project is required. Run `eve link`, then retry /connect.");return n}export{addConnections};
@@ -46,6 +46,7 @@ export interface ResolveProvisioningOptions {
46
46
  * team selection to the existing-project picker.
47
47
  */
48
48
  projectSelection?: "create-or-link" | "existing-only";
49
+ teamSelectMessage?: (currentTeam: string) => string;
49
50
  deps?: ResolveProvisioningDeps;
50
51
  }
51
52
  /** Both provisioning plans plus the model wiring they imply. Input and payload. */
@@ -1 +1 @@
1
- import{select,text}from"../ask.js";import{detectProjectResolution,isProjectResolved,mergeProjectResolution}from"../project-resolution.js";import{withSpinner}from"../with-spinner.js";import{assertNewProjectNameAvailable,isVercelAuthenticated,pickNewProjectName,pickProject,pickTeam,requireAuth,resolveProjectByNameOrId,resolveTeam,validateTeam}from"../vercel-project.js";import{pathExists}from"../path-exists.js";import{join,resolve}from"node:path";import{byokProviderEnvVar}from"#setup/scaffold/index.js";import{whimsyFor}from"#setup/cli/index.js";function vercelDemands(e){return{slack:e.channelSelection.includes(`slack`),connectSlugs:e.connectionSelection.filter(e=>e.entry.auth?.kind===`connect`).map(e=>e.slug)}}function connectClause(e){let t=e.length===1?`authenticates`:`authenticate`;return`${e.join(`, `)} ${t} through Vercel Connect`}function vercelRequirements(e){let t=[];return e.slack&&t.push(`Slack needs a public URL`),e.connectSlugs.length>0&&t.push(connectClause(e.connectSlugs)),t}function resolveProvisioning(l){let u=l.deps??{requireAuth,isVercelAuthenticated,detectProjectResolution,pathExists,validateTeam,resolveTeam,pickTeam,pickProject,pickNewProjectName,assertNewProjectNameAvailable,resolveProjectByNameOrId},parent=()=>resolve(l.targetDirectory??process.cwd());async function detectAdoptableLink(e,t){if(e.projectPath.kind!==`resolved`)return;let n=e.projectPath.path;if(await u.pathExists(join(n,`.vercel`,`project.json`)))return withSpinner(l.prompter,whimsyFor(`project-detect`),async()=>{let e=await u.detectProjectResolution(n,{signal:t});if(!(!isProjectResolved(e)||!await u.isVercelAuthenticated(n,{signal:t})))return e})}async function plansFromFlags(e,t,n,r){if(t.skipVercel)return n.apiKey===void 0?{vercelProject:{kind:`none`},aiGateway:{kind:`byop`},modelWiring:`self`}:{vercelProject:{kind:`none`},aiGateway:{kind:`byok`,apiGatewayKey:n.apiKey},modelWiring:`gateway`};if(t.team===void 0||t.team.length===0)throw Error(`Headless Vercel provisioning requires --team <slug> or --scope <slug> so the current CLI scope is not applied silently.`);await u.requireAuth(parent(),void 0,{signal:r}),await u.validateTeam(l.prompter,parent(),t.team,{signal:r});let i=await u.resolveTeam(parent(),t.team,{signal:r}),a=n.apiKey===void 0?{kind:`inherit`}:{kind:`byok`,apiGatewayKey:n.apiKey},o;if(t.project===void 0)o={kind:`new`,project:e,team:i};else{let e=await u.resolveProjectByNameOrId(parent(),i,t.project,{signal:r});if(e===null)throw Error(`Vercel project "${t.project}" was not found in ${i}.`);o={kind:`existing`,project:e,team:i}}return o.kind===`new`&&await u.assertNewProjectNameAvailable(parent(),i,o.project,{signal:r}),{vercelProject:o,aiGateway:a,modelWiring:`gateway`}}async function promptPlans(n,r){let i=l.prompter,a=n.agentName,o=l.adoptExistingLink===!1?void 0:await detectAdoptableLink(n,r);if(o!==void 0)return i.log.info(`This directory is already linked to a Vercel project, so your agent will run there — the AI Gateway authenticates through your Vercel login.`),{vercelProject:{kind:`none`},aiGateway:{kind:`inherit`},modelWiring:`gateway`,project:o};let s=vercelRequirements(vercelDemands(n)),c=!0;if(s.length>0?i.log.info(`${s.join(` and `)}, so your agent will run on Vercel.`):c=await l.asker.ask(select({key:`deploy`,message:`Where should your agent run?`,options:[{id:`vercel`,value:!0,label:`On Vercel`,hint:`AI Gateway, Durable Workflow, Sandbox, and more`},{id:`local`,value:!1,label:`Locally for now`,hint:`run with eve dev, deploy any time later`}],recommended:!0,required:!0})),c){await u.requireAuth(parent(),i,{signal:r});let t=await u.pickTeam(i,parent(),void 0,{signal:r}),n=[{value:`new`,label:`Create a new project`,hint:`Name: ${a}`},{value:`link`,label:`Link an existing project`}],o=l.projectSelection!==`existing-only`&&l.prompter.selectEditable?await l.prompter.selectEditable({message:`Vercel project`,options:n,initialValue:`new`,editable:{value:`new`,defaultValue:a,formatHint:e=>`Name: ${e}`,validate:e=>e.trim().length===0?`Project name cannot be empty.`:void 0}}):void 0;if((l.projectSelection===`existing-only`?`link`:o?.value??await l.asker.ask(select({key:`vercel-project`,message:`Vercel project`,options:[{id:`new`,value:`new`,label:`Create a new project`,hint:`Name: ${a}`},{id:`link`,value:`link`,label:`Link an existing project`}],recommended:`new`,required:!0})))===`new`){let e=o?.kind===`edited`?o.text:a;return{vercelProject:{kind:`new`,project:await u.pickNewProjectName(i,parent(),t,e,{signal:r}),team:t},aiGateway:{kind:`inherit`},modelWiring:`gateway`}}return{vercelProject:await u.pickProject(i,parent(),t,{allowCreateWhenEmpty:l.projectSelection!==`existing-only`,signal:r}),aiGateway:{kind:`inherit`},modelWiring:`gateway`}}return await l.asker.ask(select({key:`credential`,message:`How should your agent reach the model?`,options:[{id:`api-key`,value:`api-key`,label:`Use my own AI Gateway API key`,hint:`AI_GATEWAY_API_KEY`},{id:`local`,value:`local`,label:`Use my own provider API key`,hint:byokProviderEnvVar(n.modelId)}],recommended:`api-key`,required:!0}))===`api-key`?{vercelProject:{kind:`none`},aiGateway:{kind:`byok`,apiGatewayKey:await l.asker.ask(text({key:`gateway-api-key`,message:`Enter your AI_GATEWAY_API_KEY`,sensitive:!0,validate:e=>e.trim().length===0?`API key cannot be empty.`:null,required:!0}))},modelWiring:`gateway`}:{vercelProject:{kind:`none`},aiGateway:{kind:`byop`},modelWiring:`self`}}return{id:`resolve-provisioning`,async gather({state:e,signal:t}){if(l.mode.headless){let n=await plansFromFlags(e.agentName,l.mode.project,l.mode.aiGateway,t);if(n.vercelProject.kind===`none`){let t=vercelDemands(e);if(t.slack)throw Error(`Slack requires a Vercel project. Remove --skip-vercel to add Slack.`);if(t.connectSlugs.length>0)throw Error(`${connectClause(t.connectSlugs)}, which needs a Vercel project. Remove --skip-vercel to add ${t.connectSlugs.length===1?`it`:`them`}.`)}return n}return promptPlans(e,t)},async perform({input:e}){return e},apply(e,t){return{...e,vercelProject:t.vercelProject,aiGateway:t.aiGateway,modelWiring:t.modelWiring,project:t.project===void 0?e.project:mergeProjectResolution(e.project,t.project)}}}}export{resolveProvisioning};
1
+ import{select,text}from"../ask.js";import{detectProjectResolution,isProjectResolved,mergeProjectResolution}from"../project-resolution.js";import{withSpinner}from"../with-spinner.js";import{assertNewProjectNameAvailable,isVercelAuthenticated,pickNewProjectName,pickProject,pickTeam,requireAuth,resolveProjectByNameOrId,resolveTeam,validateTeam}from"../vercel-project.js";import{pathExists}from"../path-exists.js";import{join,resolve}from"node:path";import{byokProviderEnvVar}from"#setup/scaffold/index.js";import{whimsyFor}from"#setup/cli/index.js";function vercelDemands(e){return{slack:e.channelSelection.includes(`slack`),connectSlugs:e.connectionSelection.filter(e=>e.entry.auth?.kind===`connect`).map(e=>e.slug)}}function connectClause(e){let t=e.length===1?`authenticates`:`authenticate`;return`${e.join(`, `)} ${t} through Vercel Connect`}function vercelRequirements(e){let t=[];return e.slack&&t.push(`Slack needs a public URL`),e.connectSlugs.length>0&&t.push(connectClause(e.connectSlugs)),t}function resolveProvisioning(l){let u=l.deps??{requireAuth,isVercelAuthenticated,detectProjectResolution,pathExists,validateTeam,resolveTeam,pickTeam,pickProject,pickNewProjectName,assertNewProjectNameAvailable,resolveProjectByNameOrId},parent=()=>resolve(l.targetDirectory??process.cwd());async function detectAdoptableLink(e,t){if(e.projectPath.kind!==`resolved`)return;let n=e.projectPath.path;if(await u.pathExists(join(n,`.vercel`,`project.json`)))return withSpinner(l.prompter,whimsyFor(`project-detect`),async()=>{let e=await u.detectProjectResolution(n,{signal:t});if(!(!isProjectResolved(e)||!await u.isVercelAuthenticated(n,{signal:t})))return e})}async function plansFromFlags(e,t,n,r){if(t.skipVercel)return n.apiKey===void 0?{vercelProject:{kind:`none`},aiGateway:{kind:`byop`},modelWiring:`self`}:{vercelProject:{kind:`none`},aiGateway:{kind:`byok`,apiGatewayKey:n.apiKey},modelWiring:`gateway`};if(t.team===void 0||t.team.length===0)throw Error(`Headless Vercel provisioning requires --team <slug> or --scope <slug> so the current CLI scope is not applied silently.`);await u.requireAuth(parent(),void 0,{signal:r}),await u.validateTeam(l.prompter,parent(),t.team,{signal:r});let i=await u.resolveTeam(parent(),t.team,{signal:r}),a=n.apiKey===void 0?{kind:`inherit`}:{kind:`byok`,apiGatewayKey:n.apiKey},o;if(t.project===void 0)o={kind:`new`,project:e,team:i};else{let e=await u.resolveProjectByNameOrId(parent(),i,t.project,{signal:r});if(e===null)throw Error(`Vercel project "${t.project}" was not found in ${i}.`);o={kind:`existing`,project:e,team:i}}return o.kind===`new`&&await u.assertNewProjectNameAvailable(parent(),i,o.project,{signal:r}),{vercelProject:o,aiGateway:a,modelWiring:`gateway`}}async function promptPlans(n,r){let i=l.prompter,a=n.agentName,o=l.adoptExistingLink===!1?void 0:await detectAdoptableLink(n,r);if(o!==void 0)return i.log.info(`This directory is already linked to a Vercel project, so your agent will run there — the AI Gateway authenticates through your Vercel login.`),{vercelProject:{kind:`none`},aiGateway:{kind:`inherit`},modelWiring:`gateway`,project:o};let s=vercelRequirements(vercelDemands(n)),c=!0;if(s.length>0?i.log.info(`${s.join(` and `)}, so your agent will run on Vercel.`):c=await l.asker.ask(select({key:`deploy`,message:`Where should your agent run?`,options:[{id:`vercel`,value:!0,label:`On Vercel`,hint:`AI Gateway, Durable Workflow, Sandbox, and more`},{id:`local`,value:!1,label:`Locally for now`,hint:`run with eve dev, deploy any time later`}],recommended:!0,required:!0})),c){await u.requireAuth(parent(),i,{signal:r});let t={signal:r,selectMessage:l.teamSelectMessage},n=await u.pickTeam(i,parent(),void 0,t),o=[{value:`new`,label:`Create a new project`,hint:`Name: ${a}`},{value:`link`,label:`Link an existing project`}],s=l.projectSelection!==`existing-only`&&l.prompter.selectEditable?await l.prompter.selectEditable({message:`Vercel project`,options:o,initialValue:`new`,editable:{value:`new`,defaultValue:a,formatHint:e=>`Name: ${e}`,validate:e=>e.trim().length===0?`Project name cannot be empty.`:void 0}}):void 0;if((l.projectSelection===`existing-only`?`link`:s?.value??await l.asker.ask(select({key:`vercel-project`,message:`Vercel project`,options:[{id:`new`,value:`new`,label:`Create a new project`,hint:`Name: ${a}`},{id:`link`,value:`link`,label:`Link an existing project`}],recommended:`new`,required:!0})))===`new`){let e=s?.kind===`edited`?s.text:a;return{vercelProject:{kind:`new`,project:await u.pickNewProjectName(i,parent(),n,e,{signal:r}),team:n},aiGateway:{kind:`inherit`},modelWiring:`gateway`}}return{vercelProject:await u.pickProject(i,parent(),n,{allowCreateWhenEmpty:l.projectSelection!==`existing-only`,signal:r}),aiGateway:{kind:`inherit`},modelWiring:`gateway`}}return await l.asker.ask(select({key:`credential`,message:`How should your agent reach the model?`,options:[{id:`api-key`,value:`api-key`,label:`Use my own AI Gateway API key`,hint:`AI_GATEWAY_API_KEY`},{id:`local`,value:`local`,label:`Use my own provider API key`,hint:byokProviderEnvVar(n.modelId)}],recommended:`api-key`,required:!0}))===`api-key`?{vercelProject:{kind:`none`},aiGateway:{kind:`byok`,apiGatewayKey:await l.asker.ask(text({key:`gateway-api-key`,message:`Enter your AI_GATEWAY_API_KEY`,sensitive:!0,validate:e=>e.trim().length===0?`API key cannot be empty.`:null,required:!0}))},modelWiring:`gateway`}:{vercelProject:{kind:`none`},aiGateway:{kind:`byop`},modelWiring:`self`}}return{id:`resolve-provisioning`,async gather({state:e,signal:t}){if(l.mode.headless){let n=await plansFromFlags(e.agentName,l.mode.project,l.mode.aiGateway,t);if(n.vercelProject.kind===`none`){let t=vercelDemands(e);if(t.slack)throw Error(`Slack requires a Vercel project. Remove --skip-vercel to add Slack.`);if(t.connectSlugs.length>0)throw Error(`${connectClause(t.connectSlugs)}, which needs a Vercel project. Remove --skip-vercel to add ${t.connectSlugs.length===1?`it`:`them`}.`)}return n}return promptPlans(e,t)},async perform({input:e}){return e},apply(e,t){return{...e,vercelProject:t.vercelProject,aiGateway:t.aiGateway,modelWiring:t.modelWiring,project:t.project===void 0?e.project:mergeProjectResolution(e.project,t.project)}}}}export{resolveProvisioning};
@@ -22,6 +22,13 @@ export interface ChannelSetupChoice {
22
22
  }
23
23
  /** Optional interaction capability for a long-running setup operation. */
24
24
  export type ChannelSetupAwaitChoice = (options: ChannelSetupChoiceOptions) => ChannelSetupChoice;
25
+ /** Why a live setup indicator is waiting. */
26
+ export type SetupSpinnerIntent = {
27
+ kind: "progress";
28
+ } | {
29
+ kind: "external-action";
30
+ emphasis: string;
31
+ };
25
32
  /** Status and subprocess output operations used by shared setup flows. */
26
33
  export interface ChannelSetupLog {
27
34
  message(text: string): void;
@@ -38,7 +45,7 @@ export interface ChannelSetupLog {
38
45
  * (which have no live status surface) can omit it and callers fall back to
39
46
  * a persisted message.
40
47
  */
41
- spinner?(message: string): {
48
+ spinner?(message: string, intent?: SetupSpinnerIntent): {
42
49
  stop(): void;
43
50
  };
44
51
  }
@@ -48,4 +55,4 @@ export interface ChannelSetupLog {
48
55
  * phase message instead, keeping their progress trail; the spinner stops
49
56
  * whether the work resolves or throws.
50
57
  */
51
- export declare function withPhase<T>(log: ChannelSetupLog, message: string, task: () => Promise<T>): Promise<T>;
58
+ export declare function withPhase<T>(log: ChannelSetupLog, message: string, task: () => Promise<T>, intent?: SetupSpinnerIntent): Promise<T>;
@@ -1 +1 @@
1
- async function withPhase(e,t,n){let r=e.spinner?.(t);r||e.message(t);try{return await n()}finally{r?.stop()}}export{withPhase};
1
+ async function withPhase(e,t,n,r){let i=e.spinner?.(t,r);i||e.message(t);try{return await n()}finally{i?.stop()}}export{withPhase};
@@ -1,5 +1,5 @@
1
1
  export { type ConnectionSelectOption } from "./connection-add-prompter.js";
2
- export { type ChannelSetupAction, type ChannelSetupAwaitChoice, type ChannelSetupChoice, type ChannelSetupChoiceOptions, type ChannelSetupLog, type DisabledChannelReasons, withPhase, } from "./channel-setup-prompter.js";
2
+ export { type ChannelSetupAction, type ChannelSetupAwaitChoice, type ChannelSetupChoice, type ChannelSetupChoiceOptions, type ChannelSetupLog, type DisabledChannelReasons, type SetupSpinnerIntent, withPhase, } from "./channel-setup-prompter.js";
3
3
  export { createPromptCommandOutput, type PromptCommandLog } from "./command-output.js";
4
4
  export { runSelectComponent, SelectComponent, type SelectGuard } from "./select-component.js";
5
5
  export { createSelectOptionCodec, type SelectOptionCodec } from "./select-option-codec.js";
@@ -21,6 +21,8 @@ export interface PromptColors {
21
21
  export interface PromptOption<T extends PromptValue> {
22
22
  value: T;
23
23
  label: string;
24
+ /** Completion action kept after searchable results instead of being filtered. */
25
+ trailingAction?: boolean;
24
26
  /** Supporting copy; stacked prompts render newline-separated text on separate rows. */
25
27
  hint?: string;
26
28
  /** Short inline annotation shown dimmed only while the cursor is on this row. */
@@ -1 +1 @@
1
- import{previousGraphemeBoundary}from"#shared/text-boundaries.js";const SEARCH_ACTION_PREFIX=`\0search-action:`;function searchActionValue(e){return`${SEARCH_ACTION_PREFIX}${e}`}function searchActionQuery(e){return e.startsWith(SEARCH_ACTION_PREFIX)?e.slice(15):void 0}function submitRowIndex(e){return e.length}function filterOptions(e,t,n){let r=t.trim();if(r===``)return[...e];let i=r.toLowerCase(),a=e.filter(e=>e.label.toLowerCase().includes(i)||e.value.toLowerCase().includes(i)||(e.hint?.toLowerCase().includes(i)??!1)||(e.focusHint?.toLowerCase().includes(i)??!1));return n===void 0?a:[...a,{value:searchActionValue(r),label:n.label(r)}]}function isFocusable(e){return!e.disabled&&!e.locked}function isActionable(e){return isFocusable(e)&&!e.completed}function firstFocusableIndex(e,t){let n=e.findIndex(isFocusable);return n>=0?n:t?submitRowIndex(e):0}function stepCursor(e,t,n,r){let i=e.length+ +!!r;if(i===0)return t;let a=t;for(let t=0;t<i;t+=1){if(a=(a+n+i)%i,r&&a===submitRowIndex(e))return a;let t=e[a];if(t&&isFocusable(t))return a}return t}function reduceSelect(t,n,r){let i=r.submitRow===!0;switch(n.type){case`char`:{let e=t.filter+n.char;return{...t,filter:e,cursor:firstFocusableIndex(filterOptions(r.options,e,r.searchAction),i)}}case`backspace`:{if(t.filter.length===0)return t;let n=t.filter.slice(0,previousGraphemeBoundary(t.filter,t.filter.length));return{...t,filter:n,cursor:firstFocusableIndex(filterOptions(r.options,n,r.searchAction),i)}}case`clear`:return t.filter.length===0?t:{...t,filter:``,cursor:firstFocusableIndex(filterOptions(r.options,``,r.searchAction),i)};case`up`:case`down`:{let e=filterOptions(r.options,t.filter,r.searchAction),a=n.type===`up`?-1:1,o=stepCursor(e,t.cursor,a,i);return o===t.cursor?t:{...t,cursor:o}}case`toggle`:{let e=filterOptions(r.options,t.filter,r.searchAction)[t.cursor];if(e===void 0||!isActionable(e))return t;let n=new Set(t.selected);return n.has(e.value)?n.delete(e.value):n.add(e.value),{...t,selected:n}}}}function initialSelectState(e){let t=e.filter??``,n=filterOptions(e.options,t,e.searchAction),r=firstFocusableIndex(n,e.submitRow===!0);if(e.defaultValue!==void 0){let t=n.findIndex(t=>isFocusable(t)&&t.value===e.defaultValue);t>=0&&(r=t)}let i=e.options.filter(e=>e.locked).map(e=>e.value);return{filter:t,cursor:r,selected:new Set([...e.initialValues??[],...i])}}function selectValueAtCursor(e,t){let n=e[t];return n&&isActionable(n)?n.value:void 0}function orderedSelection(e,t){return e.filter(e=>t.has(e.value)).map(e=>e.value)}export{filterOptions,initialSelectState,orderedSelection,reduceSelect,searchActionQuery,searchActionValue,selectValueAtCursor,submitRowIndex};
1
+ import{previousGraphemeBoundary}from"#shared/text-boundaries.js";const SEARCH_ACTION_PREFIX=`\0search-action:`;function searchActionValue(e){return`${SEARCH_ACTION_PREFIX}${e}`}function searchActionQuery(e){return e.startsWith(SEARCH_ACTION_PREFIX)?e.slice(15):void 0}function submitRowIndex(e){return e.length}function filterOptions(e,t,n){let r=t.trim();if(r===``)return[...e];let i=r.toLowerCase(),a=e.filter(e=>e.trailingAction!==!0&&(e.label.toLowerCase().includes(i)||e.value.toLowerCase().includes(i)||(e.hint?.toLowerCase().includes(i)??!1)||(e.focusHint?.toLowerCase().includes(i)??!1)));return n!==void 0&&a.push({value:searchActionValue(r),label:n.label(r)}),[...a,...e.filter(e=>e.trailingAction===!0)]}function isFocusable(e){return!e.disabled&&!e.locked}function isActionable(e){return isFocusable(e)&&!e.completed}function firstFocusableIndex(e,t){let n=e.findIndex(isFocusable);return n>=0?n:t?submitRowIndex(e):0}function stepCursor(e,t,n,r){let i=e.length+ +!!r;if(i===0)return t;let a=t;for(let t=0;t<i;t+=1){if(a=(a+n+i)%i,r&&a===submitRowIndex(e))return a;let t=e[a];if(t&&isFocusable(t))return a}return t}function reduceSelect(t,n,r){let i=r.submitRow===!0;switch(n.type){case`char`:{let e=t.filter+n.char;return{...t,filter:e,cursor:firstFocusableIndex(filterOptions(r.options,e,r.searchAction),i)}}case`backspace`:{if(t.filter.length===0)return t;let n=t.filter.slice(0,previousGraphemeBoundary(t.filter,t.filter.length));return{...t,filter:n,cursor:firstFocusableIndex(filterOptions(r.options,n,r.searchAction),i)}}case`clear`:return t.filter.length===0?t:{...t,filter:``,cursor:firstFocusableIndex(filterOptions(r.options,``,r.searchAction),i)};case`up`:case`down`:{let e=filterOptions(r.options,t.filter,r.searchAction),a=n.type===`up`?-1:1,o=stepCursor(e,t.cursor,a,i);return o===t.cursor?t:{...t,cursor:o}}case`toggle`:{let e=filterOptions(r.options,t.filter,r.searchAction)[t.cursor];if(e===void 0||!isActionable(e))return t;let n=new Set(t.selected);return n.has(e.value)?n.delete(e.value):n.add(e.value),{...t,selected:n}}}}function initialSelectState(e){let t=e.filter??``,n=filterOptions(e.options,t,e.searchAction),r=firstFocusableIndex(n,e.submitRow===!0);if(e.defaultValue!==void 0){let t=n.findIndex(t=>isFocusable(t)&&t.value===e.defaultValue);t>=0&&(r=t)}let i=e.options.filter(e=>e.locked).map(e=>e.value);return{filter:t,cursor:r,selected:new Set([...e.initialValues??[],...i])}}function selectValueAtCursor(e,t){let n=e[t];return n&&isActionable(n)?n.value:void 0}function orderedSelection(e,t){return e.filter(e=>t.has(e.value)).map(e=>e.value)}export{filterOptions,initialSelectState,orderedSelection,reduceSelect,searchActionQuery,searchActionValue,selectValueAtCursor,submitRowIndex};