eve 0.24.5 → 0.24.6

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # eve
2
2
 
3
+ ## 0.24.6
4
+
5
+ ### Patch Changes
6
+
7
+ - 3029647: Update the generated Web Chat template for Next.js 16.3 preview type declarations.
8
+ - b97f1d1: Custom channel routes can now cancel a session's in-flight turn: route handlers receive a `cancel({ continuationToken, turnId? })` helper addressed by the channel-local continuation token, and `Session` handles returned by `send()` and `getSession()` expose `cancel({ turnId? })` for session-id-addressed cancellation. `ClientSession.cancel()` accepts the same optional `turnId` stale-request guard.
9
+
3
10
  ## 0.24.5
4
11
 
5
12
  ### Patch Changes
@@ -0,0 +1,8 @@
1
+ import type { CancelFn } from "#channel/routes.js";
2
+ import type { Runtime } from "#channel/types.js";
3
+ /**
4
+ * Builds the route-handler `cancel` helper for one channel. Resolves the
5
+ * channel-local continuation token to its owning session without delivering
6
+ * input, then delegates to the runtime's session-id-addressed cancellation.
7
+ */
8
+ export declare function createCancelFn(runtime: Runtime, channelName: string): CancelFn;
@@ -0,0 +1 @@
1
+ function createCancelFn(e,t){return async n=>{let r=`${t}:${n.continuationToken}`,i=await e.resolveSession(r);return i===void 0?{status:`no_active_turn`}:await e.cancelTurn({sessionId:i.sessionId,turnId:n.turnId})}}export{createCancelFn};
@@ -1,6 +1,6 @@
1
1
  import type { UserContent } from "ai";
2
2
  import type { CrossChannelReceiveFn } from "#channel/cross-channel-receive.js";
3
- import type { SessionAuthContext, SessionCallback } from "#channel/types.js";
3
+ import type { CancelTurnResult, SessionAuthContext, SessionCallback } from "#channel/types.js";
4
4
  import type { InputResponse } from "#runtime/input/types.js";
5
5
  import type { Session } from "#channel/session.js";
6
6
  import type { RunMode } from "#shared/run-mode.js";
@@ -9,13 +9,15 @@ import type { ChannelMethod } from "#public/definitions/channel.js";
9
9
  type WebSocketHeaders = Headers | readonly (readonly [string, string])[] | Record<string, string>;
10
10
  /**
11
11
  * Second argument passed to every route handler. `send` starts or continues a
12
- * session on this channel; `getSession` looks one up by id; `receive` hands
13
- * inbound work to a different channel; `params` contains the matched path
14
- * parameters; `waitUntil` keeps background work alive past the response;
12
+ * session on this channel; `cancel` stops the active turn on a session
13
+ * addressed by continuation token; `getSession` looks one up by id; `receive`
14
+ * hands inbound work to a different channel; `params` contains the matched
15
+ * path parameters; `waitUntil` keeps background work alive past the response;
15
16
  * `requestIp` is the client IP, or `null` when the host cannot provide it.
16
17
  */
