eve 0.24.4 → 0.24.5
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 +24 -0
- package/dist/src/channel/types.d.ts +13 -0
- package/dist/src/chunks/{use-eve-agent-Dwa2j1wE.js → use-eve-agent-8rerxDHY.js} +59 -6
- package/dist/src/chunks/{use-eve-agent-BP9FpQsJ.js → use-eve-agent-DhgdHzDG.js} +59 -6
- package/dist/src/cli/commands/build.d.ts +14 -0
- package/dist/src/cli/commands/build.js +1 -0
- package/dist/src/cli/commands/channels.js +1 -1
- package/dist/src/cli/commands/link.d.ts +6 -5
- package/dist/src/cli/commands/link.js +1 -1
- package/dist/src/cli/run.d.ts +3 -2
- package/dist/src/cli/run.js +1 -1
- package/dist/src/client/index.d.ts +1 -1
- package/dist/src/client/ndjson.js +1 -1
- package/dist/src/client/open-stream.d.ts +3 -2
- package/dist/src/client/open-stream.js +1 -1
- package/dist/src/client/session.d.ts +15 -3
- package/dist/src/client/session.js +1 -1
- package/dist/src/client/types.d.ts +8 -0
- package/dist/src/compiled/.vendor-stamp.json +5 -5
- package/dist/src/compiled/@workflow/core/index.js +2 -2
- package/dist/src/compiled/@workflow/core/runtime/helpers.d.ts +55 -0
- package/dist/src/compiled/@workflow/core/runtime/run-id-time.d.ts +9 -0
- package/dist/src/compiled/@workflow/core/runtime/step-executor.d.ts +2 -0
- package/dist/src/compiled/@workflow/core/runtime/step-latency.d.ts +70 -4
- package/dist/src/compiled/@workflow/core/runtime/suspension-handler.d.ts +10 -1
- package/dist/src/compiled/@workflow/core/runtime.js +3 -3
- package/dist/src/compiled/@workflow/core/step/context-storage.d.ts +6 -0
- package/dist/src/compiled/@workflow/core/telemetry/semantic-conventions.d.ts +25 -0
- package/dist/src/compiled/@workflow/core/version.d.ts +1 -1
- package/dist/src/compiled/@workflow/core/workflow.js +1 -1
- package/dist/src/compiled/@workflow/errors/index.d.ts +16 -0
- package/dist/src/compiled/@workflow/errors/index.js +1 -1
- package/dist/src/compiled/@workflow/world/attributes.d.ts +7 -0
- package/dist/src/compiled/@workflow/world/events.d.ts +16 -0
- package/dist/src/compiled/@workflow/world/index.d.ts +1 -1
- package/dist/src/compiled/@workflow/world-local/index.js +3 -3
- package/dist/src/compiled/@workflow/world-vercel/index.js +16 -16
- package/dist/src/compiled/_chunks/workflow/attribute-changes-DXbmITuI.js +20 -0
- package/dist/src/compiled/_chunks/workflow/{dist-DpDDcpTl.js → dist-BYo8Gno2.js} +1 -1
- package/dist/src/compiled/_chunks/workflow/{dist-Blxnyb7-.js → dist-CSfKNxQW.js} +1 -1
- package/dist/src/compiled/_chunks/workflow/resume-hook-DvvgYsRt.js +1 -0
- package/dist/src/compiled/_chunks/workflow/run-BdvQmV5a.js +1 -0
- package/dist/src/compiled/_chunks/workflow/run-id-BdE0MZz9.js +1 -0
- package/dist/src/compiled/_chunks/workflow/sleep-DzxrwWTs.js +1 -0
- package/dist/src/evals/assertions/run.d.ts +3 -3
- package/dist/src/evals/context.js +1 -1
- package/dist/src/evals/index.d.ts +2 -1
- package/dist/src/evals/match.d.ts +4 -0
- package/dist/src/evals/match.js +1 -1
- package/dist/src/evals/runner/derive-run-facts.js +1 -1
- package/dist/src/evals/session.d.ts +10 -2
- package/dist/src/evals/session.js +1 -1
- package/dist/src/evals/target.js +1 -1
- package/dist/src/evals/types.d.ts +52 -2
- package/dist/src/execution/cancel-descendant-turns-step.d.ts +6 -0
- package/dist/src/execution/cancel-descendant-turns-step.js +1 -0
- package/dist/src/execution/create-session-step.js +1 -1
- package/dist/src/execution/dispatch-runtime-actions-step.js +1 -1
- package/dist/src/execution/dispatch-workflow-runtime-actions-step.js +1 -1
- package/dist/src/execution/node-step.js +1 -1
- package/dist/src/execution/remote-agent-dispatch.d.ts +6 -0
- package/dist/src/execution/remote-agent-dispatch.js +1 -1
- package/dist/src/execution/settle-cancelled-turn-step.js +1 -1
- package/dist/src/execution/subagent-event-proxy-step.js +1 -1
- package/dist/src/execution/turn-cancellation-control.d.ts +0 -13
- package/dist/src/execution/turn-cancellation-control.js +1 -1
- package/dist/src/execution/turn-cancellation-token.d.ts +9 -0
- package/dist/src/execution/turn-cancellation-token.js +1 -0
- package/dist/src/execution/turn-workflow.js +1 -1
- package/dist/src/execution/workflow-runtime.d.ts +3 -1
- package/dist/src/execution/workflow-runtime.js +1 -1
- package/dist/src/execution/workflow-steps.js +1 -1
- package/dist/src/harness/advertised-tools.js +1 -1
- package/dist/src/harness/execute-tool.d.ts +0 -1
- package/dist/src/harness/runtime-actions.d.ts +16 -12
- package/dist/src/harness/runtime-actions.js +1 -1
- package/dist/src/internal/application/build-profile.d.ts +64 -0
- package/dist/src/internal/application/build-profile.js +1 -0
- package/dist/src/internal/application/package.js +1 -1
- package/dist/src/internal/authored-module-loader.d.ts +10 -0
- package/dist/src/internal/authored-module-loader.js +2 -2
- package/dist/src/internal/authored-module-map-loader.js +1 -1
- package/dist/src/internal/materialized-authored-modules.d.ts +2 -4
- package/dist/src/internal/materialized-authored-modules.js +1 -1
- package/dist/src/internal/nitro/dev-runtime-artifacts.js +1 -1
- package/dist/src/internal/nitro/host/build-application.js +1 -1
- package/dist/src/internal/nitro/host/types.d.ts +2 -0
- package/dist/src/internal/nitro/routes/agent-info/build-agent-info-response-from-manifest.js +1 -1
- package/dist/src/internal/nitro/routes/agent-info/build-agent-info-response.d.ts +7 -1
- package/dist/src/internal/nitro/routes/agent-info/build-agent-info-response.js +1 -1
- package/dist/src/internal/nitro/routes/channel-dispatch.js +1 -1
- package/dist/src/internal/nitro/routes/channel-route-context.d.ts +3 -0
- package/dist/src/internal/nitro/routes/channel-route-context.js +1 -1
- package/dist/src/internal/nitro/routes/runtime-stack.js +1 -1
- package/dist/src/internal/nitro/routes/schedule-task.js +1 -1
- package/dist/src/protocol/cancel-turn.d.ts +11 -0
- package/dist/src/protocol/cancel-turn.js +1 -0
- package/dist/src/protocol/routes.d.ts +10 -0
- package/dist/src/protocol/routes.js +1 -1
- package/dist/src/public/channels/eve.d.ts +2 -1
- package/dist/src/public/channels/eve.js +1 -1
- package/dist/src/public/channels/linear/api.d.ts +0 -1
- package/dist/src/public/channels/linear/api.js +17 -22
- package/dist/src/public/channels/linear/linearChannel.js +1 -1
- package/dist/src/public/definitions/channel.d.ts +20 -10
- package/dist/src/public/next/index.js +1 -1
- package/dist/src/public/next/resolve-eve-binary.d.ts +12 -0
- package/dist/src/public/next/resolve-eve-binary.js +1 -0
- package/dist/src/runtime/agent/mock-model-adapter.js +1 -1
- package/dist/src/runtime/framework-tools/agent.d.ts +13 -0
- package/dist/src/runtime/framework-tools/agent.js +1 -0
- package/dist/src/runtime/framework-tools/index.d.ts +7 -2
- package/dist/src/runtime/framework-tools/index.js +1 -1
- package/dist/src/runtime/resolve-agent-graph.js +1 -1
- package/dist/src/runtime/types.d.ts +2 -1
- package/dist/src/setup/boxes/reconcile-host-framework-preset.d.ts +26 -0
- package/dist/src/setup/boxes/reconcile-host-framework-preset.js +1 -0
- package/dist/src/setup/boxes/resolve-provisioning.js +1 -1
- package/dist/src/setup/index.js +1 -1
- package/dist/src/setup/scaffold/create/add-to-project.js +1 -1
- package/dist/src/setup/scaffold/create/project.js +2 -2
- package/dist/src/setup/scaffold/index.d.ts +1 -1
- package/dist/src/setup/scaffold/index.js +1 -1
- package/dist/src/setup/scaffold/update/channels.d.ts +7 -1
- package/dist/src/setup/scaffold/update/channels.js +2 -2
- package/dist/src/setup/scaffold/update/connections.js +3 -3
- package/dist/src/setup/vercel-project-framework.d.ts +12 -0
- package/dist/src/setup/vercel-project-framework.js +1 -1
- package/dist/src/svelte/index.js +1 -1
- package/dist/src/svelte/use-eve-agent.js +1 -1
- package/dist/src/vue/index.js +1 -1
- package/dist/src/vue/use-eve-agent.js +1 -1
- package/docs/channels/eve.mdx +11 -1
- package/docs/concepts/default-harness.md +2 -0
- package/docs/concepts/sessions-runs-and-streaming.md +11 -0
- package/docs/evals/assertions.mdx +2 -2
- package/docs/evals/cases.mdx +31 -0
- package/docs/evals/overview.mdx +1 -1
- package/docs/evals/targets.mdx +2 -1
- package/docs/guides/client/continuations.mdx +2 -0
- package/docs/guides/client/streaming.mdx +17 -1
- package/docs/guides/frontend/overview.mdx +4 -2
- package/docs/guides/frontend/use-eve-agent-svelte.mdx +2 -2
- package/docs/guides/frontend/use-eve-agent-vue.mdx +2 -2
- package/docs/guides/remote-agents.md +2 -0
- package/docs/reference/cli.md +15 -2
- package/docs/subagents.mdx +10 -0
- package/package.json +6 -6
- package/dist/src/compiled/_chunks/workflow/attribute-changes-MGTOG_uX.js +0 -20
- package/dist/src/compiled/_chunks/workflow/resume-hook-DHP5ql3-.js +0 -1
- package/dist/src/compiled/_chunks/workflow/run-D8hv1ptT.js +0 -1
- package/dist/src/compiled/_chunks/workflow/sleep-uA9pS-PT.js +0 -1
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import type { RouteHandlerArgs } from "#channel/routes.js";
|
|
2
|
+
import type { Agent } from "#public/definitions/channel.js";
|
|
2
3
|
type AgentInfoRouteResponse = () => Promise<Response>;
|
|
3
4
|
export declare function attachAgentInfoRouteResponse<TArgs extends RouteHandlerArgs>(args: TArgs, respond: AgentInfoRouteResponse): TArgs;
|
|
4
5
|
export declare function readAgentInfoRouteResponse(args: RouteHandlerArgs): AgentInfoRouteResponse | undefined;
|
|
6
|
+
export declare function attachRouteAgent<TArgs extends RouteHandlerArgs>(args: TArgs, agent: Agent): TArgs;
|
|
7
|
+
export declare function readRouteAgent(args: RouteHandlerArgs): Agent | undefined;
|
|
5
8
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
const agentInfoRouteResponseKey=`__eveAgentInfoRouteResponse`;function attachAgentInfoRouteResponse(
|
|
1
|
+
const agentInfoRouteResponseKey=`__eveAgentInfoRouteResponse`,routeAgentKey=`__eveRouteAgent`;function attachAgentInfoRouteResponse(t,n){let r=t;return r[agentInfoRouteResponseKey]=n,t}function readAgentInfoRouteResponse(t){return t[agentInfoRouteResponseKey]}function attachRouteAgent(e,n){let r=e;return r[routeAgentKey]=n,e}function readRouteAgent(e){return e[routeAgentKey]}export{attachAgentInfoRouteResponse,attachRouteAgent,readAgentInfoRouteResponse,readRouteAgent};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{createWorkflowRuntime}from"#execution/workflow-runtime.js";import{getCompiledRuntimeAgentBundle}from"#runtime/sessions/compiled-agent-cache.js";import{resolveNitroCompiledArtifactsSource}from"#internal/nitro/routes/runtime-artifacts.js";async function resolveNitroChannelRuntimeBundle(e){let t=resolveNitroCompiledArtifactsSource(e),n=await getCompiledRuntimeAgentBundle({compiledArtifactsSource:t}),r=createWorkflowRuntime({compiledArtifactsSource:t});return{channels:n.graph.root.channels,runtime:r}}export{resolveNitroChannelRuntimeBundle};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{createWorkflowRuntime}from"#execution/workflow-runtime.js";import{getCompiledRuntimeAgentBundle}from"#runtime/sessions/compiled-agent-cache.js";import{resolveNitroCompiledArtifactsSource}from"#internal/nitro/routes/runtime-artifacts.js";import{loadResolvedCompiledScheduleByTaskName}from"#runtime/schedules/resolve-schedule.js";import{ScheduleDispatcher,expectScheduleRun}from"#channel/schedule.js";import{loadResolvedModuleExport}from"#runtime/resolve-helpers.js";async function dispatchScheduleTask(e,t){return await dispatchScheduleTaskFromArtifacts(e,resolveNitroCompiledArtifactsSource(t))}async function dispatchScheduleTaskFromArtifacts(n,r){let i=await loadResolvedCompiledScheduleByTaskName(n,{compiledArtifactsSource:r}),a=await getCompiledRuntimeAgentBundle({compiledArtifactsSource:r}),o=new ScheduleDispatcher({runtime:createWorkflowRuntime({compiledArtifactsSource:r}),channels:a.graph.root.channels}),s={scheduleId:i.name};i.hasRun&&(s.run=await loadScheduleRun(i,a.moduleMap)),i.markdown!==void 0&&(s.markdown=i.markdown);let c=await o.trigger(s);return c.waitUntilTasks.length>0&&await Promise.allSettled(c.waitUntilTasks),{scheduleId:i.name,sessionIds:c.sessions.map(e=>e.id)}}async function loadScheduleRun(e,t){if(e.sourceKind!==`module`)throw Error(`Schedule "${e.name}" claims hasRun but is not a module-backed schedule.`);let n=e;return expectScheduleRun(await loadResolvedModuleExport({definition:{exportName:n.exportName,logicalPath:n.logicalPath,sourceId:n.sourceId},kindLabel:`schedule`,moduleMap:t,nodeId:void 0}),n.logicalPath,n.exportName)}export{dispatchScheduleTask,dispatchScheduleTaskFromArtifacts};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { z } from "#compiled/zod/index.js";
|
|
2
|
+
/** Outcome of requesting cooperative turn cancellation. */
|
|
3
|
+
export type CancelTurnStatus = "accepted" | "no_active_turn";
|
|
4
|
+
/** Successful standard turn-cancellation response. */
|
|
5
|
+
export interface CancelTurnResponse {
|
|
6
|
+
readonly ok: true;
|
|
7
|
+
readonly sessionId: string;
|
|
8
|
+
readonly status: CancelTurnStatus;
|
|
9
|
+
}
|
|
10
|
+
/** Successful response returned by the standard turn-cancellation route. */
|
|
11
|
+
export declare const CancelTurnResponseSchema: z.ZodType<CancelTurnResponse>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{z}from"#compiled/zod/index.js";const CancelTurnResponseSchema=z.object({ok:z.literal(!0),sessionId:z.string().min(1),status:z.enum([`accepted`,`no_active_turn`])});export{CancelTurnResponseSchema};
|
|
@@ -26,6 +26,12 @@ export declare const EVE_CONTINUE_SESSION_ROUTE_PATTERN = "/eve/v1/session/:sess
|
|
|
26
26
|
* Stable framework-owned message stream route pattern.
|
|
27
27
|
*/
|
|
28
28
|
export declare const EVE_MESSAGE_STREAM_ROUTE_PATTERN = "/eve/v1/session/:sessionId/stream";
|
|
29
|
+
/**
|
|
30
|
+
* Stable framework-owned route pattern for cancelling a session's
|
|
31
|
+
* in-flight turn. Accepts an optional `{ turnId }` body guard scoping
|
|
32
|
+
* the cancel to the turn the caller observed.
|
|
33
|
+
*/
|
|
34
|
+
export declare const EVE_CANCEL_TURN_ROUTE_PATTERN = "/eve/v1/session/:sessionId/cancel";
|
|
29
35
|
/**
|
|
30
36
|
* Framework-owned route pattern for dispatching one authored schedule
|
|
31
37
|
* exactly once from the dev server.
|
|
@@ -90,6 +96,10 @@ export declare function createEveMessageStreamRoutePath(sessionId: string): stri
|
|
|
90
96
|
* Creates the stable framework-owned continue-session route path.
|
|
91
97
|
*/
|
|
92
98
|
export declare function createEveContinueSessionRoutePath(sessionId: string): string;
|
|
99
|
+
/**
|
|
100
|
+
* Creates the stable framework-owned cancel-turn route path for one session.
|
|
101
|
+
*/
|
|
102
|
+
export declare function createEveCancelTurnRoutePath(sessionId: string): string;
|
|
93
103
|
/**
|
|
94
104
|
* Creates the stable framework-owned connection callback route path for
|
|
95
105
|
* one (`name`, `token`) pair.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
const EVE_ROUTE_PREFIX=`/eve/v1`,EVE_HEALTH_ROUTE_PATH=`${EVE_ROUTE_PREFIX}/health`,EVE_INFO_ROUTE_PATH=`${EVE_ROUTE_PREFIX}/info`,EVE_CREATE_SESSION_ROUTE_PATH=`${EVE_ROUTE_PREFIX}/session`,EVE_CONTINUE_SESSION_ROUTE_PATTERN=`${EVE_ROUTE_PREFIX}/session/:sessionId`,EVE_MESSAGE_STREAM_ROUTE_PATTERN=`${EVE_ROUTE_PREFIX}/session/:sessionId/stream`,EVE_DEV_DISPATCH_SCHEDULE_ROUTE_PATTERN=`${EVE_ROUTE_PREFIX}/dev/schedules/:scheduleId`,EVE_DEV_RUNTIME_ARTIFACTS_ROUTE_PATH=`${EVE_ROUTE_PREFIX}/dev/runtime-artifacts`,EVE_DEV_RUNTIME_ARTIFACTS_REBUILD_ROUTE_PATH=`${EVE_DEV_RUNTIME_ARTIFACTS_ROUTE_PATH}/rebuild`;function createEveDevDispatchSchedulePath(e){return`${EVE_ROUTE_PREFIX}/dev/schedules/${encodeURIComponent(e)}`}const EVE_CONNECTION_CALLBACK_ROUTE_PATTERN=`${EVE_ROUTE_PREFIX}/connections/:name/callback/:token`,EVE_CALLBACK_ROUTE_PATTERN=`${EVE_ROUTE_PREFIX}/callback/:token`;function createEveMessageStreamRoutePath(e){return`${EVE_ROUTE_PREFIX}/session/${encodeURIComponent(e)}/stream`}function createEveContinueSessionRoutePath(e){return`${EVE_ROUTE_PREFIX}/session/${encodeURIComponent(e)}`}function createEveConnectionCallbackRoutePath(e,t){return`${EVE_ROUTE_PREFIX}/connections/${encodeURIComponent(e)}/callback/${encodeURIComponent(t)}`}function createEveCallbackRoutePath(e){return`${EVE_ROUTE_PREFIX}/callback/${encodeURIComponent(e)}`}export{EVE_CALLBACK_ROUTE_PATTERN,EVE_CONNECTION_CALLBACK_ROUTE_PATTERN,EVE_CONTINUE_SESSION_ROUTE_PATTERN,EVE_CREATE_SESSION_ROUTE_PATH,EVE_DEV_DISPATCH_SCHEDULE_ROUTE_PATTERN,EVE_DEV_RUNTIME_ARTIFACTS_REBUILD_ROUTE_PATH,EVE_DEV_RUNTIME_ARTIFACTS_ROUTE_PATH,EVE_HEALTH_ROUTE_PATH,EVE_INFO_ROUTE_PATH,EVE_MESSAGE_STREAM_ROUTE_PATTERN,EVE_ROUTE_PREFIX,createEveCallbackRoutePath,createEveConnectionCallbackRoutePath,createEveContinueSessionRoutePath,createEveDevDispatchSchedulePath,createEveMessageStreamRoutePath};
|
|
1
|
+
const EVE_ROUTE_PREFIX=`/eve/v1`,EVE_HEALTH_ROUTE_PATH=`${EVE_ROUTE_PREFIX}/health`,EVE_INFO_ROUTE_PATH=`${EVE_ROUTE_PREFIX}/info`,EVE_CREATE_SESSION_ROUTE_PATH=`${EVE_ROUTE_PREFIX}/session`,EVE_CONTINUE_SESSION_ROUTE_PATTERN=`${EVE_ROUTE_PREFIX}/session/:sessionId`,EVE_MESSAGE_STREAM_ROUTE_PATTERN=`${EVE_ROUTE_PREFIX}/session/:sessionId/stream`,EVE_CANCEL_TURN_ROUTE_PATTERN=`${EVE_ROUTE_PREFIX}/session/:sessionId/cancel`,EVE_DEV_DISPATCH_SCHEDULE_ROUTE_PATTERN=`${EVE_ROUTE_PREFIX}/dev/schedules/:scheduleId`,EVE_DEV_RUNTIME_ARTIFACTS_ROUTE_PATH=`${EVE_ROUTE_PREFIX}/dev/runtime-artifacts`,EVE_DEV_RUNTIME_ARTIFACTS_REBUILD_ROUTE_PATH=`${EVE_DEV_RUNTIME_ARTIFACTS_ROUTE_PATH}/rebuild`;function createEveDevDispatchSchedulePath(e){return`${EVE_ROUTE_PREFIX}/dev/schedules/${encodeURIComponent(e)}`}const EVE_CONNECTION_CALLBACK_ROUTE_PATTERN=`${EVE_ROUTE_PREFIX}/connections/:name/callback/:token`,EVE_CALLBACK_ROUTE_PATTERN=`${EVE_ROUTE_PREFIX}/callback/:token`;function createEveMessageStreamRoutePath(e){return`${EVE_ROUTE_PREFIX}/session/${encodeURIComponent(e)}/stream`}function createEveContinueSessionRoutePath(e){return`${EVE_ROUTE_PREFIX}/session/${encodeURIComponent(e)}`}function createEveCancelTurnRoutePath(e){return`${EVE_ROUTE_PREFIX}/session/${encodeURIComponent(e)}/cancel`}function createEveConnectionCallbackRoutePath(e,t){return`${EVE_ROUTE_PREFIX}/connections/${encodeURIComponent(e)}/callback/${encodeURIComponent(t)}`}function createEveCallbackRoutePath(e){return`${EVE_ROUTE_PREFIX}/callback/${encodeURIComponent(e)}`}export{EVE_CALLBACK_ROUTE_PATTERN,EVE_CANCEL_TURN_ROUTE_PATTERN,EVE_CONNECTION_CALLBACK_ROUTE_PATTERN,EVE_CONTINUE_SESSION_ROUTE_PATTERN,EVE_CREATE_SESSION_ROUTE_PATH,EVE_DEV_DISPATCH_SCHEDULE_ROUTE_PATTERN,EVE_DEV_RUNTIME_ARTIFACTS_REBUILD_ROUTE_PATH,EVE_DEV_RUNTIME_ARTIFACTS_ROUTE_PATH,EVE_HEALTH_ROUTE_PATH,EVE_INFO_ROUTE_PATH,EVE_MESSAGE_STREAM_ROUTE_PATTERN,EVE_ROUTE_PREFIX,createEveCallbackRoutePath,createEveCancelTurnRoutePath,createEveConnectionCallbackRoutePath,createEveContinueSessionRoutePath,createEveDevDispatchSchedulePath,createEveMessageStreamRoutePath};
|
|
@@ -105,7 +105,8 @@ export interface EveChannel extends Channel {
|
|
|
105
105
|
/**
|
|
106
106
|
* Builds the default eve HTTP channel: a {@link defineChannel} instance serving the
|
|
107
107
|
* built-in `/eve/v1` routes (GET inspects the agent, POST creates a session, POST
|
|
108
|
-
* delivers a follow-up, GET streams a session's
|
|
108
|
+
* delivers a follow-up, POST cancels the in-flight turn, GET streams a session's
|
|
109
|
+
* NDJSON event feed). Every route
|
|
109
110
|
* runs {@link EveChannelInput.auth} via {@link routeAuth} before dispatching.
|
|
110
111
|
* Default-export the result as your `agent/channels/eve.ts` channel; reach for
|
|
111
112
|
* {@link defineChannel} directly only for a custom transport.
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{createLogger,logError}from"#internal/logging.js";import{hasInternalRefScheme}from"#internal/attachments/url-refs.js";import{EVE_INFO_ROUTE_PATH}from"#protocol/routes.js";import{EVE_MESSAGE_STREAM_CONTENT_TYPE,EVE_MESSAGE_STREAM_FORMAT,EVE_MESSAGE_STREAM_VERSION,EVE_SESSION_ID_HEADER,EVE_STREAM_FORMAT_HEADER,EVE_STREAM_VERSION_HEADER}from"#protocol/message.js";import{isInputResponse}from"#runtime/input/types.js";import{parseJsonObject}from"#shared/json.js";import{GET,POST,defineChannel}from"#public/definitions/channel.js";import"ai";import{parseSessionCallback}from"#channel/session-callback.js";import{readAgentInfoRouteResponse}from"#internal/nitro/routes/channel-route-context.js";import{routeAuth}from"#public/channels/auth.js";import{collectUploadPolicyViolations,formatUploadPolicyViolation,mergeUploadPolicy}from"#public/channels/upload-policy.js";const log=createLogger(`eve.channel`);function defaultEveAuth(e){return e.eve.caller}function eveChannel(e){let t=mergeUploadPolicy(e.uploadPolicy);return defineChannel({cors:normalizeEveCors(e.cors),routes:[GET(EVE_INFO_ROUTE_PATH,async(t,n)=>{let r=await routeAuth(t,e.auth);if(r instanceof Response)return r;let i=readAgentInfoRouteResponse(n);return i===void 0?Response.json({error:`Agent info route requires internal channel dispatch context.`,ok:!1},{status:500}):await i()}),POST(`/eve/v1/session`,async(n,{send:r})=>{let i=await routeAuth(n,e.auth);if(i instanceof Response)return i;let a=i,o;try{o=await n.json()}catch{return Response.json({error:`Invalid JSON body.`,ok:!1},{status:400})}if(typeof o!=`object`||!o)return Response.json({error:`Expected a JSON object.`,ok:!1},{status:400});let s=parseCreateBody(o);if(s instanceof Response)return s;let c=checkUploadPolicy(s,t);if(c!==null)return c;let l=await resolveOnMessage({auth:a,config:e,message:s.message,request:n});if(l instanceof Response)return l;if(!l.dispatch)return droppedMessageResponse();let u=`eve:${crypto.randomUUID()}`,d=await r(createSendPayload(s,mergeContext(s.context,l.context)),{auth:l.auth,callback:s.callback,continuationToken:u,mode:s.mode});return Response.json({continuationToken:d.continuationToken,ok:!0,sessionId:d.id},{headers:{"cache-control":`no-store`,[EVE_SESSION_ID_HEADER]:d.id},status:202})}),POST(`/eve/v1/session/:sessionId`,async(n,{send:r,getSession:i,params:a})=>{let o=await routeAuth(n,e.auth);if(o instanceof Response)return o;let s=o,c=a.sessionId;if(!c)return Response.json({error:`Missing session id.`,ok:!1},{status:400});try{i(c)}catch{return Response.json({error:`Session not found.`,ok:!1},{status:404})}let l;try{l=await n.json()}catch{return Response.json({error:`Invalid JSON body.`,ok:!1},{status:400})}if(typeof l!=`object`||!l)return Response.json({error:`Expected a JSON object.`,ok:!1},{status:400});let u=parseContinueBody(l);if(u instanceof Response)return u;let d=checkUploadPolicy(u,t);if(d!==null)return d;let f=u.context,p=s;if(u.message!==void 0){let t=await resolveOnMessage({auth:s,config:e,message:u.message,request:n,sessionId:c});if(t instanceof Response)return t;if(!t.dispatch)return droppedMessageResponse();f=mergeContext(u.context,t.context),p=t.auth}let m=await r({inputResponses:u.inputResponses,message:u.message,context:f,outputSchema:u.outputSchema},{auth:p,continuationToken:u.continuationToken});return Response.json({ok:!0,sessionId:m.id},{headers:{"cache-control":`no-store`,[EVE_SESSION_ID_HEADER]:m.id},status:200})}),GET(`/eve/v1/session/:sessionId/stream`,async(t,{getSession:n,params:r})=>{let l=await routeAuth(t,e.auth);if(l instanceof Response)return l;let u=r.sessionId;if(!u)return Response.json({error:`Missing session id.`,ok:!1},{status:400});let d=parseStartIndex(t);if(d instanceof Response)return d;try{let e=serializeAsNdjson(await n(u).getEventStream({startIndex:d}));return new Response(e,{headers:{"cache-control":`no-store, no-transform`,"content-type":EVE_MESSAGE_STREAM_CONTENT_TYPE,"x-accel-buffering":`no`,[EVE_SESSION_ID_HEADER]:u,[EVE_STREAM_FORMAT_HEADER]:EVE_MESSAGE_STREAM_FORMAT,[EVE_STREAM_VERSION_HEADER]:EVE_MESSAGE_STREAM_VERSION}})}catch{return Response.json({error:`Session not found.`,ok:!1},{status:404})}})],events:e.events})}function normalizeEveCors(e){if(e===void 0||e===!1)return!1;if(e===!0)return!0;let t={};return e.origin!==void 0&&(t.origin=normalizeEveCorsOrigin(e.origin)),e.methods!==void 0&&(t.methods=e.methods),e.allowedHeaders!==void 0&&(t.allowHeaders=e.allowedHeaders),e.exposedHeaders!==void 0&&(t.exposeHeaders=e.exposedHeaders),e.credentials!==void 0&&(t.credentials=e.credentials),e.maxAge!==void 0&&(t.maxAge=e.maxAge),e.preflightStatus!==void 0&&(t.preflight={statusCode:e.preflightStatus}),t}function normalizeEveCorsOrigin(e){return e===`*`||e===`null`?e:typeof e==`string`?[e]:e}async function resolveOnMessage(e){let n=e.config.onMessage??defaultOnMessage,r;try{r=await n({eve:e.sessionId===void 0?{caller:e.auth,request:e.request}:{caller:e.auth,request:e.request,sessionId:e.sessionId}},e.message)}catch(n){let r=logError(log,`onMessage handler failed`,n,{sessionId:e.sessionId});return Response.json({error:`onMessage handler failed.`,errorId:r,ok:!1},{status:500})}return r==null?{dispatch:!1}:r.context===void 0?{auth:r.auth,dispatch:!0}:{auth:r.auth,context:r.context,dispatch:!0}}function defaultOnMessage(e){return{auth:defaultEveAuth(e)}}function droppedMessageResponse(){return new Response(null,{headers:{"cache-control":`no-store`},status:204})}function parseCreateBody(e){let t=parseMessageField(e.message);if(t instanceof Response)return t;let n=parseClientContextField(e.clientContext);if(n instanceof Response)return n;let r=parseCallbackField(e.callback);if(r instanceof Response)return r;let i=parseModeField(e.mode);if(i instanceof Response)return i;let a=parseOutputSchemaField(e.outputSchema);return a instanceof Response?a:t===void 0?Response.json({error:`Missing or empty 'message' field.`,ok:!1},{status:400}):{callback:r,message:t,mode:i,context:n,outputSchema:a}}function parseContinueBody(e){let t=typeof e.continuationToken==`string`&&e.continuationToken.length>0?e.continuationToken:void 0;if(t===void 0)return Response.json({error:`Missing or empty 'continuationToken' field.`,ok:!1},{status:400});let n=parseMessageField(e.message);if(n instanceof Response)return n;let r=parseInputResponses(e.inputResponses);if(r instanceof Response)return r;let i=parseClientContextField(e.clientContext);if(i instanceof Response)return i;let a=parseOutputSchemaField(e.outputSchema);return a instanceof Response?a:n===void 0&&r===void 0?Response.json({error:`Expected a non-empty 'message', a non-empty 'inputResponses' array, or both.`,ok:!1},{status:400}):{message:n,continuationToken:t,inputResponses:r,context:i,outputSchema:a}}function createSendPayload(e,t=e.context){if(t===void 0&&e.outputSchema===void 0)return e.message;let n={message:e.message};return t!==void 0&&(n.context=t),e.outputSchema!==void 0&&(n.outputSchema=e.outputSchema),n}function parseOutputSchemaField(e){if(e!==void 0)try{return parseJsonObject(e)}catch{return Response.json({error:`Expected 'outputSchema' to be a JSON-serializable object.`,ok:!1},{status:400})}}function parseCallbackField(e){if(e===void 0)return;let t=parseSessionCallback(e);return t.ok?t.callback:Response.json({error:t.message,ok:!1},{status:400})}function parseModeField(e){if(e!==void 0)return e===`conversation`||e===`task`?e:Response.json({error:`Expected 'mode' to be either 'conversation' or 'task'.`,ok:!1},{status:400})}function parseMessageField(e){if(e===void 0)return;if(typeof e==`string`)return e.length>0?e:void 0;if(!Array.isArray(e))return Response.json({error:`Expected 'message' to be a string or an array of text/file parts.`,ok:!1},{status:400});if(e.length===0)return;let t=[];for(let n of e){let e=parseMessagePart(n);if(e instanceof Response)return e;t.push(e)}return t}function parseMessagePart(e){if(typeof e!=`object`||!e)return Response.json({error:`Expected each message part to be an object.`,ok:!1},{status:400});let t=e;if(t.type===`text`)return typeof t.text!=`string`||t.text.length===0?Response.json({error:`Text parts require a non-empty 'text' string.`,ok:!1},{status:400}):{type:`text`,text:t.text};if(t.type===`file`){if(typeof t.mediaType!=`string`||t.mediaType.length===0)return Response.json({error:`File parts require a non-empty 'mediaType' string.`,ok:!1},{status:400});if(typeof t.data!=`string`)return Response.json({error:`File parts require a 'data' string (base64, data URL, or URL).`,ok:!1},{status:400});if(hasInternalRefScheme(t.data))return Response.json({error:`File part 'data' must not use a framework-internal ref scheme.`,ok:!1},{status:400});let e={type:`file`,mediaType:t.mediaType,data:t.data};return typeof t.filename==`string`&&t.filename.length>0&&(e.filename=t.filename),e}return Response.json({error:`Unsupported message part type "${String(t.type)}". Use 'text' or 'file'.`,ok:!1},{status:400})}function checkUploadPolicy(e,t){if(!e.message)return null;let n=collectUploadPolicyViolations(e.message,t);if(n.length===0)return null;let[r]=n;if(!r)return null;let i=r.kind===`too-large`?413:415;return Response.json({error:formatUploadPolicyViolation(r),ok:!1,violations:n.map(e=>e.kind===`too-large`?{byteLength:e.byteLength,filename:e.filename,kind:e.kind,limit:e.limit,mediaType:e.mediaType}:{allowedMediaTypes:e.allowedMediaTypes,filename:e.filename,kind:e.kind,mediaType:e.mediaType})},{status:i})}function parseInputResponses(e){if(e===void 0)return;if(!Array.isArray(e)||e.length===0)return Response.json({error:`Expected 'inputResponses' to be a non-empty array.`,ok:!1},{status:400});let t=e.filter(isInputResponse);return t.length===e.length?t:Response.json({error:`Expected every 'inputResponses' entry to match the HITL response schema.`,ok:!1},{status:400})}function mergeContext(e,t){return e===void 0?t:t===void 0?e:[...e,...t]}function parseClientContextField(e){if(e!==void 0){if(typeof e==`string`)return e.length>0?[toClientContextMessage(e)]:void 0;if(Array.isArray(e))return e.length===0?void 0:e.every(e=>typeof e==`string`&&e.length>0)?e.map(e=>toClientContextMessage(e)):Response.json({error:`Expected 'clientContext' array entries to be non-empty strings.`,ok:!1},{status:400});if(typeof e!=`object`||!e)return Response.json({error:`Expected 'clientContext' to be a string, string array, or JSON object.`,ok:!1},{status:400});try{let t=parseJsonObject(e);return[toClientContextMessage(JSON.stringify(t))]}catch{return Response.json({error:`Expected 'clientContext' to be a JSON-serializable object.`,ok:!1},{status:400})}}}function toClientContextMessage(e){return`Client context:
|
|
1
|
+
import{createLogger,logError}from"#internal/logging.js";import{hasInternalRefScheme}from"#internal/attachments/url-refs.js";import{EVE_CANCEL_TURN_ROUTE_PATTERN,EVE_INFO_ROUTE_PATH}from"#protocol/routes.js";import{EVE_MESSAGE_STREAM_CONTENT_TYPE,EVE_MESSAGE_STREAM_FORMAT,EVE_MESSAGE_STREAM_VERSION,EVE_SESSION_ID_HEADER,EVE_STREAM_FORMAT_HEADER,EVE_STREAM_VERSION_HEADER}from"#protocol/message.js";import{isInputResponse}from"#runtime/input/types.js";import{parseJsonObject}from"#shared/json.js";import{GET,POST,defineChannel}from"#public/definitions/channel.js";import"ai";import{parseSessionCallback}from"#channel/session-callback.js";import{readAgentInfoRouteResponse,readRouteAgent}from"#internal/nitro/routes/channel-route-context.js";import{routeAuth}from"#public/channels/auth.js";import{collectUploadPolicyViolations,formatUploadPolicyViolation,mergeUploadPolicy}from"#public/channels/upload-policy.js";const log=createLogger(`eve.channel`);function defaultEveAuth(e){return e.eve.caller}function eveChannel(e){let n=mergeUploadPolicy(e.uploadPolicy);return defineChannel({cors:normalizeEveCors(e.cors),routes:[GET(EVE_INFO_ROUTE_PATH,async(t,n)=>{let r=await routeAuth(t,e.auth);if(r instanceof Response)return r;let i=readAgentInfoRouteResponse(n);return i===void 0?Response.json({error:`Agent info route requires internal channel dispatch context.`,ok:!1},{status:500}):await i()}),POST(`/eve/v1/session`,async(t,{send:r})=>{let i=await routeAuth(t,e.auth);if(i instanceof Response)return i;let a=i,o;try{o=await t.json()}catch{return Response.json({error:`Invalid JSON body.`,ok:!1},{status:400})}if(typeof o!=`object`||!o)return Response.json({error:`Expected a JSON object.`,ok:!1},{status:400});let s=parseCreateBody(o);if(s instanceof Response)return s;let c=checkUploadPolicy(s,n);if(c!==null)return c;let l=await resolveOnMessage({auth:a,config:e,message:s.message,request:t});if(l instanceof Response)return l;if(!l.dispatch)return droppedMessageResponse();let u=`eve:${crypto.randomUUID()}`,d=await r(createSendPayload(s,mergeContext(s.context,l.context)),{auth:l.auth,callback:s.callback,continuationToken:u,mode:s.mode});return Response.json({continuationToken:d.continuationToken,ok:!0,sessionId:d.id},{headers:{"cache-control":`no-store`,[EVE_SESSION_ID_HEADER]:d.id},status:202})}),POST(`/eve/v1/session/:sessionId`,async(t,{send:r,getSession:i,params:a})=>{let o=await routeAuth(t,e.auth);if(o instanceof Response)return o;let s=o,c=a.sessionId;if(!c)return Response.json({error:`Missing session id.`,ok:!1},{status:400});try{i(c)}catch{return Response.json({error:`Session not found.`,ok:!1},{status:404})}let l;try{l=await t.json()}catch{return Response.json({error:`Invalid JSON body.`,ok:!1},{status:400})}if(typeof l!=`object`||!l)return Response.json({error:`Expected a JSON object.`,ok:!1},{status:400});let u=parseContinueBody(l);if(u instanceof Response)return u;let d=checkUploadPolicy(u,n);if(d!==null)return d;let f=u.context,p=s;if(u.message!==void 0){let n=await resolveOnMessage({auth:s,config:e,message:u.message,request:t,sessionId:c});if(n instanceof Response)return n;if(!n.dispatch)return droppedMessageResponse();f=mergeContext(u.context,n.context),p=n.auth}let m=await r({inputResponses:u.inputResponses,message:u.message,context:f,outputSchema:u.outputSchema},{auth:p,continuationToken:u.continuationToken});return Response.json({ok:!0,sessionId:m.id},{headers:{"cache-control":`no-store`,[EVE_SESSION_ID_HEADER]:m.id},status:200})}),POST(EVE_CANCEL_TURN_ROUTE_PATTERN,async(n,r)=>{let i=await routeAuth(n,e.auth);if(i instanceof Response)return i;let a=r.params.sessionId;if(!a)return Response.json({error:`Missing session id.`,ok:!1},{status:400});let o=await parseCancelTurnBody(n);if(o instanceof Response)return o;let s;try{let e=readRouteAgent(r);if(e===void 0)throw Error(`Missing route agent.`);s=await e.cancelTurn({sessionId:a,turnId:o.turnId})}catch(e){let n=logError(log,`cancel-turn request failed`,e,{sessionId:a});return Response.json({error:`Failed to cancel the turn.`,errorId:n,ok:!1},{status:500})}return Response.json({ok:!0,sessionId:a,status:s.status},{headers:{"cache-control":`no-store`,[EVE_SESSION_ID_HEADER]:a},status:202})}),GET(`/eve/v1/session/:sessionId/stream`,async(t,{getSession:n,params:r})=>{let i=await routeAuth(t,e.auth);if(i instanceof Response)return i;let u=r.sessionId;if(!u)return Response.json({error:`Missing session id.`,ok:!1},{status:400});let d=parseStartIndex(t);if(d instanceof Response)return d;try{let e=serializeAsNdjson(await n(u).getEventStream({startIndex:d}));return new Response(e,{headers:{"cache-control":`no-store, no-transform`,"content-type":EVE_MESSAGE_STREAM_CONTENT_TYPE,"x-accel-buffering":`no`,[EVE_SESSION_ID_HEADER]:u,[EVE_STREAM_FORMAT_HEADER]:EVE_MESSAGE_STREAM_FORMAT,[EVE_STREAM_VERSION_HEADER]:EVE_MESSAGE_STREAM_VERSION}})}catch{return Response.json({error:`Session not found.`,ok:!1},{status:404})}})],events:e.events})}function normalizeEveCors(e){if(e===void 0||e===!1)return!1;if(e===!0)return!0;let t={};return e.origin!==void 0&&(t.origin=normalizeEveCorsOrigin(e.origin)),e.methods!==void 0&&(t.methods=e.methods),e.allowedHeaders!==void 0&&(t.allowHeaders=e.allowedHeaders),e.exposedHeaders!==void 0&&(t.exposeHeaders=e.exposedHeaders),e.credentials!==void 0&&(t.credentials=e.credentials),e.maxAge!==void 0&&(t.maxAge=e.maxAge),e.preflightStatus!==void 0&&(t.preflight={statusCode:e.preflightStatus}),t}function normalizeEveCorsOrigin(e){return e===`*`||e===`null`?e:typeof e==`string`?[e]:e}async function resolveOnMessage(e){let n=e.config.onMessage??defaultOnMessage,r;try{r=await n({eve:e.sessionId===void 0?{caller:e.auth,request:e.request}:{caller:e.auth,request:e.request,sessionId:e.sessionId}},e.message)}catch(n){let r=logError(log,`onMessage handler failed`,n,{sessionId:e.sessionId});return Response.json({error:`onMessage handler failed.`,errorId:r,ok:!1},{status:500})}return r==null?{dispatch:!1}:r.context===void 0?{auth:r.auth,dispatch:!0}:{auth:r.auth,context:r.context,dispatch:!0}}function defaultOnMessage(e){return{auth:defaultEveAuth(e)}}function droppedMessageResponse(){return new Response(null,{headers:{"cache-control":`no-store`},status:204})}function parseCreateBody(e){let t=parseMessageField(e.message);if(t instanceof Response)return t;let n=parseClientContextField(e.clientContext);if(n instanceof Response)return n;let r=parseCallbackField(e.callback);if(r instanceof Response)return r;let i=parseModeField(e.mode);if(i instanceof Response)return i;let a=parseOutputSchemaField(e.outputSchema);return a instanceof Response?a:t===void 0?Response.json({error:`Missing or empty 'message' field.`,ok:!1},{status:400}):{callback:r,message:t,mode:i,context:n,outputSchema:a}}function parseContinueBody(e){let t=typeof e.continuationToken==`string`&&e.continuationToken.length>0?e.continuationToken:void 0;if(t===void 0)return Response.json({error:`Missing or empty 'continuationToken' field.`,ok:!1},{status:400});let n=parseMessageField(e.message);if(n instanceof Response)return n;let r=parseInputResponses(e.inputResponses);if(r instanceof Response)return r;let i=parseClientContextField(e.clientContext);if(i instanceof Response)return i;let a=parseOutputSchemaField(e.outputSchema);return a instanceof Response?a:n===void 0&&r===void 0?Response.json({error:`Expected a non-empty 'message', a non-empty 'inputResponses' array, or both.`,ok:!1},{status:400}):{message:n,continuationToken:t,inputResponses:r,context:i,outputSchema:a}}async function parseCancelTurnBody(e){let t;try{t=await e.text()}catch{return Response.json({error:`Unreadable request body.`,ok:!1},{status:400})}if(t.trim().length===0)return{};let n;try{n=JSON.parse(t)}catch{return Response.json({error:`Invalid JSON body.`,ok:!1},{status:400})}if(typeof n!=`object`||!n||Array.isArray(n))return Response.json({error:`Expected a JSON object.`,ok:!1},{status:400});let r=n.turnId;return r===void 0?{}:typeof r!=`string`||r.length===0?Response.json({error:`Expected 'turnId' to be a non-empty string.`,ok:!1},{status:400}):{turnId:r}}function createSendPayload(e,t=e.context){if(t===void 0&&e.outputSchema===void 0)return e.message;let n={message:e.message};return t!==void 0&&(n.context=t),e.outputSchema!==void 0&&(n.outputSchema=e.outputSchema),n}function parseOutputSchemaField(e){if(e!==void 0)try{return parseJsonObject(e)}catch{return Response.json({error:`Expected 'outputSchema' to be a JSON-serializable object.`,ok:!1},{status:400})}}function parseCallbackField(e){if(e===void 0)return;let t=parseSessionCallback(e);return t.ok?t.callback:Response.json({error:t.message,ok:!1},{status:400})}function parseModeField(e){if(e!==void 0)return e===`conversation`||e===`task`?e:Response.json({error:`Expected 'mode' to be either 'conversation' or 'task'.`,ok:!1},{status:400})}function parseMessageField(e){if(e===void 0)return;if(typeof e==`string`)return e.length>0?e:void 0;if(!Array.isArray(e))return Response.json({error:`Expected 'message' to be a string or an array of text/file parts.`,ok:!1},{status:400});if(e.length===0)return;let t=[];for(let n of e){let e=parseMessagePart(n);if(e instanceof Response)return e;t.push(e)}return t}function parseMessagePart(e){if(typeof e!=`object`||!e)return Response.json({error:`Expected each message part to be an object.`,ok:!1},{status:400});let t=e;if(t.type===`text`)return typeof t.text!=`string`||t.text.length===0?Response.json({error:`Text parts require a non-empty 'text' string.`,ok:!1},{status:400}):{type:`text`,text:t.text};if(t.type===`file`){if(typeof t.mediaType!=`string`||t.mediaType.length===0)return Response.json({error:`File parts require a non-empty 'mediaType' string.`,ok:!1},{status:400});if(typeof t.data!=`string`)return Response.json({error:`File parts require a 'data' string (base64, data URL, or URL).`,ok:!1},{status:400});if(hasInternalRefScheme(t.data))return Response.json({error:`File part 'data' must not use a framework-internal ref scheme.`,ok:!1},{status:400});let e={type:`file`,mediaType:t.mediaType,data:t.data};return typeof t.filename==`string`&&t.filename.length>0&&(e.filename=t.filename),e}return Response.json({error:`Unsupported message part type "${String(t.type)}". Use 'text' or 'file'.`,ok:!1},{status:400})}function checkUploadPolicy(e,t){if(!e.message)return null;let n=collectUploadPolicyViolations(e.message,t);if(n.length===0)return null;let[r]=n;if(!r)return null;let i=r.kind===`too-large`?413:415;return Response.json({error:formatUploadPolicyViolation(r),ok:!1,violations:n.map(e=>e.kind===`too-large`?{byteLength:e.byteLength,filename:e.filename,kind:e.kind,limit:e.limit,mediaType:e.mediaType}:{allowedMediaTypes:e.allowedMediaTypes,filename:e.filename,kind:e.kind,mediaType:e.mediaType})},{status:i})}function parseInputResponses(e){if(e===void 0)return;if(!Array.isArray(e)||e.length===0)return Response.json({error:`Expected 'inputResponses' to be a non-empty array.`,ok:!1},{status:400});let t=e.filter(isInputResponse);return t.length===e.length?t:Response.json({error:`Expected every 'inputResponses' entry to match the HITL response schema.`,ok:!1},{status:400})}function mergeContext(e,t){return e===void 0?t:t===void 0?e:[...e,...t]}function parseClientContextField(e){if(e!==void 0){if(typeof e==`string`)return e.length>0?[toClientContextMessage(e)]:void 0;if(Array.isArray(e))return e.length===0?void 0:e.every(e=>typeof e==`string`&&e.length>0)?e.map(e=>toClientContextMessage(e)):Response.json({error:`Expected 'clientContext' array entries to be non-empty strings.`,ok:!1},{status:400});if(typeof e!=`object`||!e)return Response.json({error:`Expected 'clientContext' to be a string, string array, or JSON object.`,ok:!1},{status:400});try{let t=parseJsonObject(e);return[toClientContextMessage(JSON.stringify(t))]}catch{return Response.json({error:`Expected 'clientContext' to be a JSON-serializable object.`,ok:!1},{status:400})}}}function toClientContextMessage(e){return`Client context:
|
|
2
2
|
${e}`}function parseStartIndex(e){let t=new URL(e.url).searchParams.get(`startIndex`);if(t===null)return;let n=Number(t);return!/^-?\d+$/.test(t)||!Number.isSafeInteger(n)?Response.json({error:`Expected startIndex to be an integer.`,ok:!1},{status:400}):n}function serializeAsNdjson(e){let t=new TextEncoder;return e.pipeThrough(new TransformStream({transform(e,n){n.enqueue(t.encode(`${JSON.stringify(e)}\n`))}}))}export{defaultEveAuth,eveChannel};
|
|
@@ -1,4 +1,15 @@
|
|
|
1
|
-
import{isObject}from"#shared/guards.js";import{parseJsonObject}from"#shared/json.js";import{resolveLinearAccessToken}from"#public/channels/linear/auth.js";
|
|
1
|
+
import{isObject}from"#shared/guards.js";import{parseJsonObject}from"#shared/json.js";import{resolveLinearAccessToken}from"#public/channels/linear/auth.js";const AGENT_SESSION_FIELDS=`
|
|
2
|
+
fragment AgentSessionFields on AgentSession {
|
|
3
|
+
id
|
|
4
|
+
appUser { id }
|
|
5
|
+
comment { id }
|
|
6
|
+
creator { id }
|
|
7
|
+
issue { id identifier title url }
|
|
8
|
+
sourceComment { id }
|
|
9
|
+
status
|
|
10
|
+
url
|
|
11
|
+
}
|
|
12
|
+
`;var LinearApiError=class extends Error{body;queryName;status;constructor(e){super(`Linear GraphQL ${e.queryName} failed with HTTP ${e.status}.`),this.name=`LinearApiError`,this.body=e.body,this.queryName=e.queryName,this.status=e.status}};async function callLinearGraphQL(t){let r=t.api?.fetch??fetch,i=await resolveLinearAccessToken(t.credentials?.accessToken),a=await r(t.api?.apiBaseUrl??`https://api.linear.app/graphql`,{body:JSON.stringify({query:t.query,variables:t.variables??{}}),headers:{authorization:`Bearer ${i}`,"content-type":`application/json; charset=utf-8`},method:`POST`}),o=await parseResponseBody(a);if(!a.ok||hasGraphQLErrors(o)||!isObject(o)||!isObject(o.data))throw new LinearApiError({body:o,queryName:t.queryName,status:a.status});return o.data}async function createLinearAgentActivity(e){let n=(await callLinearGraphQL({api:e.api,credentials:e.credentials,query:`
|
|
2
13
|
mutation AgentActivityCreate($input: AgentActivityCreateInput!) {
|
|
3
14
|
agentActivityCreate(input: $input) {
|
|
4
15
|
success
|
|
@@ -16,37 +27,21 @@ import{isObject}from"#shared/guards.js";import{parseJsonObject}from"#shared/json
|
|
|
16
27
|
agentSessionCreateOnIssue(input: $input) {
|
|
17
28
|
success
|
|
18
29
|
agentSession {
|
|
19
|
-
|
|
20
|
-
appUserId
|
|
21
|
-
commentId
|
|
22
|
-
creator { id }
|
|
23
|
-
issue { id identifier title url }
|
|
24
|
-
issueId
|
|
25
|
-
organizationId
|
|
26
|
-
sourceCommentId
|
|
27
|
-
status
|
|
28
|
-
url
|
|
30
|
+
...AgentSessionFields
|
|
29
31
|
}
|
|
30
32
|
}
|
|
31
33
|
}
|
|
34
|
+
${AGENT_SESSION_FIELDS}
|
|
32
35
|
`,queryName:`AgentSessionCreateOnIssue`,variables:{input:parseJsonObject({externalLink:e.externalLink,externalUrls:e.externalUrls,issueId:e.issueId})}})).agentSessionCreateOnIssue?.agentSession)}async function createLinearAgentSessionOnComment(e){return normalizeAgentSessionRecord((await callLinearGraphQL({api:e.api,credentials:e.credentials,query:`
|
|
33
36
|
mutation AgentSessionCreateOnComment($input: AgentSessionCreateOnComment!) {
|
|
34
37
|
agentSessionCreateOnComment(input: $input) {
|
|
35
38
|
success
|
|
36
39
|
agentSession {
|
|
37
|
-
|
|
38
|
-
appUserId
|
|
39
|
-
commentId
|
|
40
|
-
creator { id }
|
|
41
|
-
issue { id identifier title url }
|
|
42
|
-
issueId
|
|
43
|
-
organizationId
|
|
44
|
-
sourceCommentId
|
|
45
|
-
status
|
|
46
|
-
url
|
|
40
|
+
...AgentSessionFields
|
|
47
41
|
}
|
|
48
42
|
}
|
|
49
43
|
}
|
|
44
|
+
${AGENT_SESSION_FIELDS}
|
|
50
45
|
`,queryName:`AgentSessionCreateOnComment`,variables:{input:parseJsonObject({commentId:e.commentId,externalLink:e.externalLink,externalUrls:e.externalUrls})}})).agentSessionCreateOnComment?.agentSession)}async function listLinearAgentSessionActivities(e){let t=(await callLinearGraphQL({api:e.api,credentials:e.credentials,query:`
|
|
51
46
|
query AgentSessionActivities($id: String!, $last: Int!) {
|
|
52
47
|
agentSession(id: $id) {
|
|
@@ -66,4 +61,4 @@ import{isObject}from"#shared/guards.js";import{parseJsonObject}from"#shared/json
|
|
|
66
61
|
}
|
|
67
62
|
}
|
|
68
63
|
}
|
|
69
|
-
`,queryName:`AgentSessionActivities`,variables:{id:e.agentSessionId,last:e.last??20}})).agentSession?.activities?.nodes;return Array.isArray(t)?t.map(normalizeAgentActivityRecord).filter(notNull):[]}function normalizeAgentSessionRecord(t){if(!isObject(t)||typeof t.id!=`string`)throw Error(`linearChannel: Linear Agent Session response was malformed.`);let n=
|
|
64
|
+
`,queryName:`AgentSessionActivities`,variables:{id:e.agentSessionId,last:e.last??20}})).agentSession?.activities?.nodes;return Array.isArray(t)?t.map(normalizeAgentActivityRecord).filter(notNull):[]}function normalizeAgentSessionRecord(t){if(!isObject(t)||typeof t.id!=`string`)throw Error(`linearChannel: Linear Agent Session response was malformed.`);let n=normalizeIssue(t.issue),r={id:t.id},i=relationId(t.appUser);typeof i==`string`&&(r.appUserId=i);let a=relationId(t.comment);a!==void 0&&(r.commentId=a);let o=relationId(t.creator);o!==void 0&&(r.creatorId=o),n!==void 0&&(r.issue=n);let s=relationId(t.issue);s!==void 0&&(r.issueId=s);let c=relationId(t.sourceComment);return c!==void 0&&(r.sourceCommentId=c),typeof t.status==`string`&&(r.status=t.status),(typeof t.url==`string`||t.url===null)&&(r.url=t.url),r}function relationId(t){if(t===null)return null;if(isObject(t)&&typeof t.id==`string`)return t.id}function normalizeAgentActivityRecord(t){if(!isObject(t)||typeof t.id!=`string`||!isObject(t.content))return null;let n={};typeof t.content.body==`string`&&(n.body=t.content.body),typeof t.content.type==`string`&&(n.type=t.content.type),typeof t.content.__typename==`string`&&(n.__typename=t.content.__typename);let r={content:n,id:t.id};return typeof t.updatedAt==`string`&&(r.updatedAt=t.updatedAt),r}function normalizeIssue(t){if(t===null)return null;if(!isObject(t)||typeof t.id!=`string`)return;let n={id:t.id};return typeof t.identifier==`string`&&(n.identifier=t.identifier),typeof t.title==`string`&&(n.title=t.title),typeof t.url==`string`&&(n.url=t.url),n}async function parseResponseBody(e){let t=await e.text();if(!t)return null;try{return JSON.parse(t)}catch{return t}}function hasGraphQLErrors(t){return isObject(t)&&Array.isArray(t.errors)&&t.errors.length>0}function notNull(e){return e!==null}export{LinearApiError,callLinearGraphQL,createLinearAgentActivity,createLinearAgentSessionOnComment,createLinearAgentSessionOnIssue,listLinearAgentSessionActivities,updateLinearAgentSession};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createLogger}from"#internal/logging.js";import{isObject}from"#shared/guards.js";import{POST,defineChannel}from"#public/definitions/channel.js";import{createLinearAgentActivity,createLinearAgentSessionOnComment,createLinearAgentSessionOnIssue,listLinearAgentSessionActivities,updateLinearAgentSession}from"#public/channels/linear/api.js";import{resolveLinearPromptInputResponses}from"#public/channels/linear/hitl.js";import{LINEAR_CHANNEL_DEFAULT_ROUTE}from"#public/channels/linear/constants.js";import{createDefaultEvents,defaultOnAgentSession}from"#public/channels/linear/defaults.js";import{formatLinearContextBlock,linearContinuationToken,messageFromLinearAgentSessionEvent,parseLinearWebhookEvent}from"#public/channels/linear/inbound.js";import{verifyLinearRequest}from"#public/channels/linear/verify.js";const log=createLogger(`linear.channel`);function linearChannel(e={}){let t=e.onAgentSession??defaultOnAgentSession,a={...createDefaultEvents({api:e.api,credentials:e.credentials}),...e.events};return defineChannel({kindHint:`linear`,state:initialLinearState(),metadata(e){return{agentSessionId:e.agentSessionId,commentId:e.commentId??null,issueId:e.issueId??null,issueIdentifier:e.issueIdentifier??null,organizationId:e.organizationId??null}},context(t,n){return rebuildLinearContext(t,n,e)},routes:[POST(e.route??LINEAR_CHANNEL_DEFAULT_ROUTE,async(n,{send:r,waitUntil:i})=>{let a=await verifyInbound(n,e.credentials);if(a===null)return new Response(`unauthorized`,{status:401});let o;try{o=parseLinearWebhookEvent({body:a,headers:n.headers})}catch(e){return log.warn(`inbound Linear body is not valid JSON`,{error:e}),jsonOk({ignored:!0,ok:!0})}return o===null?jsonOk({ignored:!0,ok:!0}):o.kind===`agent_session`?(i(dispatchAgentSession({config:e,event:o,onAgentSession:t,send:r})),jsonOk({ok:!0})):e.onDataWebhook===void 0?jsonOk({ignored:!0,ok:!0}):(i(Promise.resolve(e.onDataWebhook(o))),jsonOk({ok:!0}))})],async receive(t,{send:n}){let r=t.target,a=await resolveReceiveSession(r,e),o=readString(r.initialActivity);return o!==void 0&&await createLinearAgentActivity({api:e.api,credentials:e.credentials,activity:{agentSessionId:a.id,content:{body:o,type:`thought`}}}),n(t.message,{auth:t.auth,continuationToken:linearContinuationToken(a.id),state:stateFromAgentSession(a)})},events:a})}function rebuildLinearContext(e,t,n){return{linear:buildLinearHandle({agentSessionId:e.agentSessionId??``,config:n}),state:e}}function buildLinearHandle(e){return{agentSessionId:e.agentSessionId,createActivity(t,n){return createLinearAgentActivity({api:e.config.api,credentials:e.config.credentials,activity:{agentSessionId:e.agentSessionId,content:t,ephemeral:n?.ephemeral,signal:n?.signal,signalMetadata:n?.signalMetadata}})},listActivities(t){return listLinearAgentSessionActivities({api:e.config.api,credentials:e.config.credentials,agentSessionId:e.agentSessionId,last:t?.last})},updateSession(t){return updateLinearAgentSession({api:e.config.api,credentials:e.config.credentials,id:e.agentSessionId,update:t})}}}async function dispatchAgentSession(e){let{event:t}=e,n={delivery:t.delivery,linear:buildLinearHandle({agentSessionId:t.agentSession.id,config:e.config}),session:t.agentSession},r=await e.onAgentSession(n,t);if(r===null)return;let i=t.agentActivity?.body,a=t.action===`prompted`&&i!==void 0?await resolvePromptResponses({body:i,config:e.config,event:t}):[];await e.send({context:[formatLinearContextBlock(t),...t.previousComments,...r.context??[]],inputResponses:a,message:messageFromLinearAgentSessionEvent(t)},{auth:r.auth,continuationToken:linearContinuationToken(t.agentSession.id),state:stateFromAgentSession(t.agentSession)})}async function resolvePromptResponses(e){try{return resolveLinearPromptInputResponses({activities:await listLinearAgentSessionActivities({api:e.config.api,credentials:e.config.credentials,agentSessionId:e.event.agentSession.id,last:20}),body:e.body})}catch(e){return log.warn(`linear HITL activity lookup failed — treating prompt as a message`,{error:e}),[]}}async function resolveReceiveSession(e,t){if(hasString(e,`agentSessionId`))return{id:e.agentSessionId};if(hasString(e,`issueId`))return createLinearAgentSessionOnIssue({api:t.api,credentials:t.credentials,externalLink:readString(e.externalLink),externalUrls:readExternalUrls(e.externalUrls),issueId:e.issueId});if(hasString(e,`commentId`))return createLinearAgentSessionOnComment({api:t.api,credentials:t.credentials,commentId:e.commentId,externalLink:readString(e.externalLink),externalUrls:readExternalUrls(e.externalUrls)});throw Error(`linearChannel().receive requires target.agentSessionId, issueId, or commentId.`)}function stateFromAgentSession(e){return{agentSessionId:e.id,agentSessionUrl:e.url??null,commentId:e.commentId??null,issueId:e.issueId??e.issue?.id??null,issueIdentifier:e.issue?.identifier??null,issueTitle:e.issue?.title??null,issueUrl:e.issue?.url??null,organizationId
|
|
1
|
+
import{createLogger}from"#internal/logging.js";import{isObject}from"#shared/guards.js";import{POST,defineChannel}from"#public/definitions/channel.js";import{createLinearAgentActivity,createLinearAgentSessionOnComment,createLinearAgentSessionOnIssue,listLinearAgentSessionActivities,updateLinearAgentSession}from"#public/channels/linear/api.js";import{resolveLinearPromptInputResponses}from"#public/channels/linear/hitl.js";import{LINEAR_CHANNEL_DEFAULT_ROUTE}from"#public/channels/linear/constants.js";import{createDefaultEvents,defaultOnAgentSession}from"#public/channels/linear/defaults.js";import{formatLinearContextBlock,linearContinuationToken,messageFromLinearAgentSessionEvent,parseLinearWebhookEvent}from"#public/channels/linear/inbound.js";import{verifyLinearRequest}from"#public/channels/linear/verify.js";const log=createLogger(`linear.channel`);function linearChannel(e={}){let t=e.onAgentSession??defaultOnAgentSession,a={...createDefaultEvents({api:e.api,credentials:e.credentials}),...e.events};return defineChannel({kindHint:`linear`,state:initialLinearState(),metadata(e){return{agentSessionId:e.agentSessionId,commentId:e.commentId??null,issueId:e.issueId??null,issueIdentifier:e.issueIdentifier??null,organizationId:e.organizationId??null}},context(t,n){return rebuildLinearContext(t,n,e)},routes:[POST(e.route??LINEAR_CHANNEL_DEFAULT_ROUTE,async(n,{send:r,waitUntil:i})=>{let a=await verifyInbound(n,e.credentials);if(a===null)return new Response(`unauthorized`,{status:401});let o;try{o=parseLinearWebhookEvent({body:a,headers:n.headers})}catch(e){return log.warn(`inbound Linear body is not valid JSON`,{error:e}),jsonOk({ignored:!0,ok:!0})}return o===null?jsonOk({ignored:!0,ok:!0}):o.kind===`agent_session`?(i(dispatchAgentSession({config:e,event:o,onAgentSession:t,send:r})),jsonOk({ok:!0})):e.onDataWebhook===void 0?jsonOk({ignored:!0,ok:!0}):(i(Promise.resolve(e.onDataWebhook(o))),jsonOk({ok:!0}))})],async receive(t,{send:n}){let r=t.target,a=await resolveReceiveSession(r,e),o=readString(r.initialActivity);return o!==void 0&&await createLinearAgentActivity({api:e.api,credentials:e.credentials,activity:{agentSessionId:a.id,content:{body:o,type:`thought`}}}),n(t.message,{auth:t.auth,continuationToken:linearContinuationToken(a.id),state:stateFromAgentSession(a)})},events:a})}function rebuildLinearContext(e,t,n){return{linear:buildLinearHandle({agentSessionId:e.agentSessionId??``,config:n}),state:e}}function buildLinearHandle(e){return{agentSessionId:e.agentSessionId,createActivity(t,n){return createLinearAgentActivity({api:e.config.api,credentials:e.config.credentials,activity:{agentSessionId:e.agentSessionId,content:t,ephemeral:n?.ephemeral,signal:n?.signal,signalMetadata:n?.signalMetadata}})},listActivities(t){return listLinearAgentSessionActivities({api:e.config.api,credentials:e.config.credentials,agentSessionId:e.agentSessionId,last:t?.last})},updateSession(t){return updateLinearAgentSession({api:e.config.api,credentials:e.config.credentials,id:e.agentSessionId,update:t})}}}async function dispatchAgentSession(e){let{event:t}=e,n={delivery:t.delivery,linear:buildLinearHandle({agentSessionId:t.agentSession.id,config:e.config}),session:t.agentSession},r=await e.onAgentSession(n,t);if(r===null)return;let i=t.agentActivity?.body,a=t.action===`prompted`&&i!==void 0?await resolvePromptResponses({body:i,config:e.config,event:t}):[];await e.send({context:[formatLinearContextBlock(t),...t.previousComments,...r.context??[]],inputResponses:a,message:messageFromLinearAgentSessionEvent(t)},{auth:r.auth,continuationToken:linearContinuationToken(t.agentSession.id),state:stateFromAgentSession(t.agentSession)})}async function resolvePromptResponses(e){try{return resolveLinearPromptInputResponses({activities:await listLinearAgentSessionActivities({api:e.config.api,credentials:e.config.credentials,agentSessionId:e.event.agentSession.id,last:20}),body:e.body})}catch(e){return log.warn(`linear HITL activity lookup failed — treating prompt as a message`,{error:e}),[]}}async function resolveReceiveSession(e,t){if(hasString(e,`agentSessionId`))return{id:e.agentSessionId};if(hasString(e,`issueId`))return createLinearAgentSessionOnIssue({api:t.api,credentials:t.credentials,externalLink:readString(e.externalLink),externalUrls:readExternalUrls(e.externalUrls),issueId:e.issueId});if(hasString(e,`commentId`))return createLinearAgentSessionOnComment({api:t.api,credentials:t.credentials,commentId:e.commentId,externalLink:readString(e.externalLink),externalUrls:readExternalUrls(e.externalUrls)});throw Error(`linearChannel().receive requires target.agentSessionId, issueId, or commentId.`)}function stateFromAgentSession(e){return{agentSessionId:e.id,agentSessionUrl:e.url??null,commentId:e.commentId??null,issueId:e.issueId??e.issue?.id??null,issueIdentifier:e.issue?.identifier??null,issueTitle:e.issue?.title??null,issueUrl:e.issue?.url??null,organizationId:`organizationId`in e?e.organizationId??null:null,pendingToolCallMessage:null,sourceCommentId:e.sourceCommentId??null}}function initialLinearState(){return{agentSessionId:null,agentSessionUrl:null,commentId:null,issueId:null,issueIdentifier:null,issueTitle:null,issueUrl:null,organizationId:null,pendingToolCallMessage:null,sourceCommentId:null}}async function verifyInbound(e,t){try{return await verifyLinearRequest(e,{webhookSecret:t?.webhookSecret,webhookVerifier:t?.webhookVerifier})}catch(e){return log.warn(`linear inbound verification failed`,{error:e}),null}}function hasString(e,t){return typeof e[t]==`string`&&e[t].length>0}function readString(e){return typeof e==`string`&&e.length>0?e:void 0}function readExternalUrls(e){if(!Array.isArray(e))return;let n=e.filter(e=>isObject(e)&&typeof e.label==`string`&&typeof e.url==`string`);return n.length>0?n:void 0}function jsonOk(e){return new Response(JSON.stringify(e),{headers:{"content-type":`application/json; charset=utf-8`},status:200})}export{linearChannel};
|
|
@@ -3,12 +3,12 @@ import { type ChannelCorsOptions } from "#channel/cors.js";
|
|
|
3
3
|
import type { TypedReceiveTarget } from "#channel/receive-target.js";
|
|
4
4
|
import type { RouteDefinition, SendFn } from "#channel/routes.js";
|
|
5
5
|
import type { Session } from "#channel/session.js";
|
|
6
|
-
import type { DeliverInput, GetEventStreamOptions, RunHandle, RunInput } from "#channel/types.js";
|
|
6
|
+
import type { CancelTurnInput, CancelTurnResult, DeliverInput, GetEventStreamOptions, RunHandle, RunInput } from "#channel/types.js";
|
|
7
7
|
import type { HandleMessageStreamEvent } from "#protocol/message.js";
|
|
8
8
|
import type { SessionContext } from "#public/definitions/callback-context.js";
|
|
9
9
|
import type { GenericChannelDefinition, GenericReceiveInput } from "#shared/channel-definition.js";
|
|
10
10
|
declare const CHANNEL_METADATA_TYPE: unique symbol;
|
|
11
|
-
export type { GetEventStreamOptions } from "#channel/types.js";
|
|
11
|
+
export type { CancelTurnInput, CancelTurnResult, GetEventStreamOptions } from "#channel/types.js";
|
|
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";
|
|
@@ -31,17 +31,16 @@ export type ChannelRouteMethod = ChannelMethod | "WEBSOCKET";
|
|
|
31
31
|
* framework constructs this per request and passes it as the second
|
|
32
32
|
* argument.
|
|
33
33
|
*
|
|
34
|
-
* Routes call into the agent to start
|
|
35
|
-
*
|
|
36
|
-
* read events from a previously-started session (`agent.getEventStream`).
|
|
34
|
+
* Routes call into the agent to start sessions, deliver follow-ups,
|
|
35
|
+
* cancel turns, and read events.
|
|
37
36
|
*/
|
|
38
37
|
export interface RouteContext {
|
|
39
38
|
/**
|
|
40
39
|
* Handle to the agent that this route sends inbound requests to.
|
|
41
40
|
* Conceptually the runtime + harness combined: routes call `run`,
|
|
42
|
-
* `deliver`, and `getEventStream` to drive sessions of
|
|
43
|
-
* without knowing about the workflow runtime, the harness,
|
|
44
|
-
* other execution-layer detail.
|
|
41
|
+
* `deliver`, `cancelTurn`, and `getEventStream` to drive sessions of
|
|
42
|
+
* this agent without knowing about the workflow runtime, the harness,
|
|
43
|
+
* or any other execution-layer detail.
|
|
45
44
|
*
|
|
46
45
|
* Every route speaks the same `RunInput` shape regardless of which
|
|
47
46
|
* webhook it serves — `agent` is platform-agnostic.
|
|
@@ -78,8 +77,9 @@ export interface RouteContext {
|
|
|
78
77
|
*
|
|
79
78
|
* `Agent` is conceptually the workflow runtime plus the tool-loop harness:
|
|
80
79
|
* routes call `run` to start a new session of the agent, `deliver` to
|
|
81
|
-
* send a follow-up to a parked session,
|
|
82
|
-
* from a previously-started session.
|
|
80
|
+
* send a follow-up to a parked session, `cancelTurn` to stop in-flight work,
|
|
81
|
+
* and `getEventStream` to read events from a previously-started session.
|
|
82
|
+
* The framework's internal `Runtime`
|
|
83
83
|
* interface (in `channel/types.ts`) is the underlying primitive — `Agent`
|
|
84
84
|
* is the *public* shape exposed on `RouteContext` so route authors
|
|
85
85
|
* speak in terms of the agent rather than the runtime.
|
|
@@ -91,6 +91,16 @@ export interface Agent {
|
|
|
91
91
|
* with the same token resume the same session.
|
|
92
92
|
*/
|
|
93
93
|
run(input: RunInput): Promise<RunHandle>;
|
|
94
|
+
/**
|
|
95
|
+
* Requests cancellation of a session's in-flight turn. A `turnId` limits
|
|
96
|
+
* the request to the turn the caller observed.
|
|
97
|
+
*
|
|
98
|
+
* `"accepted"` means a cancellation hook accepted the request; observe
|
|
99
|
+
* the event stream for `turn.cancelled` to confirm that it affected the
|
|
100
|
+
* current turn. `"no_active_turn"` means no cancellable hook was active.
|
|
101
|
+
* Both outcomes are successful.
|
|
102
|
+
*/
|
|
103
|
+
cancelTurn(input: CancelTurnInput): Promise<CancelTurnResult>;
|
|
94
104
|
/**
|
|
95
105
|
* Sends a follow-up message to a session that is currently parked waiting
|
|
96
106
|
* for input. Throws if no parked session exists for the supplied
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{resolveEveDestinationPrefix}from"./server.js";import{ensureEveVercelOutputConfig}from"./vercel-output-config.js";import{EVE_ROUTE_PREFIX}from"#protocol/routes.js";import{isAbsolute,
|
|
1
|
+
import{resolveEveBinaryPath}from"./resolve-eve-binary.js";import{resolveEveDestinationPrefix}from"./server.js";import{ensureEveVercelOutputConfig}from"./vercel-output-config.js";import{EVE_ROUTE_PREFIX}from"#protocol/routes.js";import{isAbsolute,relative,resolve}from"node:path";const EVE_NEXT_SERVICE_PREFIX=`/_eve_internal/eve`,EVE_NEXT_PRODUCTION_PORT_ENV=`EVE_NEXT_PRODUCTION_PORT`,AGENT_NAME_PATTERN=/^[a-z0-9][a-z0-9_-]*$/;function resolveApplicationRoot(e){return e===void 0||e.length===0?process.cwd():isAbsolute(e)?e:resolve(process.cwd(),e)}function resolveDevServerTimeout(e){if(e!==void 0){if(!Number.isFinite(e)||e<=0)throw Error(`eve Next.js development server timeout must be a positive number.`);return e}}function normalizeRoutePrefix(e){let t=(e.startsWith(`/`)?e:`/${e}`).replace(/\/+$/,``);if(t.length===0)throw Error(`eve Next.js service prefix cannot resolve to the root route.`);return t}function joinRoutePrefix(e,t){return`${e.replace(/\/+$/,``)}/${t.replace(/^\/+/,``)}`}function createNamedAgentRoutePrefix(e){return joinRoutePrefix(`/eve/agents`,e)}function createNamedAgentServicePrefix(e,t){return joinRoutePrefix(e,t)}function createAgentRewriteSource(e){return joinRoutePrefix(e,`${EVE_ROUTE_PREFIX}/:path+`)}function normalizeOrigin(e){return new URL(e.trim()).origin}function readLocalProductionPort(e){let t=process.env[EVE_NEXT_PRODUCTION_PORT_ENV],n=t===void 0||t.trim().length===0?4274:Number.parseInt(t,10);if(t!==void 0&&t.trim().length>0&&String(n)!==t.trim())throw Error(`${EVE_NEXT_PRODUCTION_PORT_ENV} must be an integer between 1 and 65535.`);let r=n+e;if(r<1||r>65535)throw Error(`${EVE_NEXT_PRODUCTION_PORT_ENV} plus the eve agent count exceeds 65535.`);return r}function resolveProductionDestination(e){if(process.env.VERCEL)return{destinationPrefix:e.servicePrefix};let t=process.env.EVE_NEXT_PRODUCTION_ORIGIN;if(t!==void 0&&t.trim().length>0)return{destinationPrefix:joinRoutePrefix(normalizeOrigin(t),e.servicePrefix)};let n=`http://127.0.0.1:${String(readLocalProductionPort(e.localProductionPortOffset))}`;return{destinationPrefix:n,localServerOrigin:n}}function createEveRewriteRule(e){let t=createAgentRewriteSource(e.publicRoutePrefix);return{destination:joinRoutePrefix(e.destinationPrefix,`${EVE_ROUTE_PREFIX}/:path+`),source:t}}async function resolveExistingRewrites(e){return await e?.()}function mergeRewriteRules(e,t){return e===void 0?{beforeFiles:t}:isRewriteSections(e)?{...e,beforeFiles:[...t,...e.beforeFiles??[]]}:{afterFiles:e,beforeFiles:t}}function isRewriteSections(e){return!Array.isArray(e)}async function resolveNextConfig(e,t,n){return typeof e==`function`?await e(t,n):e}function assertValidAgentName(e){if(!AGENT_NAME_PATTERN.test(e))throw Error(`eve Next.js agent name ${JSON.stringify(e)} is invalid. Use lowercase letters, numbers, underscores, or hyphens, starting with a letter or number.`)}function quoteShellArg(e){return`'${e.replaceAll(`'`,`'\\''`)}'`}function toPosixPath(e){return e.replaceAll(`\\`,`/`)}function createDefaultBuildCommand(t){return`node ${quoteShellArg(toPosixPath(relative(t.agentRoot,resolveEveBinaryPath(t.nextRoot))))} build`}function normalizeAgentsConfig(e,t){let n=normalizeRoutePrefix(e.servicePrefix??`/_eve_internal/eve`),resolveBuildCommand=(n,r)=>r??e.eveBuildCommand??createDefaultBuildCommand({agentRoot:n,nextRoot:t});if(e.agents===void 0){let t=resolveApplicationRoot(e.eveRoot);return[{appRoot:t,buildCommand:resolveBuildCommand(t,void 0),localProductionPortOffset:0,publicRoutePrefix:``,servicePrefix:n}]}if(e.eveRoot!==void 0)throw Error(`withEve cannot combine eveRoot with agents. Use one configuration form.`);let r=Object.entries(e.agents);if(r.length===0)throw Error(`withEve agents must contain at least one named eve agent.`);return r.map(([e,t],r)=>{assertValidAgentName(e);let i=typeof t==`string`?{root:t}:t,a=resolveApplicationRoot(i.root);return{appRoot:a,buildCommand:resolveBuildCommand(a,i.buildCommand),localProductionPortOffset:r,name:e,publicRoutePrefix:createNamedAgentRoutePrefix(e),servicePrefix:normalizeRoutePrefix(i.servicePrefix??createNamedAgentServicePrefix(n,e))}})}function withEve(e,r={}){let i=process.cwd(),a=resolveDevServerTimeout(r.devServerTimeoutMs),o=normalizeAgentsConfig(r,i);return async function(r,s){let c=await resolveNextConfig(e,r,s),l=c.rewrites,u=await ensureEveVercelOutputConfig({agents:o.map(e=>({appRoot:e.appRoot,buildCommand:e.buildCommand,name:e.name,publicRoutePrefix:e.publicRoutePrefix,servicePrefix:e.servicePrefix})),nextRoot:i});if(process.env.VERCEL)return c;let d=new Map(u.agents.map(e=>[e.name,e])),f=o.map(e=>{let t=d.get(e.name),n=resolveProductionDestination({localProductionPortOffset:e.localProductionPortOffset,servicePrefix:t?.servicePrefix??e.servicePrefix});return{...e,productionDestination:n}});return{...c,async rewrites(){let[e,n]=await Promise.all([resolveExistingRewrites(l),Promise.all(f.map(async e=>createEveRewriteRule({destinationPrefix:await resolveEveDestinationPrefix({appRoot:e.appRoot,devServerTimeoutMs:a,logLabel:e.name,phase:r,productionDestinationPrefix:e.productionDestination.destinationPrefix,productionServerOrigin:e.productionDestination.localServerOrigin}),publicRoutePrefix:e.publicRoutePrefix})))]);return mergeRewriteRules(e,n)}}}}export{EVE_NEXT_SERVICE_PREFIX,withEve};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolves the absolute path to the installed eve binary from the app's
|
|
3
|
+
* perspective.
|
|
4
|
+
*
|
|
5
|
+
* Uses module resolution rather than assuming an app-local `node_modules/eve`:
|
|
6
|
+
* npm workspaces hoist eve to the workspace root, so the app-local path does
|
|
7
|
+
* not exist there, while pnpm symlinks it app-locally. eve does not export
|
|
8
|
+
* `./bin/eve.js`, but it does export `./package.json`, so we resolve that and
|
|
9
|
+
* derive the bin path from the package root. Falls back to the conventional
|
|
10
|
+
* app-local path when eve cannot be resolved (e.g. before install).
|
|
11
|
+
*/
|
|
12
|
+
export declare function resolveEveBinaryPath(nextRoot: string): string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{createRequire}from"node:module";import{dirname,join}from"node:path";function resolveEveBinaryPath(e){try{return join(dirname(createRequire(join(e,`package.json`)).resolve(`eve/package.json`)),`bin`,`eve.js`)}catch{return join(e,`node_modules`,`eve`,`bin`,`eve.js`)}}export{resolveEveBinaryPath};
|
|
@@ -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`||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=createSubagentDelegationResult(e,t)??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})}const SUBAGENT_TOOL_NAME=`agent`,SUBAGENT_DELEGATION_DIRECTIVE=/\bdelegate\s+to\s+a\s+subagent\s*:\s*(.+)$/iu;function createSubagentDelegationResult(e,t){let n=getLastUserPromptText(e.prompt);if(n===null)return null;let r=SUBAGENT_DELEGATION_DIRECTIVE.exec(n);if(r?.[1]===void 0||getAvailableTools(e).find(e=>e.name===SUBAGENT_TOOL_NAME)===void 0)return null;let i={message:r[1].trim()};return createToolCallGenerateResult({input:i,inputTokens:estimateTokenCount(getPromptText(e.prompt)),modelId:t,outputTokens:estimateTokenCount(i.message),toolCallId:createToolCallId(SUBAGENT_TOOL_NAME),toolName:SUBAGENT_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{
|
|
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=createParallelAuthoredToolCallsResult(e,t)??createSubagentDelegationResult(e,t)??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})}const SUBAGENT_TOOL_NAME=`agent`,SUBAGENT_DELEGATION_DIRECTIVE=/\bdelegate\s+to\s+a\s+subagent\s*:\s*(.+)$/iu,PARALLEL_AUTHORED_TOOLS_DIRECTIVE=/^call tools in parallel:\s*(.+)$/imu;function createParallelAuthoredToolCallsResult(e,t){let n=getLastUserPromptText(e.prompt);if(n===null)return null;let r=PARALLEL_AUTHORED_TOOLS_DIRECTIVE.exec(n)?.[1]?.split(`,`).map(e=>e.trim()).filter(Boolean);if(r===void 0||r.length<2||new Set(r).size!==r.length)return null;let i=new Map(getAvailableTools(e).map(e=>[e.name,e])),a=[];for(let e of r){let t=i.get(e);if(t===void 0)return null;a.push(t)}let o=resolveWeatherCity(n);return createToolCallsGenerateResult({calls:a.map(e=>({input:createMockAuthoredToolInput(e,n,o),toolCallId:createToolCallId(e.name),toolName:e.name})),inputTokens:estimateTokenCount(getPromptText(e.prompt)),modelId:t,outputTokens:estimateTokenCount(n)})}function createSubagentDelegationResult(e,t){let n=getLastUserPromptText(e.prompt);if(n===null)return null;let r=SUBAGENT_DELEGATION_DIRECTIVE.exec(n);if(r?.[1]===void 0||getAvailableTools(e).find(e=>e.name===SUBAGENT_TOOL_NAME)===void 0)return null;let i={message:r[1].trim()};return createToolCallGenerateResult({input:i,inputTokens:estimateTokenCount(getPromptText(e.prompt)),modelId:t,outputTokens:estimateTokenCount(i.message),toolCallId:createToolCallId(SUBAGENT_TOOL_NAME),toolName:SUBAGENT_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 createToolCallsGenerateResult({calls:[{input:e.input,toolCallId:e.toolCallId,toolName:e.toolName}],inputTokens:e.inputTokens,modelId:e.modelId,outputTokens:e.outputTokens})}function createToolCallsGenerateResult(e){return{content:e.calls.map(e=>({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};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { ResolvedToolDefinition } from "#runtime/types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Stable model-visible name for the root-only agent delegation tool.
|
|
4
|
+
*/
|
|
5
|
+
export declare const AGENT_TOOL_NAME = "agent";
|
|
6
|
+
/**
|
|
7
|
+
* Model-facing instructions for the root-only agent delegation tool.
|
|
8
|
+
*/
|
|
9
|
+
export declare const AGENT_TOOL_DESCRIPTION: string;
|
|
10
|
+
/**
|
|
11
|
+
* Shared metadata for the root-only agent delegation tool.
|
|
12
|
+
*/
|
|
13
|
+
export declare const AGENT_TOOL_DEFINITION: ResolvedToolDefinition;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{SUBAGENT_TOOL_INPUT_SCHEMA}from"#runtime/subagents/registry.js";const AGENT_TOOL_NAME=`agent`,AGENT_TOOL_DESCRIPTION=[`Delegate a focused subtask to a fresh copy of yourself.`,`Use it to isolate complex work or split a large task into independent pieces.`,"Issue multiple `agent` calls in one response to run a small fixed set in parallel.","Each child has fresh history and state but shares your tools and sandbox, so include essential context in `message` and give parallel writers non-overlapping scopes."].join(` `),AGENT_TOOL_DEFINITION={description:AGENT_TOOL_DESCRIPTION,inputSchema:SUBAGENT_TOOL_INPUT_SCHEMA,logicalPath:`eve:framework/agent`,name:AGENT_TOOL_NAME,sourceId:`eve:agent-tool`,sourceKind:`module`};export{AGENT_TOOL_DEFINITION,AGENT_TOOL_DESCRIPTION,AGENT_TOOL_NAME};
|
|
@@ -8,12 +8,17 @@ import type { ResolvedToolDefinition } from "#runtime/types.js";
|
|
|
8
8
|
* Returns framework-owned tool definitions registered in the tool registry
|
|
9
9
|
* alongside authored tools during graph resolution.
|
|
10
10
|
*
|
|
11
|
-
* `connection_search` is no longer in this list
|
|
12
|
-
* framework dynamic tool resolver
|
|
11
|
+
* `connection_search` is no longer in this list. The graph resolution path
|
|
12
|
+
* registers it as a framework dynamic tool resolver.
|
|
13
13
|
*/
|
|
14
14
|
export declare function getFrameworkToolDefinitions(_config?: {
|
|
15
15
|
readonly hasConnections?: boolean;
|
|
16
16
|
}): readonly ResolvedToolDefinition[];
|
|
17
|
+
/**
|
|
18
|
+
* Returns every static framework-owned tool definition, including tools such
|
|
19
|
+
* as `agent` that the runtime does not register in the tool registry.
|
|
20
|
+
*/
|
|
21
|
+
export declare function getAllFrameworkToolDefinitions(): readonly ResolvedToolDefinition[];
|
|
17
22
|
/**
|
|
18
23
|
* Returns the names of every framework-provided tool the framework knows
|
|
19
24
|
* about, regardless of whether the current agent gates any of them on
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{ConnectionRegistryKey}from"#context/providers/connection-key.js";import{ReadFileStateKey}from"#runtime/framework-tools/file-state.js";import{TODO_TOOL_DEFINITION,TodoStateKey}from"#runtime/framework-tools/todo.js";import{ASK_QUESTION_TOOL_DEFINITION}from"#runtime/framework-tools/ask-question.js";import{WEB_SEARCH_TOOL_DEFINITION}from"#runtime/framework-tools/web-search.js";import{BASH_TOOL_DEFINITION}from"#runtime/framework-tools/bash.js";import{GLOB_TOOL_DEFINITION}from"#runtime/framework-tools/glob.js";import{GREP_TOOL_DEFINITION}from"#runtime/framework-tools/grep.js";import{READ_FILE_TOOL_DEFINITION}from"#runtime/framework-tools/read-file.js";import{SKILL_TOOL_DEFINITION}from"#runtime/framework-tools/skill.js";import{WEB_FETCH_TOOL_DEFINITION}from"#runtime/framework-tools/web-fetch.js";import{WRITE_FILE_TOOL_DEFINITION}from"#runtime/framework-tools/write-file.js";const
|
|
1
|
+
import{ConnectionRegistryKey}from"#context/providers/connection-key.js";import{ReadFileStateKey}from"#runtime/framework-tools/file-state.js";import{TODO_TOOL_DEFINITION,TodoStateKey}from"#runtime/framework-tools/todo.js";import{AGENT_TOOL_DEFINITION}from"#runtime/framework-tools/agent.js";import{ASK_QUESTION_TOOL_DEFINITION}from"#runtime/framework-tools/ask-question.js";import{WEB_SEARCH_TOOL_DEFINITION}from"#runtime/framework-tools/web-search.js";import{BASH_TOOL_DEFINITION}from"#runtime/framework-tools/bash.js";import{GLOB_TOOL_DEFINITION}from"#runtime/framework-tools/glob.js";import{GREP_TOOL_DEFINITION}from"#runtime/framework-tools/grep.js";import{READ_FILE_TOOL_DEFINITION}from"#runtime/framework-tools/read-file.js";import{SKILL_TOOL_DEFINITION}from"#runtime/framework-tools/skill.js";import{WEB_FETCH_TOOL_DEFINITION}from"#runtime/framework-tools/web-fetch.js";import{WRITE_FILE_TOOL_DEFINITION}from"#runtime/framework-tools/write-file.js";const REGISTERED_FRAMEWORK_TOOLS=[ASK_QUESTION_TOOL_DEFINITION,BASH_TOOL_DEFINITION,GLOB_TOOL_DEFINITION,GREP_TOOL_DEFINITION,READ_FILE_TOOL_DEFINITION,WRITE_FILE_TOOL_DEFINITION,TODO_TOOL_DEFINITION,WEB_FETCH_TOOL_DEFINITION,WEB_SEARCH_TOOL_DEFINITION,SKILL_TOOL_DEFINITION],ALL_FRAMEWORK_TOOLS=[...REGISTERED_FRAMEWORK_TOOLS,AGENT_TOOL_DEFINITION];function getFrameworkToolDefinitions(e){return REGISTERED_FRAMEWORK_TOOLS}function getAllFrameworkToolDefinitions(){return ALL_FRAMEWORK_TOOLS}function getAllFrameworkToolNames(){return new Set(ALL_FRAMEWORK_TOOLS.map(e=>e.name))}export{ConnectionRegistryKey,ReadFileStateKey,TodoStateKey,getAllFrameworkToolDefinitions,getAllFrameworkToolNames,getFrameworkToolDefinitions};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{expectObjectRecord}from"#internal/authored-module.js";import{ROOT_COMPILED_AGENT_NODE_ID}from"#compiler/manifest.js";import{LOAD_SKILL_TOOL_NAME}from"#runtime/skills/fragment-context.js";import{ROOT_RUNTIME_AGENT_NODE_ID}from"#runtime/graph.js";import{
|
|
1
|
+
import{expectObjectRecord}from"#internal/authored-module.js";import{ROOT_COMPILED_AGENT_NODE_ID}from"#compiler/manifest.js";import{LOAD_SKILL_TOOL_NAME}from"#runtime/skills/fragment-context.js";import{ROOT_RUNTIME_AGENT_NODE_ID}from"#runtime/graph.js";import{createRuntimeSubagentRegistry}from"#runtime/subagents/registry.js";import{createRuntimeToolRegistry}from"#runtime/tools/registry.js";import{WORKFLOW_TOOL_NAME}from"#shared/workflow-sandbox.js";import{getAllFrameworkChannelNames,getFrameworkChannelDefinitions}from"#runtime/framework-channels/index.js";import{getAllFrameworkToolNames,getFrameworkToolDefinitions}from"#runtime/framework-tools/index.js";import{createConnectionSearchResolver}from"#runtime/framework-tools/connection-search-dynamic.js";import{resolveAgent}from"#runtime/resolve-agent.js";import{loadResolvedModuleExport}from"#runtime/resolve-helpers.js";import{createResolvedRuntimeTurnAgent}from"#runtime/agent/bootstrap.js";import{createRuntimeHookRegistry}from"#runtime/hooks/registry.js";import{createRuntimeSandboxRegistry}from"#runtime/sandbox/registry.js";var ResolveRuntimeAgentGraphError=class extends Error{logicalPath;nodeId;sourceId;constructor(e,t={}){super(e),this.name=`ResolveRuntimeAgentGraphError`,t.logicalPath!==void 0&&(this.logicalPath=t.logicalPath),t.nodeId!==void 0&&(this.nodeId=t.nodeId),t.sourceId!==void 0&&(this.sourceId=t.sourceId)}};async function resolveRuntimeAgentGraph(e){let n=new Map,r=createChildNodeIdsByParentNodeId(e.manifest),i=new Map(e.manifest.subagents.map(e=>[e.nodeId,e]));return{nodesByNodeId:n,root:await resolveRuntimeAgentNode({childNodeIdsByParentNodeId:r,manifest:e.manifest,moduleMap:e.moduleMap,nodeId:ROOT_COMPILED_AGENT_NODE_ID,nodesByNodeId:n,subagentNodesById:i})}}async function resolveRuntimeAgentNode(e){let t=toRuntimeNodeId(e.nodeId);if(e.nodesByNodeId.has(t))throw new ResolveRuntimeAgentGraphError(`Found multiple runtime agent nodes for node id "${t}".`,{nodeId:t,sourceId:e.sourceId});let r=await resolveAgent({manifest:e.manifest,moduleMap:e.moduleMap,nodeId:e.nodeId}),a=r.connections.length>0,o=getFrameworkToolDefinitions({hasConnections:a}),s=new Set(o.map(e=>e.name)),c=getAllFrameworkToolNames(),l=new Set(r.tools.map(e=>e.name));for(let n of r.disabledFrameworkTools)if(!c.has(n))throw new ResolveRuntimeAgentGraphError(`agent/tools/${n}.ts exports disableTool() but "${n}" is not a framework tool. Rename the file to one of: ${[...c].sort().join(`, `)}.`,{nodeId:t,sourceId:e.sourceId});let u=new Set(r.disabledFrameworkTools),d=await createRuntimeToolRegistry({tools:[...o.filter(e=>!l.has(e.name)&&!u.has(e.name)),...r.tools]},{reservedToolNames:[WORKFLOW_TOOL_NAME,...s.has(LOAD_SKILL_TOOL_NAME)||l.has(LOAD_SKILL_TOOL_NAME)?[]:[LOAD_SKILL_TOOL_NAME]]}),f=new Set(r.channels.map(e=>e.name)),p=getAllFrameworkChannelNames();for(let n of r.disabledFrameworkChannels)if(!p.has(n))throw new ResolveRuntimeAgentGraphError(`agent/channels/${n}.ts exports disableRoute() but "${n}" is not a framework channel. Rename the file to one of: ${[...p].sort().join(`, `)}.`,{nodeId:t,sourceId:e.sourceId});let m=new Set(r.disabledFrameworkChannels),h=[...getFrameworkChannelDefinitions().filter(e=>!f.has(e.name)&&!m.has(e.name)),...r.channels],g=createRuntimeSandboxRegistry({authoredSandbox:r.sandbox,workspaceResourceRoot:r.workspaceResourceRoot}),_=createRuntimeSubagentRegistry({reservedToolNames:[LOAD_SKILL_TOOL_NAME,...d.preparedTools.map(e=>e.name)],subagents:await resolveRuntimeSubagents({childNodeIdsByParentNodeId:e.childNodeIdsByParentNodeId,manifest:e.manifest,moduleMap:e.moduleMap,nodesByNodeId:e.nodesByNodeId,parentNodeId:e.nodeId,subagentNodesById:e.subagentNodesById})}),v=a?{...r,dynamicToolResolvers:[...r.dynamicToolResolvers,createConnectionSearchResolver()]}:r,y={agent:v,channels:h,hookRegistry:createRuntimeHookRegistry(v.hooks),nodeId:t,sandboxRegistry:g,sourceId:e.sourceId,subagentRegistry:_,toolRegistry:d,turnAgent:createResolvedRuntimeTurnAgent({agent:v,nodeId:t,tools:[...d.preparedTools,..._.preparedTools]})};return e.nodesByNodeId.set(t,y),y}async function resolveRuntimeSubagents(e){let t=[],n=e.childNodeIdsByParentNodeId.get(e.parentNodeId)??[];for(let r of n){let n=e.subagentNodesById.get(r);if(n===void 0)throw new ResolveRuntimeAgentGraphError(`Missing compiled subagent node "${r}" while resolving runtime subagents.`,{nodeId:toRuntimeNodeId(e.parentNodeId),sourceId:r});t.push(await resolveRuntimeSubagent({childNodeIdsByParentNodeId:e.childNodeIdsByParentNodeId,moduleMap:e.moduleMap,nodesByNodeId:e.nodesByNodeId,sourceRef:n,subagentNodesById:e.subagentNodesById}))}for(let n of e.manifest.remoteAgents)t.push(await resolveRuntimeRemoteAgent({moduleMap:e.moduleMap,nodeScopeId:e.parentNodeId,sourceRef:n}));return t}async function resolveRuntimeSubagent(e){let t={description:e.sourceRef.description,kind:`subagent`,logicalPath:e.sourceRef.logicalPath,name:e.sourceRef.name,nodeId:toRuntimeNodeId(e.sourceRef.nodeId),sourceId:e.sourceRef.sourceId,sourceKind:`module`};return await resolveRuntimeAgentNode({childNodeIdsByParentNodeId:e.childNodeIdsByParentNodeId,manifest:e.sourceRef.agent,moduleMap:e.moduleMap,nodeId:e.sourceRef.nodeId,nodesByNodeId:e.nodesByNodeId,sourceId:e.sourceRef.sourceId,subagentNodesById:e.subagentNodesById}),t}async function resolveRuntimeRemoteAgent(t){let n=expectObjectRecord(await loadResolvedModuleExport({definition:t.sourceRef,kindLabel:`remote agent`,moduleMap:t.moduleMap,nodeId:t.nodeScopeId}),`Expected remote agent source "${t.sourceRef.logicalPath}" to export an object.`),r={description:t.sourceRef.description,kind:`remote`,logicalPath:t.sourceRef.logicalPath,name:t.sourceRef.name,nodeId:toRuntimeNodeId(t.sourceRef.nodeId),outputSchema:t.sourceRef.outputSchema,path:t.sourceRef.path,sourceId:t.sourceRef.sourceId,sourceKind:`module`,url:await resolveRemoteAgentUrl({bakedUrl:t.sourceRef.url,logicalPath:t.sourceRef.logicalPath,resolvedUrl:n.url})};typeof n.auth==`function`&&(r.auth=n.auth);let i=resolveRemoteAgentHeaders(n.headers);return i!==void 0&&(r.headers=i),r}async function resolveRemoteAgentUrl(e){if(typeof e.resolvedUrl==`function`){let t=await e.resolvedUrl();if(typeof t!=`string`||t.length===0)throw Error(`Remote agent "${e.logicalPath}" url function must return a non-empty string.`);return t}let t=e.bakedUrl??(typeof e.resolvedUrl==`string`?e.resolvedUrl:``);if(t.length===0)throw Error(`Remote agent "${e.logicalPath}" is missing a url.`);return t}function resolveRemoteAgentHeaders(e){if(e===void 0)return;if(typeof e==`function`)return e;if(typeof e!=`object`||!e||Array.isArray(e))return;let t={};for(let[n,r]of Object.entries(e))typeof r==`string`&&(t[n]=r);return t}function createChildNodeIdsByParentNodeId(e){let t=new Map;for(let n of e.subagentEdges){let e=t.get(n.parentNodeId);if(e===void 0){t.set(n.parentNodeId,[n.childNodeId]);continue}e.push(n.childNodeId)}return t}function toRuntimeNodeId(e){return e===ROOT_COMPILED_AGENT_NODE_ID?ROOT_RUNTIME_AGENT_NODE_ID:e}export{resolveRuntimeAgentGraph};
|
|
@@ -120,7 +120,8 @@ export type ResolvedSandboxDefinition = ResolvedModuleSourceRef & {
|
|
|
120
120
|
readonly onSession?: (input: SandboxSessionContext) => Promise<void> | void;
|
|
121
121
|
};
|
|
122
122
|
/**
|
|
123
|
-
* Runtime-owned
|
|
123
|
+
* Runtime-owned tool definition resolved from a compiled module map or
|
|
124
|
+
* declared by the framework catalog.
|
|
124
125
|
* A tool without `execute` is surfaced to the client and never executed by eve.
|
|
125
126
|
*/
|
|
126
127
|
export type ResolvedToolDefinition = Readonly<Optional<InternalToolDefinitionWithExecuteFn<unknown, unknown>, "execute">> & ResolvedModuleSourceRef & {
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { Prompter } from "../prompter.js";
|
|
2
|
+
import { type SetupState } from "../state.js";
|
|
3
|
+
import type { SetupBox } from "../step.js";
|
|
4
|
+
import { syncHostFrameworkPreset } from "../vercel-project-framework.js";
|
|
5
|
+
/** Injected for tests; defaults to the real framework-preset reconciliation. */
|
|
6
|
+
export interface ReconcileHostFrameworkPresetDeps {
|
|
7
|
+
syncHostFrameworkPreset: typeof syncHostFrameworkPreset;
|
|
8
|
+
}
|
|
9
|
+
export interface ReconcileHostFrameworkPresetOptions {
|
|
10
|
+
/** Streams reconciliation progress and the applied-change note. */
|
|
11
|
+
prompter: Prompter;
|
|
12
|
+
deps?: ReconcileHostFrameworkPresetDeps;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Aligns an already-linked Vercel project's Framework Preset with a newly-added
|
|
16
|
+
* web (Next.js) channel before the deploy box runs. A project created as a
|
|
17
|
+
* standalone agent keeps the `eve` preset, which would build the agent instead
|
|
18
|
+
* of the host app; the command already deploys on the user's behalf, so this
|
|
19
|
+
* corrects the preset directly (no confirmation) and notes the change.
|
|
20
|
+
*
|
|
21
|
+
* Runs only for an already-linked project — an unlinked directory links later
|
|
22
|
+
* inside the deploy box, where a fresh `vercel link` detects the framework. All
|
|
23
|
+
* effects live in {@link syncHostFrameworkPreset}, a no-op when the preset
|
|
24
|
+
* already matches.
|
|
25
|
+
*/
|
|
26
|
+
export declare function reconcileHostFrameworkPreset(options: ReconcileHostFrameworkPresetOptions): SetupBox<SetupState, null, null>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{isProjectResolved}from"../project-resolution.js";import{requireProjectPath}from"../state.js";import{syncHostFrameworkPreset}from"../vercel-project-framework.js";import{createPromptCommandOutput}from"#setup/cli/index.js";function reconcileHostFrameworkPreset(r){let i=r.deps??{syncHostFrameworkPreset};return{id:`reconcile-host-framework-preset`,shouldRun(t){return t.deploymentPending&&t.channelSelection.includes(`web`)&&isProjectResolved(t.project)},async gather(){return null},async perform({state:e,signal:n}){let a=requireProjectPath(e),o=createPromptCommandOutput(r.prompter.log);return await i.syncHostFrameworkPreset(r.prompter,a,o,{signal:n}),null},apply(e){return e}}}export{reconcileHostFrameworkPreset};
|