17
18
  export interface RouteHandlerArgs<TState = undefined> {
18
19
  send: SendFn<TState>;
20
+ cancel: CancelFn;
19
21
  getSession: GetSessionFn;
20
22
  /**
21
23
  * Starts a session on a different channel to hand off inbound work (e.g. an
@@ -78,6 +80,25 @@ export type SendOptions<TState = undefined> = [TState] extends [undefined] ? Bas
78
80
  * stream from within a route handler.
79
81
  */
80
82
  export type GetSessionFn = (sessionId: string) => Session;
83
+ /**
84
+ * Options for {@link CancelFn}. `continuationToken` is the channel-local raw
85
+ * token, exactly as passed to {@link SendFn}. `turnId` limits the request to
86
+ * the turn the caller observed; a stale guard is consumed as a benign no-op.
87
+ */
88
+ export interface CancelOptions {
89
+ readonly continuationToken: string;
90
+ readonly turnId?: string;
91
+ }
92
+ /**
93
+ * Requests cancellation of the active turn on the session that owns the
94
+ * continuation token. Never starts a session, sends input, or clears history.
95
+ *
96
+ * Both statuses are successful: `"accepted"` means the request was consumed,
97
+ * and `"no_active_turn"` covers an unknown token and a session with nothing
98
+ * to cancel. Confirmation is `turn.cancelled` followed by `session.waiting`
99
+ * on the event stream.
100
+ */
101
+ export type CancelFn = (options: CancelOptions) => Promise<CancelTurnResult>;
81
102
  export type RouteHandler<TState = undefined> = (req: Request, args: RouteHandlerArgs<TState>) => Promise<Response>;
82
103
  /**
83
104
  * A connected WebSocket peer passed to every {@link WebSocketRouteHooks}
@@ -1,6 +1,6 @@
1
1
  import type { ContextAccessor } from "#context/key.js";
2
2
  import type { HandleMessageStreamEvent } from "#protocol/message.js";
3
- import type { Runtime } from "#channel/types.js";
3
+ import type { CancelTurnResult, Runtime } from "#channel/types.js";
4
4
  import type { SessionAuth } from "#context/keys.js";
5
5
  /**
6
6
  * Result of starting or delivering to a session. Exposes the session
@@ -14,6 +14,15 @@ import type { SessionAuth } from "#context/keys.js";
14
14
  export interface Session {
15
15
  readonly id: string;
16
16
  readonly continuationToken: string;
17
+ /**
18
+ * Requests cancellation of this session's in-flight turn. `turnId` limits
19
+ * the request to the turn the caller observed. Both statuses are
20
+ * successful; confirmation is `turn.cancelled` followed by
21
+ * `session.waiting` on the event stream.
22
+ */
23
+ cancel(options?: {
24
+ turnId?: string;
25
+ }): Promise<CancelTurnResult>;
17
26
  /**
18
27
  * Opens the durable event stream. Negative start indexes read relative to
19
28
  * the current tail (`-1` starts at the latest event).
@@ -1 +1 @@
1
- import{AuthKey,ContinuationTokenKey,InitiatorAuthKey,SessionIdKey}from"#context/keys.js";function createSession(e,t,n){return{id:e,continuationToken:t,async getEventStream(t){return n.getEventStream(e,t)}}}function createGetSessionFn(e){return t=>createSession(t,``,e)}function buildSessionHandle(i){return{get id(){return i.get(SessionIdKey)??``},get continuationToken(){return i.get(ContinuationTokenKey)??``},get auth(){return{current:i.get(AuthKey)??null,initiator:i.get(InitiatorAuthKey)??null}},setContinuationToken(e){let n=i.get(ContinuationTokenKey)??``,r=namespaceContinuationToken(n,e);n!==r&&i.set(ContinuationTokenKey,r)}}}function namespaceContinuationToken(e,t){let n=e.indexOf(`:`);if(n<=0)throw Error(`Cannot set session continuation token without an existing namespaced continuation token. Start the session with a placeholder continuationToken.`);return`${e.slice(0,n+1)}${t}`}export{buildSessionHandle,createGetSessionFn,createSession};
1
+ import{AuthKey,ContinuationTokenKey,InitiatorAuthKey,SessionIdKey}from"#context/keys.js";function createSession(e,t,n){return{id:e,continuationToken:t,async cancel(t){return n.cancelTurn({sessionId:e,turnId:t?.turnId})},async getEventStream(t){return n.getEventStream(e,t)}}}function createGetSessionFn(e){return t=>createSession(t,``,e)}function buildSessionHandle(i){return{get id(){return i.get(SessionIdKey)??``},get continuationToken(){return i.get(ContinuationTokenKey)??``},get auth(){return{current:i.get(AuthKey)??null,initiator:i.get(InitiatorAuthKey)??null}},setContinuationToken(e){let n=i.get(ContinuationTokenKey)??``,r=namespaceContinuationToken(n,e);n!==r&&i.set(ContinuationTokenKey,r)}}}function namespaceContinuationToken(e,t){let n=e.indexOf(`:`);if(n<=0)throw Error(`Cannot set session continuation token without an existing namespaced continuation token. Start the session with a placeholder continuationToken.`);return`${e.slice(0,n+1)}${t}`}export{buildSessionHandle,createGetSessionFn,createSession};
@@ -333,6 +333,14 @@ export interface Runtime {
333
333
  deliver(input: DeliverInput): Promise<{
334
334
  sessionId: string;
335
335
  }>;
336
+ /**
337
+ * Resolves the session that currently owns a continuation token without
338
+ * delivering input or starting a run. Returns `undefined` when no session
339
+ * owns the token.
340
+ */
341
+ resolveSession(continuationToken: string): Promise<{
342
+ sessionId: string;
343
+ } | undefined>;
336
344
  /**
337
345
  * Returns a readable stream of lifecycle events for an existing session.
338
346
  *
@@ -616,14 +616,16 @@ var ClientSession = class {
616
616
  sessionId
617
617
  });
618
618
  }
619
- async cancel() {
619
+ async cancel(options) {
620
620
  const sessionId = this.#state.sessionId;
621
621
  if (!sessionId) throw new Error("Session has no session ID. Send a message first.");
622
622
  const url = createClientUrl(this.#context.host, createEveCancelTurnRoutePath(sessionId));
623
623
  const headers = await this.#context.resolveHeaders();
624
+ headers.set("content-type", "application/json");
624
625
  const response = await fetch(url, withRedirectPolicy$1({
625
626
  headers,
626
- method: "POST"
627
+ method: "POST",
628
+ body: options ? JSON.stringify(options) : void 0
627
629
  }, this.#context.redirect));
628
630
  const body = await response.text();
629
631
  if (!response.ok) throw new ClientError(response.status, body, response.headers);
@@ -616,14 +616,16 @@ var ClientSession = class {
616
616
  sessionId
617
617
  });
618
618
  }
619
- async cancel() {
619
+ async cancel(options) {
620
620
  const sessionId = this.#state.sessionId;
621
621
  if (!sessionId) throw new Error("Session has no session ID. Send a message first.");
622
622
  const url = createClientUrl(this.#context.host, createEveCancelTurnRoutePath(sessionId));
623
623
  const headers = await this.#context.resolveHeaders();
624
+ headers.set("content-type", "application/json");
624
625
  const response = await fetch(url, withRedirectPolicy$1({
625
626
  headers,
626
- method: "POST"
627
+ method: "POST",
628
+ body: options ? JSON.stringify(options) : void 0
627
629
  }, this.#context.redirect));
628
630
  const body = await response.text();
629
631
  if (!response.ok) throw new ClientError(response.status, body, response.headers);
@@ -42,12 +42,16 @@ export declare class ClientSession {
42
42
  *
43
43
  * Both `accepted` and `no_active_turn` are successful outcomes. The latter
44
44
  * means the active turn settled before the request arrived or the session is
45
- * already parked. Credentials are resolved immediately before the request.
45
+ * already parked. `turnId` limits the request to the turn the caller
46
+ * observed; a stale guard is consumed as a benign no-op. Credentials are
47
+ * resolved immediately before the request.
46
48
  *
47
49
  * @throws {Error} If this handle has not started or attached to a session.
48
50
  * @throws {ClientError} If the cancel route returns a non-successful status.
49
51
  */
50
- cancel(): Promise<CancelSessionResult>;
52
+ cancel(options?: {
53
+ turnId?: string;
54
+ }): Promise<CancelSessionResult>;
51
55
  /**
52
56
  * Opens this session's event stream for the current session ID.
53
57
  *
@@ -1 +1 @@
1
- import{EVE_CREATE_SESSION_ROUTE_PATH,createEveCancelTurnRoutePath,createEveContinueSessionRoutePath}from"#protocol/routes.js";import{ClientError}from"#client/client-error.js";import{advanceSession}from"#client/session-utils.js";import{createClientUrl}from"#client/url.js";import{MessageResponse}from"#client/message-response.js";import{EVE_SESSION_ID_HEADER,isCurrentTurnBoundaryEvent}from"#protocol/message.js";import{normalizeOutputSchemaForRequest}from"#client/output-schema.js";import{isStreamDisconnectError,readNdjsonStream}from"#client/ndjson.js";import{CancelTurnResponseSchema}from"#protocol/cancel-turn.js";import{openStreamBody,openStreamIterable}from"#client/open-stream.js";var ClientSession=class{#e;#t;constructor(e,t){this.#e=e,this.#t=t}get state(){return this.#t}async send(e){let t=normalizeSendTurnInput(e),n=this.#t,{continuationToken:r,sessionId:i}=await this.#n(t,n);return this.#t===n&&(this.#t={...n,sessionId:i}),new MessageResponse({continuationToken:r,createStream:()=>this.#r(i,r,n,t),sessionId:i})}async cancel(){let e=this.#t.sessionId;if(!e)throw Error(`Session has no session ID. Send a message first.`);let n=createClientUrl(this.#e.host,createEveCancelTurnRoutePath(e)),i=await this.#e.resolveHeaders(),o=await fetch(n,withRedirectPolicy({headers:i,method:`POST`},this.#e.redirect)),s=await o.text();if(!o.ok)throw new ClientError(o.status,s,o.headers);let c;try{c=JSON.parse(s)}catch{throw Error(`Cancel route returned invalid JSON (${o.status}).`)}let l=CancelTurnResponseSchema.safeParse(c);if(!l.success||l.data.sessionId!==e)throw Error(`Cancel route returned an invalid response (${o.status}).`);return{sessionId:l.data.sessionId,status:l.data.status}}stream(e){let t=this.#t.sessionId;if(!t)throw Error(`Session has no session ID. Send a message first.`);return this.#a(t,e)}async#n(t,r){let i=r.sessionId?createEveContinueSessionRoutePath(r.sessionId):EVE_CREATE_SESSION_ROUTE_PATH,o=createClientUrl(this.#e.host,i),c=await this.#e.resolveHeaders(t.headers);c.set(`content-type`,`application/json`);let u=createHandleMessageBody({input:t,outputSchema:normalizeOutputSchemaForRequest(t.outputSchema),session:r});if(u===null)throw Error(`Session.send requires a non-empty message, inputResponses, or both.`);let d=await postTurnWithRetry({body:JSON.stringify(u),headers:c,mustDeliver:(t.inputResponses?.length??0)>0,redirect:this.#e.redirect,signal:t.signal,url:o}),f=await d.json(),p=(typeof f.sessionId==`string`?f.sessionId:void 0)??d.headers.get(EVE_SESSION_ID_HEADER)?.trim()??r.sessionId;if(!p)throw Error(`Message route did not return a session id.`);return{continuationToken:typeof f.continuationToken==`string`?f.continuationToken:void 0,sessionId:p}}async*#r(e,t,n,r){let a=[];try{let t=n.sessionId===e?n.streamIndex:0,i=this.#e.maxReconnectAttempts;for(;;){let n=await this.#i(e,t,r.signal,r.headers),o=!1;try{for await(let e of readNdjsonStream(n))if(a.push(e),t+=1,yield e,isCurrentTurnBoundaryEvent(e)){o=!0;break}}catch(e){if(!isStreamDisconnectError(e))throw e}if(o||r.signal?.aborted||i<=0)break;--i}}finally{this.#t=advanceSession({continuationToken:t,events:a,preserveCompletedSessions:this.#e.preserveCompletedSessions,sessionId:e,session:n})}}async#i(e,t,n,r){return await openStreamBody({host:this.#e.host,resolveHeaders:()=>this.#e.resolveHeaders(r),redirect:this.#e.redirect,sessionId:e,signal:n,startIndex:t})}async*#a(e,t){let n=this.#t,r=t?.startIndex??n.streamIndex,a=[];try{for await(let n of openStreamIterable({host:this.#e.host,maxReconnectAttempts:this.#e.maxReconnectAttempts,resolveHeaders:()=>this.#e.resolveHeaders(),redirect:this.#e.redirect,sessionId:e,signal:t?.signal,startIndex:r}))a.push(n),yield n}finally{r>=0&&(this.#t=advanceSession({continuationToken:n.continuationToken,events:a,preserveCompletedSessions:this.#e.preserveCompletedSessions,session:{...n,sessionId:e,streamIndex:r},sessionId:e}))}}};async function postTurnWithRetry(e){let t=e.mustDeliver?10:1,n,i,a;for(let o=0;o<t;o+=1){let s=await fetch(e.url,{body:e.body,headers:e.headers,method:`POST`,redirect:e.redirect,signal:e.signal??null});if(s.ok)return s;if(n=s.status,i=await s.text(),a=s.headers,!isRetryableDeliveryFailure(s.status,i))throw new ClientError(s.status,i,s.headers);o<t-1&&await sleep(200)}throw new ClientError(n??0,i??`Failed to deliver session turn.`,a)}function isRetryableDeliveryFailure(e,t){return e===500&&/target session was not found/i.test(t)}async function sleep(e){await new Promise(t=>setTimeout(t,e))}function normalizeSendTurnInput(e){return typeof e==`string`?{message:e}:e}function createHandleMessageBody(e){let t={};return e.input.message!==void 0&&(t.message=e.input.message),e.input.inputResponses!==void 0&&e.input.inputResponses.length>0&&(t.inputResponses=e.input.inputResponses),e.input.clientContext!==void 0&&(t.clientContext=e.input.clientContext),e.outputSchema!==void 0&&(t.outputSchema=e.outputSchema),e.session.continuationToken!==void 0&&(t.continuationToken=e.session.continuationToken),Object.keys(t).length===0||e.session.continuationToken===void 0&&t.message===void 0||e.session.continuationToken!==void 0&&t.message===void 0&&t.inputResponses===void 0?null:t}function withRedirectPolicy(e,t){return t===void 0?e:{...e,redirect:t}}export{ClientSession};
1
+ import{EVE_CREATE_SESSION_ROUTE_PATH,createEveCancelTurnRoutePath,createEveContinueSessionRoutePath}from"#protocol/routes.js";import{ClientError}from"#client/client-error.js";import{advanceSession}from"#client/session-utils.js";import{createClientUrl}from"#client/url.js";import{MessageResponse}from"#client/message-response.js";import{EVE_SESSION_ID_HEADER,isCurrentTurnBoundaryEvent}from"#protocol/message.js";import{normalizeOutputSchemaForRequest}from"#client/output-schema.js";import{isStreamDisconnectError,readNdjsonStream}from"#client/ndjson.js";import{CancelTurnResponseSchema}from"#protocol/cancel-turn.js";import{openStreamBody,openStreamIterable}from"#client/open-stream.js";var ClientSession=class{#e;#t;constructor(e,t){this.#e=e,this.#t=t}get state(){return this.#t}async send(e){let t=normalizeSendTurnInput(e),n=this.#t,{continuationToken:r,sessionId:i}=await this.#n(t,n);return this.#t===n&&(this.#t={...n,sessionId:i}),new MessageResponse({continuationToken:r,createStream:()=>this.#r(i,r,n,t),sessionId:i})}async cancel(e){let n=this.#t.sessionId;if(!n)throw Error(`Session has no session ID. Send a message first.`);let i=createClientUrl(this.#e.host,createEveCancelTurnRoutePath(n)),o=await this.#e.resolveHeaders();o.set(`content-type`,`application/json`);let s=await fetch(i,withRedirectPolicy({headers:o,method:`POST`,body:e?JSON.stringify(e):void 0},this.#e.redirect)),c=await s.text();if(!s.ok)throw new ClientError(s.status,c,s.headers);let l;try{l=JSON.parse(c)}catch{throw Error(`Cancel route returned invalid JSON (${s.status}).`)}let u=CancelTurnResponseSchema.safeParse(l);if(!u.success||u.data.sessionId!==n)throw Error(`Cancel route returned an invalid response (${s.status}).`);return{sessionId:u.data.sessionId,status:u.data.status}}stream(e){let t=this.#t.sessionId;if(!t)throw Error(`Session has no session ID. Send a message first.`);return this.#a(t,e)}async#n(t,r){let i=r.sessionId?createEveContinueSessionRoutePath(r.sessionId):EVE_CREATE_SESSION_ROUTE_PATH,o=createClientUrl(this.#e.host,i),c=await this.#e.resolveHeaders(t.headers);c.set(`content-type`,`application/json`);let u=createHandleMessageBody({input:t,outputSchema:normalizeOutputSchemaForRequest(t.outputSchema),session:r});if(u===null)throw Error(`Session.send requires a non-empty message, inputResponses, or both.`);let d=await postTurnWithRetry({body:JSON.stringify(u),headers:c,mustDeliver:(t.inputResponses?.length??0)>0,redirect:this.#e.redirect,signal:t.signal,url:o}),f=await d.json(),p=(typeof f.sessionId==`string`?f.sessionId:void 0)??d.headers.get(EVE_SESSION_ID_HEADER)?.trim()??r.sessionId;if(!p)throw Error(`Message route did not return a session id.`);return{continuationToken:typeof f.continuationToken==`string`?f.continuationToken:void 0,sessionId:p}}async*#r(e,t,n,r){let a=[];try{let t=n.sessionId===e?n.streamIndex:0,i=this.#e.maxReconnectAttempts;for(;;){let n=await this.#i(e,t,r.signal,r.headers),o=!1;try{for await(let e of readNdjsonStream(n))if(a.push(e),t+=1,yield e,isCurrentTurnBoundaryEvent(e)){o=!0;break}}catch(e){if(!isStreamDisconnectError(e))throw e}if(o||r.signal?.aborted||i<=0)break;--i}}finally{this.#t=advanceSession({continuationToken:t,events:a,preserveCompletedSessions:this.#e.preserveCompletedSessions,sessionId:e,session:n})}}async#i(e,t,n,r){return await openStreamBody({host:this.#e.host,resolveHeaders:()=>this.#e.resolveHeaders(r),redirect:this.#e.redirect,sessionId:e,signal:n,startIndex:t})}async*#a(e,t){let n=this.#t,r=t?.startIndex??n.streamIndex,a=[];try{for await(let n of openStreamIterable({host:this.#e.host,maxReconnectAttempts:this.#e.maxReconnectAttempts,resolveHeaders:()=>this.#e.resolveHeaders(),redirect:this.#e.redirect,sessionId:e,signal:t?.signal,startIndex:r}))a.push(n),yield n}finally{r>=0&&(this.#t=advanceSession({continuationToken:n.continuationToken,events:a,preserveCompletedSessions:this.#e.preserveCompletedSessions,session:{...n,sessionId:e,streamIndex:r},sessionId:e}))}}};async function postTurnWithRetry(e){let t=e.mustDeliver?10:1,n,i,a;for(let o=0;o<t;o+=1){let s=await fetch(e.url,{body:e.body,headers:e.headers,method:`POST`,redirect:e.redirect,signal:e.signal??null});if(s.ok)return s;if(n=s.status,i=await s.text(),a=s.headers,!isRetryableDeliveryFailure(s.status,i))throw new ClientError(s.status,i,s.headers);o<t-1&&await sleep(200)}throw new ClientError(n??0,i??`Failed to deliver session turn.`,a)}function isRetryableDeliveryFailure(e,t){return e===500&&/target session was not found/i.test(t)}async function sleep(e){await new Promise(t=>setTimeout(t,e))}function normalizeSendTurnInput(e){return typeof e==`string`?{message:e}:e}function createHandleMessageBody(e){let t={};return e.input.message!==void 0&&(t.message=e.input.message),e.input.inputResponses!==void 0&&e.input.inputResponses.length>0&&(t.inputResponses=e.input.inputResponses),e.input.clientContext!==void 0&&(t.clientContext=e.input.clientContext),e.outputSchema!==void 0&&(t.outputSchema=e.outputSchema),e.session.continuationToken!==void 0&&(t.continuationToken=e.session.continuationToken),Object.keys(t).length===0||e.session.continuationToken===void 0&&t.message===void 0||e.session.continuationToken!==void 0&&t.message===void 0&&t.inputResponses===void 0?null:t}function withRedirectPolicy(e,t){return t===void 0?e:{...e,redirect:t}}export{ClientSession};
@@ -1 +1 @@
1
- import{createLogger,logError}from"#internal/logging.js";import{RuntimeNoActiveSessionError}from"#execution/runtime-errors.js";import{resolveInstalledPackageInfo}from"#internal/application/package.js";import{serializeContext}from"#context/serialize.js";import{getCompiledRuntimeAgentBundle}from"#runtime/sessions/compiled-agent-cache.js";import{getRun,resumeHook,start}from"#internal/workflow/runtime.js";import{ROOT_RUNTIME_AGENT_NODE_ID}from"#runtime/graph.js";import{sessionCancelHookToken}from"#execution/turn-cancellation-token.js";import{buildSessionAttributes,buildSubagentRootAttributes,readParentLineage}from"#execution/eve-workflow-attributes.js";import{EntityConflictError,HookNotFoundError,RunExpiredError,WorkflowRunNotFoundError}from"#compiled/@workflow/errors/index.js";import{isEveDevEnvironment}from"#internal/application/dev-environment.js";import{normalizeEveAttributes}from"#runtime/attributes/normalize.js";import{buildRunContext}from"#execution/runtime-context.js";import{parseNdjsonStream}from"#execution/ndjson-stream.js";const WORKFLOW_ENTRY_NAME=`workflowEntry`,TURN_WORKFLOW_NAME=`turnWorkflow`,EVE_PACKAGE_INFO=resolveInstalledPackageInfo(),LATEST_DEPLOYMENT_UNSUPPORTED_MESSAGE=`deploymentId 'latest' requires a World that implements resolveLatestDeploymentId()`,STABLE_WORKFLOW_NAMES=new Set([WORKFLOW_ENTRY_NAME,TURN_WORKFLOW_NAME]),STABLE_ID_BASE=EVE_PACKAGE_INFO.name,log=createLogger(`execution.workflow-runtime`),workflowEntryReference={workflowId:`workflow//${STABLE_ID_BASE}//${WORKFLOW_ENTRY_NAME}`},turnWorkflowReference={workflowId:`workflow//${STABLE_ID_BASE}//${TURN_WORKFLOW_NAME}`};function createWorkflowRuntime(e){return{async run(n){let r=await getCompiledRuntimeAgentBundle({compiledArtifactsSource:e.compiledArtifactsSource,nodeId:e.nodeId}),i=serializeContext(buildRunContext({bundle:r,run:n})),a=readParentLineage(i),o=a.sessionId===void 0?buildSessionAttributes({inputMessage:n.title??n.input.message,serializedContext:i}):buildSubagentRootAttributes({identity:{nodeId:r.nodeId??ROOT_RUNTIME_AGENT_NODE_ID},parentCallId:a.callId,parentSessionId:a.sessionId,parentTurnId:a.turnId,rootSessionId:a.rootSessionId??a.sessionId,serializedContext:i}),s;try{s=await startWorkflowPreferLatest(workflowEntryReference,[{input:n.input,limits:n.limits,serializedContext:i}],{allowReservedAttributes:!0,attributes:normalizeEveAttributes(o)})}catch(e){throw logError(log,`failed to start workflow run`,e,{continuationToken:n.continuationToken}),e}let c,getEvents=()=>(c??=parseNdjsonStream(()=>getRun(s.runId).getReadable()),c);return{continuationToken:n.continuationToken??s.runId,get events(){return getEvents()},sessionId:s.runId}},async cancelTurn(e){return await requestWorkflowTurnCancellation(e)},async deliver(e){let r={auth:e.auth,kind:`deliver`,payloads:[e.payload],requestId:e.requestId};try{return{sessionId:normalizeWorkflowHook(await resumeHook(e.continuationToken,r)).runId}}catch(r){throw HookNotFoundError.is(r)?new RuntimeNoActiveSessionError(e.continuationToken):(logError(log,`failed to deliver to active session`,r,{continuationToken:e.continuationToken}),r)}},async getEventStream(e,t){return parseNdjsonStream(()=>getRun(e).getReadable({startIndex:t?.startIndex}))}}}async function requestWorkflowTurnCancellation(e){let t=e.turnId===void 0?{}:{turnId:e.turnId};try{return await resumeHook(sessionCancelHookToken(e.sessionId),t),{status:`accepted`}}catch(e){if(isInactiveCancelTarget(e))return{status:`no_active_turn`};throw e}}function isInactiveCancelTarget(e){return HookNotFoundError.is(e)||WorkflowRunNotFoundError.is(e)||RunExpiredError.is(e)||EntityConflictError.is(e)}async function startWorkflowPreferLatest(e,t,n){if(!shouldRouteToLatestDeployment())return n===void 0?await start(e,t):await start(e,t,n);try{return await start(e,t,{...n,deploymentId:`latest`})}catch(r){if(!isLatestDeploymentUnsupportedError(r))throw r;return n===void 0?await start(e,t):await start(e,t,n)}}function shouldRouteToLatestDeployment(){return process.env.VERCEL_ENV===`production`||isEveDevEnvironment()}function isLatestDeploymentUnsupportedError(e){return e instanceof Error&&e.message.includes(`deploymentId 'latest' requires a World that implements resolveLatestDeploymentId()`)}function normalizeWorkflowHook(e){if(typeof e!=`object`||!e||!(`runId`in e))throw Error(`Workflow hook did not include a run id.`);let t=e.runId;if(typeof t!=`string`||t.length===0)throw Error(`Workflow hook did not include a run id.`);return{runId:t}}export{LATEST_DEPLOYMENT_UNSUPPORTED_MESSAGE,STABLE_WORKFLOW_NAMES,createWorkflowRuntime,requestWorkflowTurnCancellation,startWorkflowPreferLatest,turnWorkflowReference,workflowEntryReference};
1
+ import{createLogger,logError}from"#internal/logging.js";import{RuntimeNoActiveSessionError}from"#execution/runtime-errors.js";import{resolveInstalledPackageInfo}from"#internal/application/package.js";import{serializeContext}from"#context/serialize.js";import{getCompiledRuntimeAgentBundle}from"#runtime/sessions/compiled-agent-cache.js";import{getHookByToken,getRun,resumeHook,start}from"#internal/workflow/runtime.js";import{ROOT_RUNTIME_AGENT_NODE_ID}from"#runtime/graph.js";import{sessionCancelHookToken}from"#execution/turn-cancellation-token.js";import{buildSessionAttributes,buildSubagentRootAttributes,readParentLineage}from"#execution/eve-workflow-attributes.js";import{EntityConflictError,HookNotFoundError,RunExpiredError,WorkflowRunNotFoundError}from"#compiled/@workflow/errors/index.js";import{isEveDevEnvironment}from"#internal/application/dev-environment.js";import{normalizeEveAttributes}from"#runtime/attributes/normalize.js";import{buildRunContext}from"#execution/runtime-context.js";import{parseNdjsonStream}from"#execution/ndjson-stream.js";const WORKFLOW_ENTRY_NAME=`workflowEntry`,TURN_WORKFLOW_NAME=`turnWorkflow`,EVE_PACKAGE_INFO=resolveInstalledPackageInfo(),LATEST_DEPLOYMENT_UNSUPPORTED_MESSAGE=`deploymentId 'latest' requires a World that implements resolveLatestDeploymentId()`,STABLE_WORKFLOW_NAMES=new Set([WORKFLOW_ENTRY_NAME,TURN_WORKFLOW_NAME]),STABLE_ID_BASE=EVE_PACKAGE_INFO.name,log=createLogger(`execution.workflow-runtime`),workflowEntryReference={workflowId:`workflow//${STABLE_ID_BASE}//${WORKFLOW_ENTRY_NAME}`},turnWorkflowReference={workflowId:`workflow//${STABLE_ID_BASE}//${TURN_WORKFLOW_NAME}`};function createWorkflowRuntime(e){return{async run(n){let r=await getCompiledRuntimeAgentBundle({compiledArtifactsSource:e.compiledArtifactsSource,nodeId:e.nodeId}),i=serializeContext(buildRunContext({bundle:r,run:n})),a=readParentLineage(i),o=a.sessionId===void 0?buildSessionAttributes({inputMessage:n.title??n.input.message,serializedContext:i}):buildSubagentRootAttributes({identity:{nodeId:r.nodeId??ROOT_RUNTIME_AGENT_NODE_ID},parentCallId:a.callId,parentSessionId:a.sessionId,parentTurnId:a.turnId,rootSessionId:a.rootSessionId??a.sessionId,serializedContext:i}),s;try{s=await startWorkflowPreferLatest(workflowEntryReference,[{input:n.input,limits:n.limits,serializedContext:i}],{allowReservedAttributes:!0,attributes:normalizeEveAttributes(o)})}catch(e){throw logError(log,`failed to start workflow run`,e,{continuationToken:n.continuationToken}),e}let c,getEvents=()=>(c??=parseNdjsonStream(()=>getRun(s.runId).getReadable()),c);return{continuationToken:n.continuationToken??s.runId,get events(){return getEvents()},sessionId:s.runId}},async cancelTurn(e){return await requestWorkflowTurnCancellation(e)},async deliver(e){let r={auth:e.auth,kind:`deliver`,payloads:[e.payload],requestId:e.requestId};try{return{sessionId:normalizeWorkflowHook(await resumeHook(e.continuationToken,r)).runId}}catch(r){throw HookNotFoundError.is(r)?new RuntimeNoActiveSessionError(e.continuationToken):(logError(log,`failed to deliver to active session`,r,{continuationToken:e.continuationToken}),r)}},async getEventStream(e,t){return parseNdjsonStream(()=>getRun(e).getReadable({startIndex:t?.startIndex}))},async resolveSession(e){try{return{sessionId:(await getHookByToken(e)).runId}}catch(n){if(HookNotFoundError.is(n))return;throw logError(log,`failed to resolve session by continuation token`,n,{continuationToken:e}),n}}}}async function requestWorkflowTurnCancellation(e){let t=e.turnId===void 0?{}:{turnId:e.turnId};try{return await resumeHook(sessionCancelHookToken(e.sessionId),t),{status:`accepted`}}catch(e){if(isInactiveCancelTarget(e))return{status:`no_active_turn`};throw e}}function isInactiveCancelTarget(e){return HookNotFoundError.is(e)||WorkflowRunNotFoundError.is(e)||RunExpiredError.is(e)||EntityConflictError.is(e)}async function startWorkflowPreferLatest(e,t,n){if(!shouldRouteToLatestDeployment())return n===void 0?await start(e,t):await start(e,t,n);try{return await start(e,t,{...n,deploymentId:`latest`})}catch(r){if(!isLatestDeploymentUnsupportedError(r))throw r;return n===void 0?await start(e,t):await start(e,t,n)}}function shouldRouteToLatestDeployment(){return process.env.VERCEL_ENV===`production`||isEveDevEnvironment()}function isLatestDeploymentUnsupportedError(e){return e instanceof Error&&e.message.includes(`deploymentId 'latest' requires a World that implements resolveLatestDeploymentId()`)}function normalizeWorkflowHook(e){if(typeof e!=`object`||!e||!(`runId`in e))throw Error(`Workflow hook did not include a run id.`);let t=e.runId;if(typeof t!=`string`||t.length===0)throw Error(`Workflow hook did not include a run id.`);return{runId:t}}export{LATEST_DEPLOYMENT_UNSUPPORTED_MESSAGE,STABLE_WORKFLOW_NAMES,createWorkflowRuntime,requestWorkflowTurnCancellation,startWorkflowPreferLatest,turnWorkflowReference,workflowEntryReference};
@@ -1 +1 @@
1
- import{createRequire}from"node:module";import{existsSync,readFileSync,realpathSync}from"node:fs";import{basename,dirname,join}from"node:path";import{EVE_PACKAGE_NAME}from"#internal/package-name.js";import{fileURLToPath}from"node:url";let cachedPackageInfo;const BUNDLED_FALLBACK_PACKAGE_VERSION=`0.24.5`,WORKFLOW_MODULE_ALIASES={"workflow/errors":`src/compiled/@workflow/errors/index.js`,"workflow/internal/private":`src/compiled/@workflow/core/private.js`};function resolveFallbackPackageVersion(){return BUNDLED_FALLBACK_PACKAGE_VERSION.startsWith(`__`)?`0.0.0`:BUNDLED_FALLBACK_PACKAGE_VERSION}const FALLBACK_PACKAGE_INFO={name:EVE_PACKAGE_NAME,version:resolveFallbackPackageVersion()};function resolveCurrentModulePath(){return typeof __filename==`string`?__filename:resolveCurrentModulePathFromStack()}function resolveCurrentModulePathFromStack(){let e=Error.prepareStackTrace;try{Error.prepareStackTrace=(e,t)=>t;let e=Error().stack?.[0]?.getFileName();if(typeof e!=`string`||e.length===0)throw Error(`Failed to resolve the current module path from the stack trace.`);return e.startsWith(`file:`)?fileURLToPath(e):e}finally{Error.prepareStackTrace=e}}const require=createRequire(resolveCurrentModulePath());function isBuildOutputPackageRoot(e){return basename(e)===`dist`&&existsSync(join(dirname(e),`package.json`))}function resolvePackageBuildRoot(){let e=dirname(realpathSync(resolveCurrentModulePath()));for(;;){if(isBuildOutputPackageRoot(e))return e;let t=dirname(e);if(t===e)return null;e=t}}function findNearestPackageRoot(e){let n=e;for(;;){if(existsSync(join(n,`package.json`))&&!isBuildOutputPackageRoot(n))return n;let r=dirname(n);if(r===n)throw Error(`Failed to resolve package root from "${e}".`);n=r}}function resolvePackageRoot(){return findNearestPackageRoot(dirname(realpathSync(resolveCurrentModulePath())))}function tryResolvePackageRoot(){try{return resolvePackageRoot()}catch{return}}function rewriteSourceFilePathForBuild(e){return e.replace(/\.[cm]?tsx?$/,`.js`)}function resolvePackageSourceFilePath(e){let t=resolvePackageBuildRoot();return t===null?join(resolvePackageRoot(),e):join(t,rewriteSourceFilePathForBuild(e))}function resolvePackageSourceDirectoryPath(e){let t=resolvePackageBuildRoot();return join(t===null?resolvePackageRoot():t,e)}function resolvePackageDependencyPath(e){return require.resolve(e)}function resolvePackageCompiledFilePath(e){let t=resolvePackageBuildRoot();return t===null?join(resolvePackageRoot(),`.generated`,`compiled`,e.replace(/^src\/compiled\//,``)):join(t,e)}function normalizeInstalledPackageInfo(e){let t=e;if(!(typeof t.name!=`string`||typeof t.version!=`string`))return{name:t.name,version:t.version}}function tryReadInstalledPackageInfo(e,t){let r=normalizeInstalledPackageInfo(JSON.parse(readFileSync(e,`utf8`)));if(r?.name===t)return r}function resolveInstalledPackageInfo(){if(cachedPackageInfo)return cachedPackageInfo;let e=tryResolvePackageRoot(),t=e===void 0?void 0:tryReadInstalledPackageInfo(join(e,`package.json`),EVE_PACKAGE_NAME);if(t)return cachedPackageInfo=t,cachedPackageInfo;try{let e=tryReadInstalledPackageInfo(require.resolve(`${EVE_PACKAGE_NAME}/package.json`),EVE_PACKAGE_NAME);if(e)return cachedPackageInfo=e,cachedPackageInfo}catch{}return cachedPackageInfo={...FALLBACK_PACKAGE_INFO},cachedPackageInfo}function readWorkflowVersionFromManifest(e){let t=e;for(let e of[t.devDependencies,t.dependencies,t.peerDependencies]){let t=e?.[`@workflow/core`];if(typeof t==`string`&&t.trim().length>0)return t}}function resolveExpectedWorkflowVersion(){let e=tryResolvePackageRoot();if(e!==void 0)try{return readWorkflowVersionFromManifest(JSON.parse(readFileSync(join(e,`package.json`),`utf8`)))}catch{}try{return readWorkflowVersionFromManifest(JSON.parse(readFileSync(require.resolve(`${EVE_PACKAGE_NAME}/package.json`),`utf8`)))}catch{return}}function resolveWorkflowModulePath(e){if(e===`workflow`)return resolvePackageSourceFilePath(`src/internal/workflow/index.ts`);if(e===`workflow/api`||e===`workflow/runtime`)return resolvePackageSourceFilePath(`src/internal/workflow/runtime.ts`);if(e===`workflow/internal/builtins`)return resolvePackageSourceFilePath(`src/internal/workflow/builtins.ts`);let t=WORKFLOW_MODULE_ALIASES[e];return t===void 0?require.resolve(e):resolvePackageCompiledFilePath(t)}export{resolveExpectedWorkflowVersion,resolveInstalledPackageInfo,resolvePackageCompiledFilePath,resolvePackageDependencyPath,resolvePackageRoot,resolvePackageSourceDirectoryPath,resolvePackageSourceFilePath,resolveWorkflowModulePath};
1
+ import{createRequire}from"node:module";import{existsSync,readFileSync,realpathSync}from"node:fs";import{basename,dirname,join}from"node:path";import{EVE_PACKAGE_NAME}from"#internal/package-name.js";import{fileURLToPath}from"node:url";let cachedPackageInfo;const BUNDLED_FALLBACK_PACKAGE_VERSION=`0.24.6`,WORKFLOW_MODULE_ALIASES={"workflow/errors":`src/compiled/@workflow/errors/index.js`,"workflow/internal/private":`src/compiled/@workflow/core/private.js`};function resolveFallbackPackageVersion(){return BUNDLED_FALLBACK_PACKAGE_VERSION.startsWith(`__`)?`0.0.0`:BUNDLED_FALLBACK_PACKAGE_VERSION}const FALLBACK_PACKAGE_INFO={name:EVE_PACKAGE_NAME,version:resolveFallbackPackageVersion()};function resolveCurrentModulePath(){return typeof __filename==`string`?__filename:resolveCurrentModulePathFromStack()}function resolveCurrentModulePathFromStack(){let e=Error.prepareStackTrace;try{Error.prepareStackTrace=(e,t)=>t;let e=Error().stack?.[0]?.getFileName();if(typeof e!=`string`||e.length===0)throw Error(`Failed to resolve the current module path from the stack trace.`);return e.startsWith(`file:`)?fileURLToPath(e):e}finally{Error.prepareStackTrace=e}}const require=createRequire(resolveCurrentModulePath());function isBuildOutputPackageRoot(e){return basename(e)===`dist`&&existsSync(join(dirname(e),`package.json`))}function resolvePackageBuildRoot(){let e=dirname(realpathSync(resolveCurrentModulePath()));for(;;){if(isBuildOutputPackageRoot(e))return e;let t=dirname(e);if(t===e)return null;e=t}}function findNearestPackageRoot(e){let n=e;for(;;){if(existsSync(join(n,`package.json`))&&!isBuildOutputPackageRoot(n))return n;let r=dirname(n);if(r===n)throw Error(`Failed to resolve package root from "${e}".`);n=r}}function resolvePackageRoot(){return findNearestPackageRoot(dirname(realpathSync(resolveCurrentModulePath())))}function tryResolvePackageRoot(){try{return resolvePackageRoot()}catch{return}}function rewriteSourceFilePathForBuild(e){return e.replace(/\.[cm]?tsx?$/,`.js`)}function resolvePackageSourceFilePath(e){let t=resolvePackageBuildRoot();return t===null?join(resolvePackageRoot(),e):join(t,rewriteSourceFilePathForBuild(e))}function resolvePackageSourceDirectoryPath(e){let t=resolvePackageBuildRoot();return join(t===null?resolvePackageRoot():t,e)}function resolvePackageDependencyPath(e){return require.resolve(e)}function resolvePackageCompiledFilePath(e){let t=resolvePackageBuildRoot();return t===null?join(resolvePackageRoot(),`.generated`,`compiled`,e.replace(/^src\/compiled\//,``)):join(t,e)}function normalizeInstalledPackageInfo(e){let t=e;if(!(typeof t.name!=`string`||typeof t.version!=`string`))return{name:t.name,version:t.version}}function tryReadInstalledPackageInfo(e,t){let r=normalizeInstalledPackageInfo(JSON.parse(readFileSync(e,`utf8`)));if(r?.name===t)return r}function resolveInstalledPackageInfo(){if(cachedPackageInfo)return cachedPackageInfo;let e=tryResolvePackageRoot(),t=e===void 0?void 0:tryReadInstalledPackageInfo(join(e,`package.json`),EVE_PACKAGE_NAME);if(t)return cachedPackageInfo=t,cachedPackageInfo;try{let e=tryReadInstalledPackageInfo(require.resolve(`${EVE_PACKAGE_NAME}/package.json`),EVE_PACKAGE_NAME);if(e)return cachedPackageInfo=e,cachedPackageInfo}catch{}return cachedPackageInfo={...FALLBACK_PACKAGE_INFO},cachedPackageInfo}function readWorkflowVersionFromManifest(e){let t=e;for(let e of[t.devDependencies,t.dependencies,t.peerDependencies]){let t=e?.[`@workflow/core`];if(typeof t==`string`&&t.trim().length>0)return t}}function resolveExpectedWorkflowVersion(){let e=tryResolvePackageRoot();if(e!==void 0)try{return readWorkflowVersionFromManifest(JSON.parse(readFileSync(join(e,`package.json`),`utf8`)))}catch{}try{return readWorkflowVersionFromManifest(JSON.parse(readFileSync(require.resolve(`${EVE_PACKAGE_NAME}/package.json`),`utf8`)))}catch{return}}function resolveWorkflowModulePath(e){if(e===`workflow`)return resolvePackageSourceFilePath(`src/internal/workflow/index.ts`);if(e===`workflow/api`||e===`workflow/runtime`)return resolvePackageSourceFilePath(`src/internal/workflow/runtime.ts`);if(e===`workflow/internal/builtins`)return resolvePackageSourceFilePath(`src/internal/workflow/builtins.ts`);let t=WORKFLOW_MODULE_ALIASES[e];return t===void 0?require.resolve(e):resolvePackageCompiledFilePath(t)}export{resolveExpectedWorkflowVersion,resolveInstalledPackageInfo,resolvePackageCompiledFilePath,resolvePackageDependencyPath,resolvePackageRoot,resolvePackageSourceDirectoryPath,resolvePackageSourceFilePath,resolveWorkflowModulePath};
@@ -1 +1 @@
1
- import{createGetSessionFn}from"#channel/session.js";import{createLogger,logError}from"#internal/logging.js";import{createSendFn}from"#channel/send.js";import{createCrossChannelReceiveFn,toCrossChannelTargets}from"#channel/cross-channel-receive.js";import{DEVELOPMENT_WORKFLOW_SECRET_ENV}from"#internal/workflow/development-world-protocol.js";import{readTrustedDevelopmentClientAddress}from"#internal/nitro/dev-client-address.js";import{attachAgentInfoRouteResponse,attachRouteAgent}from"#internal/nitro/routes/channel-route-context.js";import{resolveNitroChannelRuntimeBundle}from"#internal/nitro/routes/runtime-stack.js";import{readVercelProjectLink}from"#internal/vercel/project-link.js";import{withVercelOidcProjectResolver}from"#runtime/governance/auth/vercel-oidc-project.js";const log=createLogger(`channel.dispatch`);async function dispatchChannelRequest(e,t,r){let i=await resolveNitroChannelRuntimeBundle(r),a=i.channels.find(e=>`${e.method.toUpperCase()} ${e.urlPath}`===t);if(a===void 0)return Response.json({error:`No matching channel for this request.`,ok:!1},{status:404});let o=buildRouteArgs(e,i,a.name,r),s;try{s=await withDevelopmentVercelOidcContext(r,e.req,async()=>{if(a.handler)return await a.handler(e.req,o.args);let t={agent:o.agent,waitUntil:o.args.waitUntil,params:o.args.params,requestIp:o.args.requestIp};return await a.fetch(e.req,t)})}catch(r){let i=logError(log,`channel handler threw`,r,{routeKey:t,channel:a.name});return flushBackgroundTasks(e,o.backgroundTasks,t,a.name),Response.json({error:`Channel handler failed.`,errorId:i,ok:!1},{status:500})}return flushBackgroundTasks(e,o.backgroundTasks,t,a.name),s}async function dispatchChannelWebSocketRequest(e,t,r){let i=await resolveNitroChannelRuntimeBundle(r),a=i.channels.find(e=>`${e.method.toUpperCase()} ${e.urlPath}`===t);if(a===void 0||a.websocket===void 0)return rejectWebSocketUpgrade({error:`No matching websocket channel for this request.`,ok:!1},404);let o=a.websocket,s=buildRouteArgs(e,i,a.name,r);try{let n=await withDevelopmentVercelOidcContext(r,e.req,async()=>await o(e.req,s.args));return flushBackgroundTasks(e,s.backgroundTasks,t,a.name),n}catch(r){let i=logError(log,`channel websocket handler threw`,r,{routeKey:t,channel:a.name});return flushBackgroundTasks(e,s.backgroundTasks,t,a.name),rejectWebSocketUpgrade({error:`Channel websocket handler failed.`,errorId:i,ok:!1},500)}}async function withDevelopmentVercelOidcContext(e,t,n){return e.kind===`development`?await withVercelOidcProjectResolver({request:t,resolveCurrentProject:async()=>{let t=await readVercelProjectLink(e.appRoot);return t===void 0?void 0:{environment:`development`,projectId:t.projectId}}},n):await n()}function buildRouteArgs(t,n,o,s){let c=readVercelRequestId(t.req.headers),l=extractRequestIp(t,s),u=[],d=t.context.params??{},f={};for(let[e,t]of Object.entries(d))f[e]=decodeURIComponent(t);let waitUntil=e=>{u.push(e)},p=n.channels.find(e=>e.name===o)?.adapter??{kind:`channel`},m=createRouteAgent(n.runtime,c);return{agent:m,args:attachRouteAgent(attachAgentInfoRouteResponse({send:createSendFn(n.runtime,p,o,{requestId:c}),getSession:createGetSessionFn(n.runtime),receive:createCrossChannelReceiveFn(n.runtime,toCrossChannelTargets(n.channels)),params:f,waitUntil,requestIp:l},async()=>{let{handleAgentInfoRequest:e}=await import(`#internal/nitro/routes/info.js`);return await e(s)}),m),backgroundTasks:u}}function createRouteAgent(e,t){return{async cancelTurn(t){return await e.cancelTurn(t)},async deliver(n){let r={...n,requestId:t};return await e.deliver(r)},async getEventStream(t,n){return await e.getEventStream(t,n)},async run(n){let r={...n,requestId:t};return await e.run(r)}}}function readVercelRequestId(e){let t=e.get(`x-vercel-id`)?.trim();return t===``?void 0:t}function rejectWebSocketUpgrade(e,t){return{upgrade(){throw Response.json(e,{status:t})}}}function flushBackgroundTasks(e,t,r,i){t.length!==0&&e.waitUntil(Promise.allSettled(t).then(e=>{for(let t of e)t.status===`rejected`&&logError(log,`channel background task failed`,t.reason,{routeKey:r,channel:i})}))}function extractRequestIp(e,t){if(t.kind===`development`){let t=readTrustedDevelopmentClientAddress(e.req.headers,process.env[DEVELOPMENT_WORKFLOW_SECRET_ENV]);if(t!==void 0)return t}return extractSocketIp(e)}function extractSocketIp(e){let t=e.req.ip;return typeof t==`string`&&t.length>0?t:null}export{dispatchChannelRequest,dispatchChannelWebSocketRequest};
1
+ import{createGetSessionFn}from"#channel/session.js";import{createLogger,logError}from"#internal/logging.js";import{createSendFn}from"#channel/send.js";import{createCrossChannelReceiveFn,toCrossChannelTargets}from"#channel/cross-channel-receive.js";import{DEVELOPMENT_WORKFLOW_SECRET_ENV}from"#internal/workflow/development-world-protocol.js";import{readTrustedDevelopmentClientAddress}from"#internal/nitro/dev-client-address.js";import{createCancelFn}from"#channel/cancel.js";import{attachAgentInfoRouteResponse,attachRouteAgent}from"#internal/nitro/routes/channel-route-context.js";import{resolveNitroChannelRuntimeBundle}from"#internal/nitro/routes/runtime-stack.js";import{readVercelProjectLink}from"#internal/vercel/project-link.js";import{withVercelOidcProjectResolver}from"#runtime/governance/auth/vercel-oidc-project.js";const log=createLogger(`channel.dispatch`);async function dispatchChannelRequest(e,t,r){let i=await resolveNitroChannelRuntimeBundle(r),a=i.channels.find(e=>`${e.method.toUpperCase()} ${e.urlPath}`===t);if(a===void 0)return Response.json({error:`No matching channel for this request.`,ok:!1},{status:404});let o=buildRouteArgs(e,i,a.name,r),s;try{s=await withDevelopmentVercelOidcContext(r,e.req,async()=>{if(a.handler)return await a.handler(e.req,o.args);let t={agent:o.agent,waitUntil:o.args.waitUntil,params:o.args.params,requestIp:o.args.requestIp};return await a.fetch(e.req,t)})}catch(r){let i=logError(log,`channel handler threw`,r,{routeKey:t,channel:a.name});return flushBackgroundTasks(e,o.backgroundTasks,t,a.name),Response.json({error:`Channel handler failed.`,errorId:i,ok:!1},{status:500})}return flushBackgroundTasks(e,o.backgroundTasks,t,a.name),s}async function dispatchChannelWebSocketRequest(e,t,r){let i=await resolveNitroChannelRuntimeBundle(r),a=i.channels.find(e=>`${e.method.toUpperCase()} ${e.urlPath}`===t);if(a===void 0||a.websocket===void 0)return rejectWebSocketUpgrade({error:`No matching websocket channel for this request.`,ok:!1},404);let o=a.websocket,s=buildRouteArgs(e,i,a.name,r);try{let n=await withDevelopmentVercelOidcContext(r,e.req,async()=>await o(e.req,s.args));return flushBackgroundTasks(e,s.backgroundTasks,t,a.name),n}catch(r){let i=logError(log,`channel websocket handler threw`,r,{routeKey:t,channel:a.name});return flushBackgroundTasks(e,s.backgroundTasks,t,a.name),rejectWebSocketUpgrade({error:`Channel websocket handler failed.`,errorId:i,ok:!1},500)}}async function withDevelopmentVercelOidcContext(e,t,n){return e.kind===`development`?await withVercelOidcProjectResolver({request:t,resolveCurrentProject:async()=>{let t=await readVercelProjectLink(e.appRoot);return t===void 0?void 0:{environment:`development`,projectId:t.projectId}}},n):await n()}function buildRouteArgs(t,n,o,s){let c=readVercelRequestId(t.req.headers),l=extractRequestIp(t,s),u=[],d=t.context.params??{},f={};for(let[e,t]of Object.entries(d))f[e]=decodeURIComponent(t);let waitUntil=e=>{u.push(e)},p=n.channels.find(e=>e.name===o)?.adapter??{kind:`channel`},m=createRouteAgent(n.runtime,c);return{agent:m,args:attachRouteAgent(attachAgentInfoRouteResponse({send:createSendFn(n.runtime,p,o,{requestId:c}),cancel:createCancelFn(n.runtime,o),getSession:createGetSessionFn(n.runtime),receive:createCrossChannelReceiveFn(n.runtime,toCrossChannelTargets(n.channels)),params:f,waitUntil,requestIp:l},async()=>{let{handleAgentInfoRequest:e}=await import(`#internal/nitro/routes/info.js`);return await e(s)}),m),backgroundTasks:u}}function createRouteAgent(e,t){return{async cancelTurn(t){return await e.cancelTurn(t)},async deliver(n){let r={...n,requestId:t};return await e.deliver(r)},async getEventStream(t,n){return await e.getEventStream(t,n)},async run(n){let r={...n,requestId:t};return await e.run(r)}}}function readVercelRequestId(e){let t=e.get(`x-vercel-id`)?.trim();return t===``?void 0:t}function rejectWebSocketUpgrade(e,t){return{upgrade(){throw Response.json(e,{status:t})}}}function flushBackgroundTasks(e,t,r,i){t.length!==0&&e.waitUntil(Promise.allSettled(t).then(e=>{for(let t of e)t.status===`rejected`&&logError(log,`channel background task failed`,t.reason,{routeKey:r,channel:i})}))}function extractRequestIp(e,t){if(t.kind===`development`){let t=readTrustedDevelopmentClientAddress(e.req.headers,process.env[DEVELOPMENT_WORKFLOW_SECRET_ENV]);if(t!==void 0)return t}return extractSocketIp(e)}function extractSocketIp(e){let t=e.req.ip;return typeof t==`string`&&t.length>0?t:null}export{dispatchChannelRequest,dispatchChannelWebSocketRequest};
@@ -1,4 +1,4 @@
1
- export { defineChannel, GET, POST, PUT, PATCH, DELETE, WS, type Channel, type ChannelCors, type ChannelCorsOptions, type ChannelDefinition, type ChannelSessionOps, type ChannelEvents, type InferChannelMetadata, type Session, type SessionHandle, type RouteDefinition, type RouteHandlerArgs, type SendFn, type SendOptions, type SendPayload, type GetSessionFn, type HttpRouteDefinition, type WebSocketMessage, type WebSocketPeer, type WebSocketRouteDefinition, type WebSocketRouteHandler, type WebSocketRouteHooks, type WebSocketUpgradeRequest, type WebSocketUpgradeResult, } from "#public/definitions/channel.js";
1
+ export { defineChannel, GET, POST, PUT, PATCH, DELETE, WS, type CancelFn, type CancelOptions, type CancelTurnResult, type Channel, type ChannelCors, type ChannelCorsOptions, type ChannelDefinition, type ChannelSessionOps, type ChannelEvents, type InferChannelMetadata, type Session, type SessionHandle, type RouteDefinition, type RouteHandlerArgs, type SendFn, type SendOptions, type SendPayload, type GetSessionFn, type HttpRouteDefinition, type WebSocketMessage, type WebSocketPeer, type WebSocketRouteDefinition, type WebSocketRouteHandler, type WebSocketRouteHooks, type WebSocketUpgradeRequest, type WebSocketUpgradeResult, } from "#public/definitions/channel.js";
2
2
  export { createWebSocketUpgradeServer, type WebSocketUpgradeServerBridge, } from "#channel/websocket-upgrade-server.js";
3
3
  import type { Channel, InferChannelMetadata } from "#public/definitions/channel.js";
4
4
  /**
@@ -12,7 +12,7 @@ export type { CancelTurnInput, CancelTurnResult, GetEventStreamOptions } from "#
12
12
  export type { Session, SessionHandle } from "#channel/session.js";
13
13
  export type { ChannelCors, ChannelCorsOptions } from "#channel/cors.js";
14
14
  export { GET, POST, PUT, PATCH, DELETE, WS } from "#channel/routes.js";
15
- export type { HttpRouteDefinition, RouteDefinition, RouteHandlerArgs, SendFn, SendOptions, SendPayload, GetSessionFn, WebSocketMessage, WebSocketPeer, WebSocketRouteDefinition, WebSocketRouteHandler, WebSocketRouteHooks, WebSocketUpgradeRequest, WebSocketUpgradeResult, } from "#channel/routes.js";
15
+ export type { CancelFn, CancelOptions, HttpRouteDefinition, RouteDefinition, RouteHandlerArgs, SendFn, SendOptions, SendPayload, GetSessionFn, WebSocketMessage, WebSocketPeer, WebSocketRouteDefinition, WebSocketRouteHandler, WebSocketRouteHooks, WebSocketUpgradeRequest, WebSocketUpgradeResult, } from "#channel/routes.js";
16
16
  /**
17
17
  * HTTP method a route handles. Defaults to `"POST"` — almost every route
18
18
  * is a webhook. Override only when authoring a non-webhook route such as a
@@ -1,4 +1,4 @@
1
- import{pinnedNodeEngineMajor}from"../../node-engine.js";import{SUPPORTED_AUTHORED_MODULE_FILE_EXTENSIONS}from"../update/module-files.js";import{pathExists,writeTextFile}from"../files.js";import{resolveVersionToken}from"../version-tokens.js";import{applyPackageManagerWorkspaceConfiguration,isPackageManagerWorkspaceMember,patchWorkspaceRootPackageJson}from"../workspace-root.js";import{WEB_APP_TEMPLATE_FILES}from"./web-template.js";import{basename,join,resolve}from"node:path";import{mkdir,readdir,stat}from"node:fs/promises";const CURRENT_DIRECTORY_PROJECT_NAME=`.`,ALLOWED_CREATE_IN_PLACE_ENTRIES=new Set([`.DS_Store`,`.git`,`.gitkeep`,`.hg`]),DEFAULT_AI_PACKAGE_VERSION=`^7.0.26`,DEFAULT_CONNECT_PACKAGE_VERSION=`0.2.2`,DEFAULT_ZOD_PACKAGE_VERSION=`4.4.3`,DEFAULT_EVE_PACKAGE_CONTRACT={version:`0.24.5`,nodeEngine:`>=24`};function resolveEvePackageContract(e=DEFAULT_EVE_PACKAGE_CONTRACT){return{version:resolveVersionToken(`evePackage.version`,e.version),nodeEngine:resolveVersionToken(`evePackage.nodeEngine`,e.nodeEngine)}}function modelProviderSlug(e){let t=(e.split(`/`)[0]??``).replaceAll(/[^A-Za-z0-9._-]/gu,``);return t.length>0?t:`anthropic`}function byokProviderEnvVar(e){let t=modelProviderSlug(e).toUpperCase().replaceAll(/[^A-Z0-9]/gu,`_`);return`${/^[0-9]/.test(t)?`_`:``}${t}_API_KEY`}function agentTemplateFiles(e){return{"agent/agent.ts":BASE_AGENT_TEMPLATE.replaceAll(`__EVE_INIT_MODEL__`,e),"agent/channels/eve.ts":WEB_APP_TEMPLATE_FILES[`agent/channels/eve.ts`],"agent/instructions.md":AGENT_INSTRUCTIONS_TEMPLATE}}function renderTemplate(e,t){return e.replaceAll(`__EVE_INIT_APP_NAME__`,t.appName).replaceAll(`__EVE_INIT_MODEL__`,t.model).replaceAll(`__EVE_INIT_BYOK_PROVIDER__`,modelProviderSlug(t.model)).replaceAll(`__EVE_INIT_BYOK_ENV_VAR__`,byokProviderEnvVar(t.model)).replaceAll(`__EVE_INIT_PACKAGE_VERSION__`,formatEveDependencySpecifier(t.eveVersion)).replaceAll(`__EVE_INIT_AI_SDK_VERSION__`,t.aiPackageVersion).replaceAll(`__EVE_INIT_CONNECT_VERSION__`,t.connectPackageVersion).replaceAll(`__EVE_INIT_ZOD_VERSION__`,t.zodPackageVersion).replaceAll(`__EVE_INIT_TYPESCRIPT_VERSION__`,t.typescriptPackageVersion).replaceAll(`__EVE_INIT_TYPES_NODE_VERSION__`,t.nodeTypesVersion).replaceAll(`__EVE_INIT_NODE_ENGINE__`,t.nodeEngine)}function formatEveDependencySpecifier(e){return/^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z-.]+)?$/.test(e)?`^${e}`:e}const BASE_AGENT_TEMPLATE=`import { defineAgent } from "eve";
1
+ import{pinnedNodeEngineMajor}from"../../node-engine.js";import{SUPPORTED_AUTHORED_MODULE_FILE_EXTENSIONS}from"../update/module-files.js";import{pathExists,writeTextFile}from"../files.js";import{resolveVersionToken}from"../version-tokens.js";import{applyPackageManagerWorkspaceConfiguration,isPackageManagerWorkspaceMember,patchWorkspaceRootPackageJson}from"../workspace-root.js";import{WEB_APP_TEMPLATE_FILES}from"./web-template.js";import{basename,join,resolve}from"node:path";import{mkdir,readdir,stat}from"node:fs/promises";const CURRENT_DIRECTORY_PROJECT_NAME=`.`,ALLOWED_CREATE_IN_PLACE_ENTRIES=new Set([`.DS_Store`,`.git`,`.gitkeep`,`.hg`]),DEFAULT_AI_PACKAGE_VERSION=`^7.0.26`,DEFAULT_CONNECT_PACKAGE_VERSION=`0.2.2`,DEFAULT_ZOD_PACKAGE_VERSION=`4.4.3`,DEFAULT_EVE_PACKAGE_CONTRACT={version:`0.24.6`,nodeEngine:`>=24`};function resolveEvePackageContract(e=DEFAULT_EVE_PACKAGE_CONTRACT){return{version:resolveVersionToken(`evePackage.version`,e.version),nodeEngine:resolveVersionToken(`evePackage.nodeEngine`,e.nodeEngine)}}function modelProviderSlug(e){let t=(e.split(`/`)[0]??``).replaceAll(/[^A-Za-z0-9._-]/gu,``);return t.length>0?t:`anthropic`}function byokProviderEnvVar(e){let t=modelProviderSlug(e).toUpperCase().replaceAll(/[^A-Z0-9]/gu,`_`);return`${/^[0-9]/.test(t)?`_`:``}${t}_API_KEY`}function agentTemplateFiles(e){return{"agent/agent.ts":BASE_AGENT_TEMPLATE.replaceAll(`__EVE_INIT_MODEL__`,e),"agent/channels/eve.ts":WEB_APP_TEMPLATE_FILES[`agent/channels/eve.ts`],"agent/instructions.md":AGENT_INSTRUCTIONS_TEMPLATE}}function renderTemplate(e,t){return e.replaceAll(`__EVE_INIT_APP_NAME__`,t.appName).replaceAll(`__EVE_INIT_MODEL__`,t.model).replaceAll(`__EVE_INIT_BYOK_PROVIDER__`,modelProviderSlug(t.model)).replaceAll(`__EVE_INIT_BYOK_ENV_VAR__`,byokProviderEnvVar(t.model)).replaceAll(`__EVE_INIT_PACKAGE_VERSION__`,formatEveDependencySpecifier(t.eveVersion)).replaceAll(`__EVE_INIT_AI_SDK_VERSION__`,t.aiPackageVersion).replaceAll(`__EVE_INIT_CONNECT_VERSION__`,t.connectPackageVersion).replaceAll(`__EVE_INIT_ZOD_VERSION__`,t.zodPackageVersion).replaceAll(`__EVE_INIT_TYPESCRIPT_VERSION__`,t.typescriptPackageVersion).replaceAll(`__EVE_INIT_TYPES_NODE_VERSION__`,t.nodeTypesVersion).replaceAll(`__EVE_INIT_NODE_ENGINE__`,t.nodeEngine)}function formatEveDependencySpecifier(e){return/^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z-.]+)?$/.test(e)?`^${e}`:e}const BASE_AGENT_TEMPLATE=`import { defineAgent } from "eve";
2
2
 
3
3
  export default defineAgent({
4
4
  model: "__EVE_INIT_MODEL__",
@@ -31,7 +31,7 @@ export declare const WEB_APP_TEMPLATE_FILES: {
31
31
  readonly "components.json": '{\n "$schema": "https://ui.shadcn.com/schema.json",\n "style": "new-york",\n "rsc": true,\n "tsx": true,\n "tailwind": {\n "config": "",\n "css": "app/globals.css",\n "baseColor": "neutral",\n "cssVariables": true,\n "prefix": ""\n },\n "iconLibrary": "lucide",\n "aliases": {\n "components": "@/components",\n "utils": "@/lib/utils",\n "ui": "@/components/ui",\n "lib": "@/lib",\n "hooks": "@/hooks"\n },\n "registries": {}\n}\n';
32
32
  readonly "css.d.ts": 'declare module "*.css";\n';
33
33
  readonly "lib/utils.ts": 'import { clsx, type ClassValue } from "clsx";\nimport { twMerge } from "tailwind-merge";\n\nexport function cn(...inputs: ClassValue[]): string {\n return twMerge(clsx(inputs));\n}\n';
34
- readonly "next-env.d.ts": '/// <reference types="next" />\n/// <reference types="next/image-types/global" />\nimport "./.next/types/routes.d.ts";\n\n// NOTE: This file should not be edited\n// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.\n';
34
+ readonly "next-env.d.ts": '/// <reference types="next" />\n/// <reference types="next/image-types/global" />\nimport "./.next/types/routes.d.ts";\nimport "./.next/types/root-params.d.ts";\n\n// NOTE: This file should not be edited\n// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.\n';
35
35
  readonly "next.config.ts": 'import type { NextConfig } from "next";\nimport { withEve } from "eve/next";\n\nconst nextConfig: NextConfig = {};\n\nexport default withEve(nextConfig__EVE_INIT_WITH_EVE_OPTIONS__);\n';
36
36
  readonly "postcss.config.mjs": 'const config = {\n plugins: {\n "@tailwindcss/postcss": {},\n },\n};\n\nexport default config;\n';
37
37
  readonly "tsconfig.json": '{\n "$schema": "https://json.schemastore.org/tsconfig",\n "compilerOptions": {\n "target": "ES2017",\n "lib": ["dom", "dom.iterable", "esnext"],\n "allowJs": true,\n "skipLibCheck": true,\n "strict": true,\n "noEmit": true,\n "esModuleInterop": true,\n "module": "esnext",\n "moduleResolution": "Bundler",\n "resolveJsonModule": true,\n "isolatedModules": true,\n "jsx": "react-jsx",\n "incremental": true,\n "plugins": [\n {\n "name": "next"\n }\n ],\n "paths": {\n "@/*": ["./*"]\n }\n },\n "include": [\n "next-env.d.ts",\n "**/*.ts",\n "**/*.tsx",\n ".next/types/**/*.ts",\n ".next/dev/types/**/*.ts"\n ],\n "exclude": ["node_modules"]\n}\n';
@@ -4821,6 +4821,7 @@ export function cn(...inputs: ClassValue[]): string {
4821
4821
  `,"next-env.d.ts":`/// <reference types="next" />
4822
4822
  /// <reference types="next/image-types/global" />
4823
4823
  import "./.next/types/routes.d.ts";
4824
+ import "./.next/types/root-params.d.ts";
4824
4825
 
4825
4826
  // NOTE: This file should not be edited
4826
4827
  // see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
@@ -1,4 +1,4 @@
1
- import{pinnedNodeEngineMajor}from"../../node-engine.js";import{getSupportedModuleBaseName,matchesSupportedModuleBaseName}from"./module-files.js";import{pathExists,writeTextFile}from"../files.js";import{resolveVersionToken}from"../version-tokens.js";import{patchPackageJson}from"./package-json.js";import{applyPackageManagerWorkspaceConfiguration,isPackageManagerWorkspaceMember,patchWorkspaceRootPackageJson}from"../workspace-root.js";import{WEB_APP_TEMPLATE_FILES,WEB_APP_TEMPLATE_PACKAGE_JSON}from"../create/web-template.js";import{DEFAULT_EVE_PACKAGE_CONTRACT,resolveEvePackageContract}from"../create/project.js";import{basename,join,resolve}from"node:path";import{readFile,readdir}from"node:fs/promises";const SLACK_CHANNEL_DEFAULT_ROUTE=`/eve/v1/slack`,DEFAULT_SLACK_CONNECTOR_SLUG=`my-agent`,NEXT_PACKAGE_NAME=`next`,PACKAGE_DEPENDENCY_FIELDS=[`dependencies`,`devDependencies`],WEB_NEXT_CONFIG_PATH=`next.config.ts`,WEB_COMPETING_NEXT_CONFIG_PATHS=[`next.config.js`,`next.config.mjs`,WEB_NEXT_CONFIG_PATH,`next.config.mts`].filter(e=>e!==WEB_NEXT_CONFIG_PATH);function toSlackConnectorSlug(e){return e}function isJsonObject(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}async function readPackageJsonObject(e){if(!await pathExists(e))return;let t=JSON.parse(await readFile(e,`utf8`));return isJsonObject(t)?t:void 0}async function readDependencyVersion(e,t){let n=await readPackageJsonObject(e);if(n===void 0||!isJsonObject(n.dependencies))return;let r=n.dependencies[t];return typeof r==`string`?r:void 0}function packageJsonHasDependency(e,t){for(let n of PACKAGE_DEPENDENCY_FIELDS){let r=e[n];if(isJsonObject(r)&&typeof r[t]==`string`)return!0}return!1}async function hasPackageDependency(e,t){let n=await readPackageJsonObject(e);return n!==void 0&&packageJsonHasDependency(n,t)}async function isNextJsProject(e){return hasPackageDependency(join(e,`package.json`),NEXT_PACKAGE_NAME)}const VERCEL_HOST_FRAMEWORK_PRESETS={"@sveltejs/kit":`sveltekit`,[NEXT_PACKAGE_NAME]:`nextjs`,nuxt:`nuxtjs`,nuxt3:`nuxtjs`,"nuxt-edge":`nuxtjs`,"nuxt-nightly":`nuxtjs`};async function resolveVercelHostFrameworkPreset(e){let t=await readPackageJsonObject(join(e,`package.json`));if(t!==void 0){for(let[e,n]of Object.entries(VERCEL_HOST_FRAMEWORK_PRESETS))if(packageJsonHasDependency(t,e))return n}}async function hasVercelHostFramework(e){return await resolveVercelHostFrameworkPreset(e)!==void 0}async function ensurePackageDependency(e,t,n){return!await pathExists(e)||await readDependencyVersion(e,t)===n?[]:(await patchPackageJson(e,{dependencies:{[t]:n}}),[{path:e,dependencies:[t],devDependencies:[],scripts:[]}])}function resolveWebPackageVersions(e){return{evePackage:e?.evePackage??DEFAULT_EVE_PACKAGE_CONTRACT,aiPackageVersion:e?.aiPackageVersion??`^7.0.26`,nextPackageVersion:e?.nextPackageVersion??`16.2.6`,reactPackageVersion:e?.reactPackageVersion??`19.2.6`,reactDomPackageVersion:e?.reactDomPackageVersion??`19.2.6`,streamdownPackageVersion:e?.streamdownPackageVersion??`2.5.0`,zodPackageVersion:e?.zodPackageVersion??`4.4.3`,typesReactPackageVersion:e?.typesReactPackageVersion??`19.2.15`,typesReactDomPackageVersion:e?.typesReactDomPackageVersion??`19.2.3`}}function formatEveDependencySpecifier(e){return/^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z-.]+)?$/.test(e)?`^${e}`:e}async function patchWebPackageJson(t,n,i,s,u){let f=join(t,`package.json`);if(!await pathExists(f))return{mutations:[]};let m=resolveEvePackageContract(s.evePackage),h=pinnedNodeEngineMajor(m.nodeEngine),g={...WEB_APP_TEMPLATE_PACKAGE_JSON.dependencies,ai:resolveVersionToken(`aiPackageVersion`,s.aiPackageVersion),eve:formatEveDependencySpecifier(m.version),next:resolveVersionToken(`nextPackageVersion`,s.nextPackageVersion),react:resolveVersionToken(`reactPackageVersion`,s.reactPackageVersion),"react-dom":resolveVersionToken(`reactDomPackageVersion`,s.reactDomPackageVersion),streamdown:resolveVersionToken(`streamdownPackageVersion`,s.streamdownPackageVersion),zod:resolveVersionToken(`zodPackageVersion`,s.zodPackageVersion)},_={...WEB_APP_TEMPLATE_PACKAGE_JSON.devDependencies,"@types/node":h,"@types/react":resolveVersionToken(`typesReactPackageVersion`,s.typesReactPackageVersion),"@types/react-dom":resolveVersionToken(`typesReactDomPackageVersion`,s.typesReactDomPackageVersion),typescript:`6.0.3`},v=WEB_APP_TEMPLATE_PACKAGE_JSON.scripts,y=isPackageManagerWorkspaceMember(n,i),b={dependencies:g,devDependencies:_,scripts:v};y||(b.nodeEngineRequirement=m.nodeEngine);let x=await patchPackageJson(f,b),S=(await patchWorkspaceRootPackageJson(n,i,{aiPackageVersion:g.ai,nodeEngineRequirement:m.nodeEngine,onWorkspaceRootMutation:u})).nodeEngineOverride??x.nodeEngineOverride;return{mutations:[{path:f,dependencies:Object.keys(g),devDependencies:Object.keys(_),scripts:Object.keys(v)}],nodeEngineOverride:S}}function normalizeSlackConnectorSlug(e){return toSlackConnectorSlug((e.trim().replace(/^@/,``).split(`/`).at(-1)??``).toLowerCase().replace(/[^a-z0-9_-]+/g,`-`).replace(/^[^a-z0-9]+/,``).replace(/[^a-z0-9]+$/,``).slice(0,100).replace(/[^a-z0-9]+$/,``)||`my-agent`)}async function deriveSlackConnectorSlug(e,t){if(t!==void 0&&t.length>0&&t!==`.`)return normalizeSlackConnectorSlug(t);try{let t=await readFile(join(e,`package.json`),`utf8`),n=JSON.parse(t);if(typeof n.name==`string`&&n.name.length>0)return normalizeSlackConnectorSlug(n.name)}catch{}return normalizeSlackConnectorSlug(basename(resolve(e))||`my-agent`)}function buildSlackTemplate(e){if(!e.startsWith(`slack/`)||e.length===6)throw Error(`Invalid Slack connector UID "${e}".`);return`import { connectSlackCredentials } from "@vercel/connect/eve";
1
+ import{pinnedNodeEngineMajor}from"../../node-engine.js";import{getSupportedModuleBaseName,matchesSupportedModuleBaseName}from"./module-files.js";import{pathExists,writeTextFile}from"../files.js";import{resolveVersionToken}from"../version-tokens.js";import{patchPackageJson}from"./package-json.js";import{applyPackageManagerWorkspaceConfiguration,isPackageManagerWorkspaceMember,patchWorkspaceRootPackageJson}from"../workspace-root.js";import{WEB_APP_TEMPLATE_FILES,WEB_APP_TEMPLATE_PACKAGE_JSON}from"../create/web-template.js";import{DEFAULT_EVE_PACKAGE_CONTRACT,resolveEvePackageContract}from"../create/project.js";import{basename,join,resolve}from"node:path";import{readFile,readdir}from"node:fs/promises";const SLACK_CHANNEL_DEFAULT_ROUTE=`/eve/v1/slack`,DEFAULT_SLACK_CONNECTOR_SLUG=`my-agent`,NEXT_PACKAGE_NAME=`next`,PACKAGE_DEPENDENCY_FIELDS=[`dependencies`,`devDependencies`],WEB_NEXT_CONFIG_PATH=`next.config.ts`,WEB_COMPETING_NEXT_CONFIG_PATHS=[`next.config.js`,`next.config.mjs`,WEB_NEXT_CONFIG_PATH,`next.config.mts`].filter(e=>e!==WEB_NEXT_CONFIG_PATH);function toSlackConnectorSlug(e){return e}function isJsonObject(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}async function readPackageJsonObject(e){if(!await pathExists(e))return;let t=JSON.parse(await readFile(e,`utf8`));return isJsonObject(t)?t:void 0}async function readDependencyVersion(e,t){let n=await readPackageJsonObject(e);if(n===void 0||!isJsonObject(n.dependencies))return;let r=n.dependencies[t];return typeof r==`string`?r:void 0}function packageJsonHasDependency(e,t){for(let n of PACKAGE_DEPENDENCY_FIELDS){let r=e[n];if(isJsonObject(r)&&typeof r[t]==`string`)return!0}return!1}async function hasPackageDependency(e,t){let n=await readPackageJsonObject(e);return n!==void 0&&packageJsonHasDependency(n,t)}async function isNextJsProject(e){return hasPackageDependency(join(e,`package.json`),NEXT_PACKAGE_NAME)}const VERCEL_HOST_FRAMEWORK_PRESETS={"@sveltejs/kit":`sveltekit`,[NEXT_PACKAGE_NAME]:`nextjs`,nuxt:`nuxtjs`,nuxt3:`nuxtjs`,"nuxt-edge":`nuxtjs`,"nuxt-nightly":`nuxtjs`};async function resolveVercelHostFrameworkPreset(e){let t=await readPackageJsonObject(join(e,`package.json`));if(t!==void 0){for(let[e,n]of Object.entries(VERCEL_HOST_FRAMEWORK_PRESETS))if(packageJsonHasDependency(t,e))return n}}async function hasVercelHostFramework(e){return await resolveVercelHostFrameworkPreset(e)!==void 0}async function ensurePackageDependency(e,t,n){return!await pathExists(e)||await readDependencyVersion(e,t)===n?[]:(await patchPackageJson(e,{dependencies:{[t]:n}}),[{path:e,dependencies:[t],devDependencies:[],scripts:[]}])}function resolveWebPackageVersions(e){return{evePackage:e?.evePackage??DEFAULT_EVE_PACKAGE_CONTRACT,aiPackageVersion:e?.aiPackageVersion??`^7.0.26`,nextPackageVersion:e?.nextPackageVersion??`16.3.0-preview.6`,reactPackageVersion:e?.reactPackageVersion??`19.2.6`,reactDomPackageVersion:e?.reactDomPackageVersion??`19.2.6`,streamdownPackageVersion:e?.streamdownPackageVersion??`2.5.0`,zodPackageVersion:e?.zodPackageVersion??`4.4.3`,typesReactPackageVersion:e?.typesReactPackageVersion??`19.2.15`,typesReactDomPackageVersion:e?.typesReactDomPackageVersion??`19.2.3`}}function formatEveDependencySpecifier(e){return/^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z-.]+)?$/.test(e)?`^${e}`:e}async function patchWebPackageJson(t,n,i,s,u){let f=join(t,`package.json`);if(!await pathExists(f))return{mutations:[]};let m=resolveEvePackageContract(s.evePackage),h=pinnedNodeEngineMajor(m.nodeEngine),g={...WEB_APP_TEMPLATE_PACKAGE_JSON.dependencies,ai:resolveVersionToken(`aiPackageVersion`,s.aiPackageVersion),eve:formatEveDependencySpecifier(m.version),next:resolveVersionToken(`nextPackageVersion`,s.nextPackageVersion),react:resolveVersionToken(`reactPackageVersion`,s.reactPackageVersion),"react-dom":resolveVersionToken(`reactDomPackageVersion`,s.reactDomPackageVersion),streamdown:resolveVersionToken(`streamdownPackageVersion`,s.streamdownPackageVersion),zod:resolveVersionToken(`zodPackageVersion`,s.zodPackageVersion)},_={...WEB_APP_TEMPLATE_PACKAGE_JSON.devDependencies,"@types/node":h,"@types/react":resolveVersionToken(`typesReactPackageVersion`,s.typesReactPackageVersion),"@types/react-dom":resolveVersionToken(`typesReactDomPackageVersion`,s.typesReactDomPackageVersion),typescript:`6.0.3`},v=WEB_APP_TEMPLATE_PACKAGE_JSON.scripts,y=isPackageManagerWorkspaceMember(n,i),b={dependencies:g,devDependencies:_,scripts:v};y||(b.nodeEngineRequirement=m.nodeEngine);let x=await patchPackageJson(f,b),S=(await patchWorkspaceRootPackageJson(n,i,{aiPackageVersion:g.ai,nodeEngineRequirement:m.nodeEngine,onWorkspaceRootMutation:u})).nodeEngineOverride??x.nodeEngineOverride;return{mutations:[{path:f,dependencies:Object.keys(g),devDependencies:Object.keys(_),scripts:Object.keys(v)}],nodeEngineOverride:S}}function normalizeSlackConnectorSlug(e){return toSlackConnectorSlug((e.trim().replace(/^@/,``).split(`/`).at(-1)??``).toLowerCase().replace(/[^a-z0-9_-]+/g,`-`).replace(/^[^a-z0-9]+/,``).replace(/[^a-z0-9]+$/,``).slice(0,100).replace(/[^a-z0-9]+$/,``)||`my-agent`)}async function deriveSlackConnectorSlug(e,t){if(t!==void 0&&t.length>0&&t!==`.`)return normalizeSlackConnectorSlug(t);try{let t=await readFile(join(e,`package.json`),`utf8`),n=JSON.parse(t);if(typeof n.name==`string`&&n.name.length>0)return normalizeSlackConnectorSlug(n.name)}catch{}return normalizeSlackConnectorSlug(basename(resolve(e))||`my-agent`)}function buildSlackTemplate(e){if(!e.startsWith(`slack/`)||e.length===6)throw Error(`Invalid Slack connector UID "${e}".`);return`import { connectSlackCredentials } from "@vercel/connect/eve";
2
2
  import { slackChannel } from "eve/channels/slack";
3
3
 
4
4
  export default slackChannel({
@@ -1,3 +1,3 @@
1
- import { n as defaultMessageReducer, t as useEveAgent } from "../chunks/use-eve-agent-8rerxDHY.js";
1
+ import { n as defaultMessageReducer, t as useEveAgent } from "../chunks/use-eve-agent-6BO9gFVq.js";
2
2
 
3
3
  export { defaultMessageReducer, useEveAgent };
@@ -1,3 +1,3 @@
1
- import { t as useEveAgent } from "../chunks/use-eve-agent-8rerxDHY.js";
1
+ import { t as useEveAgent } from "../chunks/use-eve-agent-6BO9gFVq.js";
2
2
 
3
3
  export { useEveAgent };
@@ -1,3 +1,3 @@
1
- import { n as defaultMessageReducer, t as useEveAgent } from "../chunks/use-eve-agent-DhgdHzDG.js";
1
+ import { n as defaultMessageReducer, t as useEveAgent } from "../chunks/use-eve-agent-B1MJNRE-.js";
2
2
 
3
3
  export { defaultMessageReducer, useEveAgent };
@@ -1,3 +1,3 @@
1
- import { t as useEveAgent } from "../chunks/use-eve-agent-DhgdHzDG.js";
1
+ import { t as useEveAgent } from "../chunks/use-eve-agent-B1MJNRE-.js";
2
2
 
3
3
  export { useEveAgent };
@@ -47,7 +47,8 @@ export default defineChannel({
47
47
  Declare routes with the `POST()` and `GET()` helpers. Each route handler receives the raw `Request` and a helpers object:
48
48
 
49
49
  - `send(message, { auth, continuationToken, state?, title? })` starts or resumes a session. `title` overrides the new workflow session's display title without changing the model message. Returns a `Session`.
50
- - `getSession(sessionId)` looks up an existing session. The returned `Session` exposes `getEventStream({ startIndex? })` for streaming.
50
+ - `cancel({ continuationToken, turnId? })` requests cancellation of the active turn on the session that owns the token. See [Cancel a turn](#cancel-a-turn).
51
+ - `getSession(sessionId)` looks up an existing session. The returned `Session` exposes `getEventStream({ startIndex? })` for streaming and `cancel({ turnId? })` for session-id-addressed cancellation.
51
52
  - `receive(channel, ...)` hands inbound work to a different channel for cross-channel hand-off.
52
53
  - `params` holds route parameters extracted from the path pattern.
53
54
  - `waitUntil(promise)` extends the request lifetime for background work.
@@ -55,6 +56,35 @@ Declare routes with the `POST()` and `GET()` helpers. Each route handler receive
55
56
 
56
57
  Event handlers like `"message.completed"` are declared under the `events` key. They receive `(eventData, channel, ctx)`, where `eventData` is the event payload, `channel` carries platform handles and session continuation operations, and `ctx` is the eve `SessionContext`. Every channel kind shares this signature. The one exception is `session.failed`, which receives only `(eventData, channel)` with no `ctx`.
57
58
 
59
+ ## Cancel a turn
60
+
61
+ A stop route cancels a session's in-flight turn with the `cancel` helper, addressed by the same channel-local continuation token used with `send()`:
62
+
63
+ ```ts
64
+ import { defineChannel, POST } from "eve/channels";
65
+
66
+ export default defineChannel({
67
+ routes: [
68
+ POST("/threads/:threadId/stop", async (_req, { cancel, params }) => {
69
+ const result = await cancel({ continuationToken: params.threadId });
70
+ return Response.json(result);
71
+ }),
72
+ ],
73
+ });
74
+ ```
75
+
76
+ Both result statuses are successful. `"accepted"` means the cancellation request was consumed, not that the observed turn will cancel; confirmation is `turn.cancelled` followed by `session.waiting` on the event stream. `"no_active_turn"` covers an unknown token and a session with nothing to cancel — idle, parked, or already completed.
77
+
78
+ Semantics:
79
+
80
+ - `cancel` never starts a session, sends input, or clears history. The session parks and accepts the next message normally.
81
+ - Pass `turnId` (stamped on every turn-scoped stream event) to guard against stale stop requests. A mismatched guard is consumed as a benign no-op and cannot cancel a newer turn.
82
+ - The helper addresses only this channel's sessions; it cannot cancel a session owned by another channel.
83
+ - Cancellation stops work without replacement input. Partial streamed output and completed side effects remain observable, and active local or remote subagents receive cancellation recursively.
84
+ - The route owns authentication of the inbound stop request, exactly as for `send()`.
85
+
86
+ When you already hold a `Session` — returned by `send()` or `getSession(sessionId)` — call `session.cancel({ turnId? })` to request the same cancellation addressed by session id.
87
+
58
88
  ## CORS
59
89
 
60
90
  Custom HTTP channels leave CORS untouched unless you opt in. Pass `cors: true`
@@ -95,7 +125,7 @@ export default defineChannel({
95
125
  });
96
126
  ```
97
127
 
98
- `WS()` handlers receive the same helpers as HTTP route handlers: `send`, `getSession`, `receive`, `params`, `waitUntil`, and `requestIp`. The returned hooks are eve-owned structural types compatible with Nitro/H3 websocket routing, including `upgrade`, `open`, `message`, `close`, and `error`.
128
+ `WS()` handlers receive the same helpers as HTTP route handlers: `send`, `cancel`, `getSession`, `receive`, `params`, `waitUntil`, and `requestIp`. The returned hooks are eve-owned structural types compatible with Nitro/H3 websocket routing, including `upgrade`, `open`, `message`, `close`, and `error`.
99
129
 
100
130
  ### Node upgrade server escape hatch
101
131
 
@@ -100,6 +100,8 @@ curl -X POST http://127.0.0.1:3000/eve/v1/session/<sessionId>/cancel
100
100
 
101
101
  `"accepted"` means a cancellation hook accepted the request. Confirm cancellation on the stream as `turn.cancelled` followed by `session.waiting`; the session then accepts the next message normally. If the turn is waiting on active local or remote subagents, eve also requests cancellation of every adopted child, recursively, before settling the parent. Each child reports its own cancellation boundary on its child-session stream; the parent does not emit `subagent.completed` for cancelled work. `"no_active_turn"` means no resumable cancellation target exists, including an unknown session or an already-settled turn. Both statuses are success, so clients can fire and forget. See the [eve channel](../channels/eve) for the full route contract.
102
102
 
103
+ Custom channel routes request the same cancellation without knowing the session id: the `cancel` route helper is addressed by the channel-local continuation token, and `Session.cancel()` by session id. See [custom channels](../channels/custom#cancel-a-turn).
104
+
103
105
  ## Reconnect and rewind
104
106
 
105
107
  The stream is durable. Every event is recorded before a step completes, so the whole stream is replayable. A nonnegative `startIndex` is an absolute event count: use it to pick up where you dropped off or pass `0` to rewind to the start.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eve",
3
- "version": "0.24.5",
3
+ "version": "0.24.6",
4
4
  "private": false,
5
5
  "description": "Filesystem-first framework for durable backend AI agents that run anywhere.",
6
6
  "keywords": [
@@ -324,7 +324,7 @@
324
324
  "jsonc-parser": "3.3.1",
325
325
  "just-bash": "3.0.1",
326
326
  "microsandbox": "0.5.5",
327
- "next": "16.2.6",
327
+ "next": "16.3.0-preview.6",
328
328
  "picocolors": "1.1.1",
329
329
  "react": "19.2.6",
330
330
  "react-test-renderer": "19.2.6",