eve 0.30.8 → 0.31.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (211) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/README.md +5 -6
  3. package/dist/src/acp/adapter.d.ts +10 -4
  4. package/dist/src/acp/adapter.js +1 -1
  5. package/dist/src/channel/adapter-context.d.ts +1 -1
  6. package/dist/src/channel/adapter.d.ts +2 -4
  7. package/dist/src/channel/adapter.js +1 -1
  8. package/dist/src/channel/channel-address.d.ts +58 -0
  9. package/dist/src/channel/channel-address.js +1 -0
  10. package/dist/src/channel/channel-operations.d.ts +72 -0
  11. package/dist/src/channel/channel-operations.js +1 -0
  12. package/dist/src/channel/compiled-channel.d.ts +10 -6
  13. package/dist/src/channel/cross-channel-receive.d.ts +13 -25
  14. package/dist/src/channel/cross-channel-receive.js +2 -2
  15. package/dist/src/channel/receive-target.d.ts +1 -2
  16. package/dist/src/channel/routes.d.ts +21 -149
  17. package/dist/src/channel/schedule.d.ts +1 -1
  18. package/dist/src/channel/schedule.js +1 -1
  19. package/dist/src/channel/send-input.d.ts +6 -0
  20. package/dist/src/channel/send-input.js +1 -0
  21. package/dist/src/channel/session.d.ts +44 -30
  22. package/dist/src/channel/session.js +1 -1
  23. package/dist/src/channel/types.d.ts +8 -35
  24. package/dist/src/chunks/{use-eve-agent-DDoDDmJ2.js → use-eve-agent-CF5D6jSV.js} +339 -367
  25. package/dist/src/chunks/{use-eve-agent-Bx-ONuyb.js → use-eve-agent-DbYZLG0h.js} +342 -368
  26. package/dist/src/cli/commands/agent-prompt/build-and-verify.md +1 -2
  27. package/dist/src/cli/commands/channel-add-conflicts.js +1 -1
  28. package/dist/src/cli/commands/info.d.ts +1 -1
  29. package/dist/src/cli/commands/info.js +1 -1
  30. package/dist/src/cli/dev/tui/runner.d.ts +1 -1
  31. package/dist/src/cli/dev/tui/runner.js +1 -1
  32. package/dist/src/cli/dev/tui/subagent-pump.js +1 -1
  33. package/dist/src/cli/dev/tui/tui.js +1 -1
  34. package/dist/src/cli/invoke/invoke.d.ts +1 -1
  35. package/dist/src/cli/invoke/invoke.js +1 -1
  36. package/dist/src/cli/invoke/result.d.ts +0 -11
  37. package/dist/src/cli/invoke/result.js +1 -1
  38. package/dist/src/client/client-error.d.ts +2 -0
  39. package/dist/src/client/client-error.js +1 -1
  40. package/dist/src/client/client.d.ts +7 -14
  41. package/dist/src/client/client.js +1 -1
  42. package/dist/src/client/eve-agent-store.d.ts +4 -4
  43. package/dist/src/client/eve-agent-store.js +1 -1
  44. package/dist/src/client/index.d.ts +2 -1
  45. package/dist/src/client/index.js +1 -1
  46. package/dist/src/client/message-response.d.ts +2 -7
  47. package/dist/src/client/message-response.js +1 -1
  48. package/dist/src/client/open-stream.js +1 -1
  49. package/dist/src/client/session-controls.d.ts +29 -0
  50. package/dist/src/client/session-controls.js +1 -0
  51. package/dist/src/client/session-utils.d.ts +0 -20
  52. package/dist/src/client/session-utils.js +1 -1
  53. package/dist/src/client/session.d.ts +26 -90
  54. package/dist/src/client/session.js +1 -1
  55. package/dist/src/client/sessions.d.ts +20 -0
  56. package/dist/src/client/sessions.js +1 -0
  57. package/dist/src/client/types.d.ts +26 -47
  58. package/dist/src/compiler/normalize-subagent.js +1 -1
  59. package/dist/src/evals/cli/eval-client.js +1 -1
  60. package/dist/src/evals/context.js +1 -1
  61. package/dist/src/evals/session.d.ts +7 -6
  62. package/dist/src/evals/session.js +1 -1
  63. package/dist/src/evals/types.d.ts +9 -9
  64. package/dist/src/execution/agent-handle-dispatch.js +1 -1
  65. package/dist/src/execution/cancel-descendant-turns-step.js +1 -1
  66. package/dist/src/execution/dispatch-runtime-actions-step.js +1 -1
  67. package/dist/src/execution/remote-agent-dispatch.d.ts +1 -3
  68. package/dist/src/execution/remote-agent-dispatch.js +1 -1
  69. package/dist/src/execution/runtime-context.js +1 -1
  70. package/dist/src/execution/runtime-errors.d.ts +1 -1
  71. package/dist/src/execution/session-command-token.d.ts +2 -0
  72. package/dist/src/execution/session-command-token.js +1 -1
  73. package/dist/src/execution/settle-cancelled-turn-step.js +1 -1
  74. package/dist/src/execution/subagent-hitl-proxy.js +1 -1
  75. package/dist/src/execution/turn-control-receiver.d.ts +2 -2
  76. package/dist/src/execution/turn-workflow.js +1 -1
  77. package/dist/src/execution/workflow-entry.js +1 -1
  78. package/dist/src/execution/workflow-runtime.js +1 -1
  79. package/dist/src/harness/cancelled-turn-emission.d.ts +1 -1
  80. package/dist/src/harness/cancelled-turn-emission.js +1 -1
  81. package/dist/src/harness/emission.d.ts +1 -1
  82. package/dist/src/harness/emission.js +1 -1
  83. package/dist/src/harness/handles/prompt.d.ts +22 -3
  84. package/dist/src/harness/handles/prompt.js +1 -1
  85. package/dist/src/harness/handles/store.d.ts +0 -5
  86. package/dist/src/harness/handles/store.js +1 -1
  87. package/dist/src/harness/runtime-actions.js +1 -1
  88. package/dist/src/harness/session-limit-enforcement.js +1 -1
  89. package/dist/src/harness/tool-loop.js +1 -1
  90. package/dist/src/internal/application/package.js +1 -1
  91. package/dist/src/internal/nitro/dev-runtime-artifacts.js +1 -1
  92. package/dist/src/internal/nitro/dev-runtime-source-snapshot-copy.js +1 -1
  93. package/dist/src/internal/nitro/dev-runtime-source-snapshot-local-roots.d.ts +15 -0
  94. package/dist/src/internal/nitro/dev-runtime-source-snapshot-local-roots.js +1 -0
  95. package/dist/src/internal/nitro/dev-runtime-source-snapshot.d.ts +14 -2
  96. package/dist/src/internal/nitro/dev-runtime-source-snapshot.js +1 -1
  97. package/dist/src/internal/nitro/host/dev-server-http.js +1 -1
  98. package/dist/src/internal/nitro/routes/channel-dispatch.d.ts +2 -5
  99. package/dist/src/internal/nitro/routes/channel-dispatch.js +1 -1
  100. package/dist/src/internal/nitro/routes/channel-route-context.d.ts +4 -3
  101. package/dist/src/internal/nitro/routes/channel-route-context.js +1 -1
  102. package/dist/src/packages/eve-catalog/src/index.js +1 -1
  103. package/dist/src/protocol/cancel-turn.d.ts +9 -4
  104. package/dist/src/protocol/cancel-turn.js +1 -1
  105. package/dist/src/protocol/message.d.ts +4 -14
  106. package/dist/src/protocol/message.js +2 -2
  107. package/dist/src/protocol/reset-session.d.ts +1 -1
  108. package/dist/src/protocol/routes.d.ts +27 -47
  109. package/dist/src/protocol/routes.js +1 -1
  110. package/dist/src/public/channels/chat-sdk/chatSdkChannel.d.ts +19 -21
  111. package/dist/src/public/channels/chat-sdk/chatSdkChannel.js +2 -2
  112. package/dist/src/public/channels/discord/discordChannel.d.ts +4 -4
  113. package/dist/src/public/channels/discord/discordChannel.js +1 -1
  114. package/dist/src/public/channels/eve.d.ts +11 -10
  115. package/dist/src/public/channels/eve.js +1 -1
  116. package/dist/src/public/channels/github/dispatch.d.ts +8 -8
  117. package/dist/src/public/channels/github/dispatch.js +1 -1
  118. package/dist/src/public/channels/github/githubChannel.d.ts +3 -3
  119. package/dist/src/public/channels/github/githubChannel.js +1 -1
  120. package/dist/src/public/channels/github/pr-context.d.ts +1 -1
  121. package/dist/src/public/channels/index.d.ts +1 -1
  122. package/dist/src/public/channels/linear/linearChannel.d.ts +3 -3
  123. package/dist/src/public/channels/linear/linearChannel.js +1 -1
  124. package/dist/src/public/channels/slack/index.d.ts +1 -1
  125. package/dist/src/public/channels/slack/interactions.d.ts +3 -4
  126. package/dist/src/public/channels/slack/interactions.js +1 -1
  127. package/dist/src/public/channels/slack/session-operations.d.ts +37 -0
  128. package/dist/src/public/channels/slack/session-operations.js +1 -0
  129. package/dist/src/public/channels/slack/slackChannel.d.ts +55 -74
  130. package/dist/src/public/channels/slack/slackChannel.js +1 -1
  131. package/dist/src/public/channels/teams/teamsChannel.d.ts +3 -3
  132. package/dist/src/public/channels/teams/teamsChannel.js +1 -1
  133. package/dist/src/public/channels/telegram/telegramChannel.d.ts +4 -4
  134. package/dist/src/public/channels/telegram/telegramChannel.js +1 -1
  135. package/dist/src/public/channels/twilio/twilioChannel.d.ts +3 -3
  136. package/dist/src/public/channels/twilio/twilioChannel.js +1 -1
  137. package/dist/src/public/definitions/callback-context.d.ts +1 -2
  138. package/dist/src/public/definitions/channel.d.ts +21 -86
  139. package/dist/src/public/definitions/channel.js +1 -1
  140. package/dist/src/public/definitions/remote-agent.js +1 -1
  141. package/dist/src/public/definitions/schedule.d.ts +16 -16
  142. package/dist/src/public/schedules/index.d.ts +1 -1
  143. package/dist/src/react/use-eve-agent.d.ts +7 -4
  144. package/dist/src/react/use-eve-agent.js +1 -1
  145. package/dist/src/runtime/agent/bootstrap-model-utils.d.ts +11 -0
  146. package/dist/src/runtime/agent/bootstrap-model-utils.js +1 -1
  147. package/dist/src/runtime/agent/mock-model-adapter.js +1 -1
  148. package/dist/src/runtime/agent/mock-model-fixtures.js +2 -2
  149. package/dist/src/runtime/prompt/compose.js +1 -1
  150. package/dist/src/runtime/subagents/dynamic-remote-agent-config.js +1 -1
  151. package/dist/src/runtime/types.d.ts +2 -2
  152. package/dist/src/services/inspect-application.d.ts +1 -1
  153. package/dist/src/services/inspect-application.js +1 -1
  154. package/dist/src/setup/channel-add-conflicts.js +1 -1
  155. package/dist/src/setup/scaffold/create/project.js +1 -1
  156. package/dist/src/setup/scaffold/create/web-template.d.ts +1 -1
  157. package/dist/src/setup/scaffold/create/web-template.js +29 -17
  158. package/dist/src/shared/channel-definition.d.ts +7 -7
  159. package/dist/src/shared/schedule-definition.d.ts +2 -2
  160. package/dist/src/svelte/index.js +1 -1
  161. package/dist/src/svelte/use-eve-agent.d.ts +8 -5
  162. package/dist/src/svelte/use-eve-agent.js +1 -1
  163. package/dist/src/vue/index.js +1 -1
  164. package/dist/src/vue/use-eve-agent.d.ts +8 -5
  165. package/dist/src/vue/use-eve-agent.js +1 -1
  166. package/docs/README.md +6 -6
  167. package/docs/channels/chat-sdk.mdx +5 -6
  168. package/docs/channels/custom.mdx +116 -144
  169. package/docs/channels/discord.mdx +1 -1
  170. package/docs/channels/eve.mdx +76 -30
  171. package/docs/channels/github.mdx +1 -1
  172. package/docs/channels/linear.mdx +6 -8
  173. package/docs/channels/overview.mdx +2 -2
  174. package/docs/channels/slack.mdx +46 -15
  175. package/docs/channels/telegram.mdx +1 -1
  176. package/docs/channels/twilio.mdx +1 -1
  177. package/docs/concepts/default-harness.md +11 -3
  178. package/docs/concepts/execution-model-and-durability.mdx +17 -5
  179. package/docs/concepts/sessions-runs-and-streaming.md +42 -16
  180. package/docs/evals/cases.mdx +3 -3
  181. package/docs/evals/targets.mdx +1 -1
  182. package/docs/guides/auth-and-route-protection.md +2 -1
  183. package/docs/guides/client/continuations.mdx +50 -77
  184. package/docs/guides/client/messages.mdx +29 -33
  185. package/docs/guides/client/output-schema.mdx +7 -14
  186. package/docs/guides/client/overview.mdx +40 -11
  187. package/docs/guides/client/streaming.mdx +17 -23
  188. package/docs/guides/frontend/nuxt.mdx +1 -1
  189. package/docs/guides/frontend/overview.mdx +40 -36
  190. package/docs/guides/frontend/sveltekit.mdx +1 -1
  191. package/docs/guides/frontend/use-eve-agent-svelte.mdx +19 -23
  192. package/docs/guides/frontend/use-eve-agent-vue.mdx +21 -25
  193. package/docs/guides/instrumentation.md +1 -1
  194. package/docs/patterns/dynamic-scheduling.md +16 -15
  195. package/docs/schedules.mdx +10 -11
  196. package/docs/subagents.mdx +1 -1
  197. package/docs/tools/human-in-the-loop.md +1 -1
  198. package/docs/tutorial/ship-it.mdx +1 -1
  199. package/package.json +1 -1
  200. package/dist/src/channel/cancel.d.ts +0 -6
  201. package/dist/src/channel/cancel.js +0 -1
  202. package/dist/src/channel/clear-session.d.ts +0 -4
  203. package/dist/src/channel/clear-session.js +0 -1
  204. package/dist/src/channel/compact-session.d.ts +0 -4
  205. package/dist/src/channel/compact-session.js +0 -1
  206. package/dist/src/channel/reset-session.d.ts +0 -6
  207. package/dist/src/channel/reset-session.js +0 -1
  208. package/dist/src/channel/resolve-active-session.d.ts +0 -4
  209. package/dist/src/channel/resolve-active-session.js +0 -1
  210. package/dist/src/channel/send.d.ts +0 -6
  211. package/dist/src/channel/send.js +0 -1
@@ -1,18 +1,19 @@
1
- import { CHANNEL_SENTINEL } from "#channel/compiled-channel.js";
1
+ import { type ChannelReference } from "#channel/compiled-channel.js";
2
2
  import { type ChannelCorsOptions } from "#channel/cors.js";
3
- import type { TypedReceiveTarget } from "#channel/receive-target.js";
4
- import type { RouteDefinition, SendFn } from "#channel/routes.js";
3
+ import type { ChannelFrom, ChannelReceiveContext, ChannelResolveSession, ChannelRespondOptions, ChannelSendOptions, ChannelSource } from "#channel/channel-operations.js";
4
+ import type { RouteDefinition } from "#channel/routes.js";
5
5
  import type { Session } from "#channel/session.js";
6
- import type { CancelTurnInput, CancelTurnResult, DeliverInput, GetEventStreamOptions, RunHandle, RunInput } from "#channel/types.js";
7
- import type { UnstampedMessageStreamEvent, MessageStreamEvent } from "#protocol/message.js";
6
+ import type { UnstampedMessageStreamEvent } from "#protocol/message.js";
8
7
  import type { SessionContext } from "#public/definitions/callback-context.js";
9
8
  import type { GenericChannelDefinition, GenericReceiveInput } from "#shared/channel-definition.js";
10
9
  declare const CHANNEL_METADATA_TYPE: unique symbol;
11
- export type { CancelTurnInput, CancelTurnResult, ClearSessionResult, CompactSessionResult, GetEventStreamOptions, } from "#channel/types.js";
10
+ export type { CancelTurnResult, ClearSessionResult, CompactSessionResult, GetEventStreamOptions, ResetSessionResult, SessionCallback, } from "#channel/types.js";
12
11
  export type { Session, SessionHandle } from "#channel/session.js";
12
+ export type { SessionRespondOptions, SessionSendOptions } from "#channel/session.js";
13
+ export type { ChannelFrom, ChannelReceiveContext, ChannelResolveSession, ChannelRespondOptions, ChannelSendOptions, ChannelSource, };
13
14
  export type { ChannelCors, ChannelCorsOptions } from "#channel/cors.js";
14
15
  export { GET, POST, PUT, PATCH, DELETE, WS } from "#channel/routes.js";
15
- export type { CancelFn, CancelOptions, ClearFn, ClearOptions, CompactFn, CompactOptions, ResetFn, ResetOptions, ResetResult, HttpRouteDefinition, RouteDefinition, RouteHandlerArgs, SendFn, SendOptions, SendPayload, ResolveActiveSessionFn, GetSessionFn, WebSocketMessage, WebSocketPeer, WebSocketRouteDefinition, WebSocketRouteHandler, WebSocketRouteHooks, WebSocketUpgradeRequest, WebSocketUpgradeResult, } from "#channel/routes.js";
16
+ export type { AttachSessionFn, HttpRouteDefinition, RouteDefinition, RouteHandlerArgs, WebSocketMessage, WebSocketPeer, WebSocketRouteDefinition, WebSocketRouteHandler, WebSocketRouteHooks, WebSocketUpgradeRequest, WebSocketUpgradeResult, } from "#channel/routes.js";
16
17
  /**
17
18
  * HTTP method a route handles. Defaults to `"POST"` — almost every route
18
19
  * is a webhook. Override only when authoring a non-webhook route such as a
@@ -31,27 +32,14 @@ export type ChannelRouteMethod = ChannelMethod | "WEBSOCKET";
31
32
  * framework constructs this per request and passes it as the second
32
33
  * argument.
33
34
  *
34
- * Routes call into the agent to start sessions, deliver follow-ups,
35
- * cancel turns, and read events.
35
+ * Framework callback routes use this for request metadata and background work.
36
36
  */
37
37
  export interface RouteContext {
38
- /**
39
- * Handle to the agent that this route sends inbound requests to.
40
- * Conceptually the runtime + harness combined: routes call `run`,
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.
44
- *
45
- * Every route speaks the same `RunInput` shape regardless of which
46
- * webhook it serves — `agent` is platform-agnostic.
47
- */
48
- readonly agent: Agent;
49
38
  /**
50
39
  * Hands a background promise to the request host so the serverless
51
40
  * invocation stays alive until the promise resolves. Use this when the
52
41
  * route responds to the platform immediately (e.g. a Slack `200 OK`
53
- * acknowledgement) but still needs to drive an `agent.run()` call to
54
- * completion.
42
+ * acknowledgement) but still needs to finish background work.
55
43
  */
56
44
  readonly waitUntil: (task: Promise<unknown>) => void;
57
45
  /**
@@ -72,56 +60,6 @@ export interface RouteContext {
72
60
  */
73
61
  readonly requestIp: string | null;
74
62
  }
75
- /**
76
- * Route-facing handle to the agent that owns this request.
77
- *
78
- * `Agent` is conceptually the workflow runtime plus the tool-loop harness:
79
- * routes call `run` to start a new session of the agent, `deliver` to
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
- * interface (in `channel/types.ts`) is the underlying primitive — `Agent`
84
- * is the *public* shape exposed on `RouteContext` so route authors
85
- * speak in terms of the agent rather than the runtime.
86
- */
87
- export interface Agent {
88
- /**
89
- * Starts a new agent session and returns a handle. The session's identity
90
- * is the supplied `continuationToken` — subsequent calls to `deliver()`
91
- * with the same token resume the same session.
92
- */
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>;
104
- /**
105
- * Sends a follow-up message to a session that is currently parked waiting
106
- * for input. Throws if no parked session exists for the supplied
107
- * `continuationToken` — routes typically catch the failure and fall back
108
- * to `run()` to start a new session.
109
- */
110
- deliver(input: DeliverInput): Promise<{
111
- sessionId: string;
112
- }>;
113
- /**
114
- * Returns a readable NDJSON-style stream of lifecycle events for an
115
- * existing session. Used by the framework's HTTP session-stream route and by
116
- * any user-authored route that exposes an event-streaming endpoint.
117
- *
118
- * Nonnegative `options.startIndex` values skip events the caller has already
119
- * consumed. Negative values read relative to the current tail (`-1` starts
120
- * at the latest event). The framework HTTP session-stream route forwards
121
- * the `startIndex` query parameter unchanged.
122
- */
123
- getEventStream(sessionId: string, options?: GetEventStreamOptions): Promise<ReadableStream<MessageStreamEvent>>;
124
- }
125
63
  /**
126
64
  * Marker discriminator written into every {@link DisabledRouteSentinel}.
127
65
  */
@@ -151,25 +89,25 @@ type EventData<T extends UnstampedMessageStreamEvent["type"]> = Extract<Unstampe
151
89
  }> extends {
152
90
  data: infer D;
153
91
  } ? D : undefined;
154
- /**
155
- * Session operations on the `channel` argument of every channel event handler.
156
- */
157
- export interface ChannelSessionOps {
158
- readonly continuationToken: string;
159
- setContinuationToken(token: string): void;
92
+ /** Continuation routing on the `channel` argument of every channel event handler. */
93
+ export interface ChannelContinuationOps {
94
+ readonly continuation?: {
95
+ readonly token: string;
96
+ rekey(token: string): void;
97
+ };
160
98
  }
161
99
  /**
162
100
  * Channel context passed to event handlers: `TCtx` intersected with
163
- * {@link ChannelSessionOps}.
101
+ * {@link ChannelContinuationOps}.
164
102
  */
165
- export type ChannelContext<TCtx> = TCtx & ChannelSessionOps;
103
+ export type ChannelContext<TCtx> = TCtx & ChannelContinuationOps;
166
104
  type ChannelEventHandler<T extends UnstampedMessageStreamEvent["type"], TCtx> = (data: EventData<T>, channel: ChannelContext<TCtx>, ctx: SessionContext) => void | Promise<void>;
167
105
  type ChannelSessionFailedHandler<TCtx> = (data: EventData<"session.failed">, channel: ChannelContext<TCtx>) => void | Promise<void>;
168
106
  /**
169
107
  * Optional handlers keyed by session lifecycle event name. Each handler receives
170
108
  * the event `data`, the {@link ChannelContext}, and a {@link SessionContext}
171
109
  * `ctx`. The `session.failed` handler is the exception: it receives only `data`
172
- * and the channel context, with no `ctx`.
110
+ * and the channel context, with no `ctx`; its data includes `sessionId`.
173
111
  */
174
112
  export interface ChannelEvents<TCtx = void> {
175
113
  readonly "context.cleared"?: ChannelEventHandler<"context.cleared", TCtx>;
@@ -217,14 +155,11 @@ export type ChannelDefinition<TState = undefined, TCtx = void, TReceiveTarget =
217
155
  * {@link ChannelDefinition} it has no `TCtx` parameter: the context type is
218
156
  * internal to the definition.
219
157
  */
220
- export interface Channel<TState = undefined, TReceiveTarget = Record<string, unknown>, TMetadata extends Record<string, unknown> = Record<string, unknown>> extends TypedReceiveTarget<TReceiveTarget> {
221
- readonly __kind: typeof CHANNEL_SENTINEL;
158
+ export interface Channel<TState = undefined, TReceiveTarget = Record<string, unknown>, TMetadata extends Record<string, unknown> = Record<string, unknown>> extends ChannelReference<TReceiveTarget> {
222
159
  readonly [CHANNEL_METADATA_TYPE]?: TMetadata;
223
160
  readonly routes: readonly RouteDefinition<TState>[];
224
161
  readonly cors?: ChannelCorsOptions;
225
- readonly receive?: (input: ReceiveInput<TReceiveTarget>, args: {
226
- send: SendFn<TState>;
227
- }) => Promise<Session>;
162
+ readonly receive?: (input: ReceiveInput<TReceiveTarget>, ctx: ChannelReceiveContext<TState>) => Promise<Session>;
228
163
  }
229
164
  /**
230
165
  * Extracts the metadata projection type (`TMetadata`) from a {@link Channel}.
@@ -1 +1 @@
1
- import{CHANNEL_SENTINEL}from"#channel/compiled-channel.js";import{defaultDeliverResult}from"#channel/adapter.js";import{buildCallbackContext}from"#context/build-callback-context.js";import{normalizeChannelCors}from"#channel/cors.js";import{HTTP_ADAPTER_KIND}from"#channel/http.js";import{DELETE,GET,PATCH,POST,PUT,WS}from"#channel/routes.js";const DISABLED_ROUTE_SENTINEL_KIND=`eve:disabled-channel`;function disableRoute(){return{kind:DISABLED_ROUTE_SENTINEL_KIND}}function isDisabledRouteSentinel(e){return typeof e==`object`&&!!e&&e.kind===DISABLED_ROUTE_SENTINEL_KIND}function defineChannel(t){let n=buildAdapter(t),i=normalizeChannelCors(t.cors);return{__kind:CHANNEL_SENTINEL,routes:t.routes,adapter:n,cors:i,receive:t.receive}}const eventTypes=Object.keys({"context.cleared":null,"compaction.requested":null,"compaction.completed":null,"turn.started":null,"actions.requested":null,"action.partial":null,"action.result":null,"message.completed":null,"message.appended":null,"reasoning.appended":null,"reasoning.completed":null,"input.requested":null,"turn.failed":null,"turn.completed":null,"turn.cancelled":null,"session.failed":null,"session.completed":null,"session.waiting":null,"authorization.required":null,"authorization.completed":null});function buildAdapter(e){let r=e.state!=null,a=e.context!=null,o=e.fetchFile!==void 0,s=e.metadata,c=r||a||s!==void 0,l={},u=!1,d=e.events;for(let e of eventTypes){let t=d?.[e];t&&(u=!0,l[e]=(r,i)=>{let a={...i,continuationToken:i.session?.continuationToken??``,setContinuationToken:e=>i.session?.setContinuationToken(e)};if(e===`session.failed`)return t(r,a);let o=buildCallbackContext();return t(r,a,o)})}return!c&&!u&&!o?{kind:e.kindHint??HTTP_ADAPTER_KIND}:{kind:e.kindHint??`defineChannel`,state:r?{...e.state}:{},fetchFile:e.fetchFile,instrumentation:s===void 0?void 0:{metadata(e){return s(e)}},createAdapterContext(t){let n=t.state,r=t.session;return{...a?e.context(n,r):{},state:n,ctx:t.ctx,session:r}},deliver(e){return defaultDeliverResult(e)},...l}}export{DELETE,GET,PATCH,POST,PUT,WS,defineChannel,disableRoute,isDisabledRouteSentinel};
1
+ import{CHANNEL_SENTINEL}from"#channel/compiled-channel.js";import{defaultDeliverResult}from"#channel/adapter.js";import{buildCallbackContext}from"#context/build-callback-context.js";import{normalizeChannelCors}from"#channel/cors.js";import{HTTP_ADAPTER_KIND}from"#channel/http.js";import{DELETE,GET,PATCH,POST,PUT,WS}from"#channel/routes.js";const DISABLED_ROUTE_SENTINEL_KIND=`eve:disabled-channel`;function disableRoute(){return{kind:DISABLED_ROUTE_SENTINEL_KIND}}function isDisabledRouteSentinel(e){return typeof e==`object`&&!!e&&e.kind===DISABLED_ROUTE_SENTINEL_KIND}function defineChannel(t){let n=buildAdapter(t),i=normalizeChannelCors(t.cors);return{__kind:CHANNEL_SENTINEL,routes:t.routes,adapter:n,cors:i,receive:t.receive}}const eventTypes=Object.keys({"context.cleared":null,"compaction.requested":null,"compaction.completed":null,"turn.started":null,"actions.requested":null,"action.partial":null,"action.result":null,"message.completed":null,"message.appended":null,"reasoning.appended":null,"reasoning.completed":null,"input.requested":null,"turn.failed":null,"turn.completed":null,"turn.cancelled":null,"session.failed":null,"session.completed":null,"session.waiting":null,"authorization.required":null,"authorization.completed":null});function buildAdapter(e){let r=e.state!=null,a=e.context!=null,o=e.fetchFile!==void 0,s=e.metadata,c=r||a||s!==void 0,l={},u=!1,d=e.events;for(let e of eventTypes){let t=d?.[e];t&&(u=!0,l[e]=(r,i)=>{let{session:a,...o}=i,s={...o,continuation:a?.continuation===void 0?void 0:{token:a.continuation.token,rekey:e=>a.continuation?.rekey(e)}};if(e===`session.failed`)return t(r,s);let c=buildCallbackContext();return t(r,s,c)})}return!c&&!u&&!o?{kind:e.kindHint??HTTP_ADAPTER_KIND}:{kind:e.kindHint??`defineChannel`,state:r?{...e.state}:{},fetchFile:e.fetchFile,instrumentation:s===void 0?void 0:{metadata(e){return s(e)}},createAdapterContext(t){let n=t.state,r=t.session;return{...a?e.context(n,r):{},state:n,ctx:t.ctx,session:r}},deliver(e){return defaultDeliverResult(e)},...l}}export{DELETE,GET,PATCH,POST,PUT,WS,defineChannel,disableRoute,isDisabledRouteSentinel};
@@ -1 +1 @@
1
- import{EVE_CREATE_SESSION_ROUTE_PATH}from"#protocol/routes.js";function defineRemoteAgent(e){return{...e,kind:`remote`,path:e.path??EVE_CREATE_SESSION_ROUTE_PATH}}export{defineRemoteAgent};
1
+ import{EVE_SESSION_ROUTE_PATH}from"#protocol/routes.js";function defineRemoteAgent(e){return{...e,kind:`remote`,path:e.path??EVE_SESSION_ROUTE_PATH}}export{defineRemoteAgent};
@@ -1,20 +1,21 @@
1
- import type { CrossChannelReceiveFn } from "#channel/cross-channel-receive.js";
1
+ import type { CrossChannelToFn } from "#channel/cross-channel-receive.js";
2
2
  import type { SessionAuthContext } from "#channel/types.js";
3
3
  import type { ExactDefinition } from "#public/definitions/exact.js";
4
4
  import type { GenericScheduleDefinition, GenericScheduleRunHandler, GenericScheduleDefinitionFields } from "#shared/schedule-definition.js";
5
5
  export type { InferReceiveTarget, TypedReceiveTarget } from "#channel/receive-target.js";
6
+ /** Selects a proactive target channel from a schedule handler. */
7
+ export type ScheduleToFn = CrossChannelToFn;
6
8
  /**
7
9
  * Arguments passed to a schedule's `run` handler. A tight subset of a route
8
- * handler's args: `receive` starts a session on another channel and `waitUntil`
9
- * extends the task lifetime. There is no `send` because a schedule has no
10
- * current channel.
10
+ * handler's args: `to` selects another channel and `waitUntil`
11
+ * extends the task lifetime.
11
12
  */
12
13
  export interface ScheduleHandlerArgs {
13
14
  /**
14
- * Starts a session on another channel, using the same contract as a route
15
- * handler's `args.receive(channel, ...)`.
15
+ * Selects a proactive target on another channel. Call `.send(message, options)`
16
+ * on the returned handle.
16
17
  */
17
- readonly receive: CrossChannelReceiveFn;
18
+ readonly to: ScheduleToFn;
18
19
  /**
19
20
  * Extends the cron task's lifetime past handler return so the runtime awaits
20
21
  * background work (the parked workflow session, in-flight fetches, etc.)
@@ -22,14 +23,14 @@ export interface ScheduleHandlerArgs {
22
23
  */
23
24
  readonly waitUntil: (task: Promise<unknown>) => void;
24
25
  /**
25
- * Pre-built APP auth context. Pass this to `receive(channel, { auth })`
26
+ * Pre-built APP auth context. Pass this to `to(channel, target).send(message, { auth })`
26
27
  * for schedules that run on behalf of the agent itself.
27
28
  */
28
29
  readonly appAuth: SessionAuthContext;
29
30
  }
30
31
  /**
31
32
  * The `run` form of {@link ScheduleDefinition} invokes this handler when a
32
- * schedule's cron fires. It receives {@link ScheduleHandlerArgs} (`receive`,
33
+ * schedule's cron fires. It receives {@link ScheduleHandlerArgs} (`to`,
33
34
  * `waitUntil`, `appAuth`) and may return synchronously or as a promise.
34
35
  */
35
36
  export type ScheduleRunHandler = GenericScheduleRunHandler<ScheduleHandlerArgs>;
@@ -41,7 +42,7 @@ export type ScheduleRunHandler = GenericScheduleRunHandler<ScheduleHandlerArgs>;
41
42
  * on the prompt and discards the output (equivalent to the `<name>.md`
42
43
  * markdown form).
43
44
  * - `run`: full handler ({@link ScheduleRunHandler}). Receives
44
- * `{ receive, waitUntil, appAuth }` and decides what to do.
45
+ * `{ to, waitUntil, appAuth }` and decides what to do.
45
46
  *
46
47
  * Identity is derived from the file path under `agent/schedules/`; authored
47
48
  * definitions do not carry a `name` field.
@@ -60,12 +61,11 @@ export type ScheduleDefinition = GenericScheduleDefinition<ScheduleHandlerArgs>;
60
61
  *
61
62
  * export default defineSchedule({
62
63
  * cron: "0 9 * * 1-5",
63
- * async run({ receive, waitUntil, appAuth }) {
64
- * waitUntil(receive(slack, {
65
- * message: "Post the daily standup summary.",
66
- * target: { channelId: "C0123ABC" },
67
- * auth: appAuth,
68
- * }));
64
+ * async run({ to, waitUntil, appAuth }) {
65
+ * waitUntil(to(slack, { channelId: "C0123ABC" }).send(
66
+ * "Post the daily standup summary.",
67
+ * { auth: appAuth },
68
+ * ));
69
69
  * },
70
70
  * });
71
71
  * ```
@@ -1,4 +1,4 @@
1
1
  /**
2
2
  * Schedule authoring helpers for `agent/schedules/*` files.
3
3
  */
4
- export { defineSchedule, type ScheduleDefinition, type ScheduleHandlerArgs, type ScheduleRunHandler, type TypedReceiveTarget, } from "#public/definitions/schedule.js";
4
+ export { defineSchedule, type ScheduleDefinition, type ScheduleHandlerArgs, type ScheduleRunHandler, type ScheduleToFn, type TypedReceiveTarget, } from "#public/definitions/schedule.js";
@@ -3,7 +3,8 @@ import type { EveAgentReducer } from "#client/reducer.js";
3
3
  import type { ClientSession } from "#client/session.js";
4
4
  import { type EveMessageData } from "#client/message-reducer.js";
5
5
  import type { MessageStreamEvent } from "#protocol/message.js";
6
- import type { ClientAuth, HeadersValue, SendTurnPayload, SessionState } from "#client/types.js";
6
+ import type { UserContent } from "ai";
7
+ import type { ClientAuth, HeadersValue, RespondTurnOptions, SendTurnOptions, ClientSessionState } from "#client/types.js";
7
8
  export type { PrepareSend };
8
9
  /**
9
10
  * Lifecycle status of an eve agent session.
@@ -26,8 +27,10 @@ export type UseEveAgentSnapshot<TData> = EveAgentStoreSnapshot<TData>;
26
27
  export interface UseEveAgentHelpers<TData> extends UseEveAgentSnapshot<TData> {
27
28
  /** Resets the session: aborts any in-flight turn, recreates the owned session, and clears events and projected data. */
28
29
  readonly reset: () => void;
29
- /** Sends a turn (message, HITL responses, and/or client context). Rejects if a turn is already in flight. */
30
- readonly send: <TOutput = unknown>(input: SendTurnPayload<TOutput>) => Promise<void>;
30
+ /** Sends a message. Rejects if a turn is already in flight. */
31
+ readonly send: <TOutput = unknown>(message: string | UserContent, options?: SendTurnOptions<TOutput>) => Promise<void>;
32
+ /** Answers pending HITL input requests. Rejects if a turn is already in flight. */
33
+ readonly respond: <TOutput = unknown>(inputResponses: Parameters<ClientSession["respond"]>[0], options?: RespondTurnOptions<TOutput>) => Promise<void>;
31
34
  /** Aborts the in-flight turn's stream, if any. */
32
35
  readonly stop: () => void;
33
36
  }
@@ -63,7 +66,7 @@ export interface UseEveAgentOptions<TData> extends EveAgentStoreCallbacks<TData>
63
66
  readonly host?: string;
64
67
  /** Ordered prefix of the session stream used to rehydrate projected state. */
65
68
  readonly initialEvents?: readonly MessageStreamEvent[];
66
- readonly initialSession?: SessionState;
69
+ readonly initialSession?: ClientSessionState;
67
70
  /**
68
71
  * Project submitted user messages before eve confirms them with a
69
72
  * `message.received` stream event.
@@ -1 +1 @@
1
- import{EveAgentStore}from"#client/eve-agent-store.js";import{defaultMessageReducer}from"#client/message-reducer.js";import{useCallback,useMemo,useRef,useSyncExternalStore}from"react";import{resolveEveAgentHost}from"#client/agent-host.js";function useEveAgent(n={}){let r=useRef(void 0);if(!r.current){let t=n.reducer??defaultMessageReducer();r.current=new EveAgentStore({auth:n.auth,headers:n.headers,host:resolveEveAgentHost({agent:n.agent,host:n.host}),initialEvents:n.initialEvents,initialSession:n.initialSession,optimistic:n.optimistic,reducer:t,session:n.session})}let i=r.current;i.setCallbacks({onError:n.onError,onEvent:n.onEvent,onFinish:n.onFinish,onSessionChange:n.onSessionChange,prepareSend:n.prepareSend});let a=useSyncExternalStore(useCallback(e=>i.subscribe(e),[i]),()=>i.snapshot,()=>i.snapshot),o=useCallback(()=>i.reset(),[i]),s=useCallback(e=>i.send(e),[i]),c=useCallback(()=>i.stop(),[i]);return useMemo(()=>({...a,reset:o,send:s,stop:c}),[o,s,a,c])}export{useEveAgent};
1
+ import{EveAgentStore}from"#client/eve-agent-store.js";import{defaultMessageReducer}from"#client/message-reducer.js";import{useCallback,useMemo,useRef,useSyncExternalStore}from"react";import{resolveEveAgentHost}from"#client/agent-host.js";function useEveAgent(r={}){let i=useRef(void 0);if(!i.current){let n=r.reducer??defaultMessageReducer();i.current=new EveAgentStore({auth:r.auth,headers:r.headers,host:resolveEveAgentHost({agent:r.agent,host:r.host}),initialEvents:r.initialEvents,initialSession:r.initialSession,optimistic:r.optimistic,reducer:n,session:r.session})}let a=i.current;a.setCallbacks({onError:r.onError,onEvent:r.onEvent,onFinish:r.onFinish,onSessionChange:r.onSessionChange,prepareSend:r.prepareSend});let o=useSyncExternalStore(useCallback(e=>a.subscribe(e),[a]),()=>a.snapshot,()=>a.snapshot),s=useCallback(()=>a.reset(),[a]),c=useCallback((e,t)=>a.send({...t,message:e}),[a]),l=useCallback((e,t)=>a.send({...t,inputResponses:e}),[a]),u=useCallback(()=>a.stop(),[a]);return useMemo(()=>({...o,reset:s,respond:l,send:c,stop:u}),[s,l,c,o,u])}export{useEveAgent};
@@ -28,8 +28,19 @@ export declare function estimateTokenCount(value: string): number;
28
28
  export declare function getPromptContentText(content: BootstrapPrompt[number]["content"]): string;
29
29
  /**
30
30
  * Returns the text from the last user message in the prompt, or `null`.
31
+ *
32
+ * Skips framework-injected `[Agents]` announcements: they ride the user
33
+ * role in conversation history, but they are not authored input and must
34
+ * not drive mock directive parsing.
31
35
  */
32
36
  export declare function getLastUserPromptText(prompt: BootstrapPrompt): string | null;
37
+ /**
38
+ * True when the text is a framework-injected `[Agents]` announcement.
39
+ * Announcements are user-role scaffolding, not authored input: mock model
40
+ * heuristics must scan past them instead of treating them as the turn's
41
+ * message or as a turn boundary.
42
+ */
43
+ export declare function isAgentsAnnouncementText(text: string): boolean;
33
44
  /**
34
45
  * Joins all message content in the prompt into a single string.
35
46
  */
@@ -1 +1 @@
1
- const BOOTSTRAP_RESPONSE_TIMESTAMP=new Date(`2026-03-16T00:00:00.000Z`);function createBootstrapGenerateResult(t){return{content:[{text:t.text,type:`text`}],finishReason:{raw:void 0,unified:`stop`},response:{id:`bootstrap-response`,modelId:t.modelId,timestamp:BOOTSTRAP_RESPONSE_TIMESTAMP},usage:{inputTokens:{cacheRead:0,cacheWrite:0,noCache:t.inputTokens,total:t.inputTokens},outputTokens:{reasoning:0,text:t.outputTokens,total:t.outputTokens}},warnings:[]}}function createBootstrapStreamResult(e){let t=[{type:`stream-start`,warnings:e.warnings}];e.response!==void 0&&t.push({...e.response,type:`response-metadata`});let n=0;for(let r of e.content)switch(r.type){case`text`:{let e=`text_${n}`;n+=1,t.push({id:e,type:`text-start`}),r.text.length>0&&t.push({delta:r.text,id:e,type:`text-delta`}),t.push({id:e,type:`text-end`});break}case`tool-call`:t.push(r);break;default:break}return t.push({finishReason:e.finishReason,type:`finish`,usage:e.usage}),{stream:new ReadableStream({start(e){for(let n of t)e.enqueue(n);e.close()}})}}function estimateTokenCount(e){return Math.max(1,Math.ceil(e.trim().length/4))}function getPromptContentText(e){return typeof e==`string`?e:e.flatMap(e=>{if(typeof e==`string`)return[e];switch(e.type){case`text`:return[e.text];default:return[]}}).join(``)}function getLastUserPromptText(e){for(let t of[...e].reverse()){if(t.role!==`user`)continue;let e=getPromptContentText(t.content).trim();if(e.length>0)return e}return null}function getPromptText(e){return e.map(e=>getPromptContentText(e.content)).join(` `)}export{createBootstrapGenerateResult,createBootstrapStreamResult,estimateTokenCount,getLastUserPromptText,getPromptContentText,getPromptText};
1
+ import{AGENTS_SNIPPET_LABEL}from"#harness/handles/prompt.js";const BOOTSTRAP_RESPONSE_TIMESTAMP=new Date(`2026-03-16T00:00:00.000Z`);function createBootstrapGenerateResult(e){return{content:[{text:e.text,type:`text`}],finishReason:{raw:void 0,unified:`stop`},response:{id:`bootstrap-response`,modelId:e.modelId,timestamp:BOOTSTRAP_RESPONSE_TIMESTAMP},usage:{inputTokens:{cacheRead:0,cacheWrite:0,noCache:e.inputTokens,total:e.inputTokens},outputTokens:{reasoning:0,text:e.outputTokens,total:e.outputTokens}},warnings:[]}}function createBootstrapStreamResult(e){let t=[{type:`stream-start`,warnings:e.warnings}];e.response!==void 0&&t.push({...e.response,type:`response-metadata`});let n=0;for(let r of e.content)switch(r.type){case`text`:{let e=`text_${n}`;n+=1,t.push({id:e,type:`text-start`}),r.text.length>0&&t.push({delta:r.text,id:e,type:`text-delta`}),t.push({id:e,type:`text-end`});break}case`tool-call`:t.push(r);break;default:break}return t.push({finishReason:e.finishReason,type:`finish`,usage:e.usage}),{stream:new ReadableStream({start(e){for(let n of t)e.enqueue(n);e.close()}})}}function estimateTokenCount(e){return Math.max(1,Math.ceil(e.trim().length/4))}function getPromptContentText(e){return typeof e==`string`?e:e.flatMap(e=>{if(typeof e==`string`)return[e];switch(e.type){case`text`:return[e.text];default:return[]}}).join(``)}function getLastUserPromptText(e){for(let t of[...e].reverse()){if(t.role!==`user`)continue;let e=getPromptContentText(t.content).trim();if(!isAgentsAnnouncementText(e)&&e.length>0)return e}return null}function isAgentsAnnouncementText(t){return t.startsWith(AGENTS_SNIPPET_LABEL)}function getPromptText(e){return e.map(e=>getPromptContentText(e.content)).join(` `)}export{createBootstrapGenerateResult,createBootstrapStreamResult,estimateTokenCount,getLastUserPromptText,getPromptContentText,getPromptText,isAgentsAnnouncementText};
@@ -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=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
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,isAgentsAnnouncementText}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`){if(isAgentsAnnouncementText(getPromptContentText(n.content).trim()))continue;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};
@@ -1,3 +1,3 @@
1
- import{LOAD_SKILL_TOOL_NAME}from"#runtime/skills/fragment-context.js";import{getPromptContentText}from"#runtime/agent/bootstrap-model-utils.js";import{createJsonSchemaSample}from"#runtime/agent/mock-structured-output.js";function createMockAuthoredToolInput(e,t,r){let i=getToolInputPropertyNames(e.inputSchema);if(e.name===`ask_question`||hasProperties(i,[`prompt`,`options`]))return createAskQuestionInput(t);if(i.includes(`command`))return{command:resolveShellCommand(t)};if(i.includes(`topic`)||!hasDeclaredInputProperties(e.inputSchema)&&/\btopic\b/u.test(normalizeText(t)))return{topic:resolveLookupTopic(t)};let a=extractAnchoredInputs(i,t);if(Object.keys(a).length>0)return a;if(i.length===1&&i[0]===`message`)return{message:t};if(i.includes(`city`)||!hasDeclaredInputProperties(e.inputSchema))return{city:r};let o=createJsonSchemaSample(e.inputSchema);return isRecord(o)?o:{}}function extractAnchoredInputs(e,t){let n={};for(let r of e){let e=RegExp(`\\b${escapeRegExp(r)}\\b\\s*(?:to|=|:)?\\s*(?:\`([^\`]+)\`|"([^"]+)"|'([^']+)')`,`iu`).exec(t),i=e?.[1]??e?.[2]??e?.[3];i!==void 0&&(n[r]=i.trim())}return n}function escapeRegExp(e){return e.replace(/[$()*+.?[\\\]^{|}]/gu,String.raw`\$&`)}function resolveMockFixtureToken(e){let n=e.filter(e=>e.role===`system`).map(e=>getPromptContentText(e.content)).join(`
2
- `),r=[...getLoadedSkillResultTexts(e),n,getTrailingUserText(e)];for(let e of r){let t=resolveExactFixtureReply(e);if(t!==null)return t}return null}function resolveWeatherCity(e){let t=/"city"\s*:\s*"([^"]+)"/u.exec(e);return t?.[1]?t[1].trim():(/\b(?:in|for)\s+([A-Za-z][A-Za-z\s.-]*?)(?:[?.!,]|$)/u.exec(e)??/\b([A-Z][a-z]+(?:\s+[A-Z][a-z]+)*)\b/u.exec(e))?.[1]?.trim()||`Brooklyn`}function formatToolOutput(e){if(typeof e==`string`)return e;try{return JSON.stringify(e)}catch{return String(e)}}function getTrailingUserText(e){let n=[];for(let r of[...e].reverse())if(r.role!==`system`){if(r.role!==`user`)break;n.unshift(getPromptContentText(r.content))}return n.join(`
1
+ import{LOAD_SKILL_TOOL_NAME}from"#runtime/skills/fragment-context.js";import{getPromptContentText,isAgentsAnnouncementText}from"#runtime/agent/bootstrap-model-utils.js";import{createJsonSchemaSample}from"#runtime/agent/mock-structured-output.js";function createMockAuthoredToolInput(e,t,n){let i=getToolInputPropertyNames(e.inputSchema);if(e.name===`ask_question`||hasProperties(i,[`prompt`,`options`]))return createAskQuestionInput(t);if(i.includes(`command`))return{command:resolveShellCommand(t)};if(i.includes(`topic`)||!hasDeclaredInputProperties(e.inputSchema)&&/\btopic\b/u.test(normalizeText(t)))return{topic:resolveLookupTopic(t)};let a=extractAnchoredInputs(i,t);if(Object.keys(a).length>0)return a;if(i.length===1&&i[0]===`message`)return{message:t};if(i.includes(`city`)||!hasDeclaredInputProperties(e.inputSchema))return{city:n};let o=createJsonSchemaSample(e.inputSchema);return isRecord(o)?o:{}}function extractAnchoredInputs(e,t){let n={};for(let r of e){let e=RegExp(`\\b${escapeRegExp(r)}\\b\\s*(?:to|=|:)?\\s*(?:\`([^\`]+)\`|"([^"]+)"|'([^']+)')`,`iu`).exec(t),i=e?.[1]??e?.[2]??e?.[3];i!==void 0&&(n[r]=i.trim())}return n}function escapeRegExp(e){return e.replace(/[$()*+.?[\\\]^{|}]/gu,String.raw`\$&`)}function resolveMockFixtureToken(e){let n=e.filter(e=>e.role===`system`).map(e=>getPromptContentText(e.content)).join(`
2
+ `),r=[...getLoadedSkillResultTexts(e),n,getTrailingUserText(e)];for(let e of r){let t=resolveExactFixtureReply(e);if(t!==null)return t}return null}function resolveWeatherCity(e){let t=/"city"\s*:\s*"([^"]+)"/u.exec(e);return t?.[1]?t[1].trim():(/\b(?:in|for)\s+([A-Za-z][A-Za-z\s.-]*?)(?:[?.!,]|$)/u.exec(e)??/\b([A-Z][a-z]+(?:\s+[A-Z][a-z]+)*)\b/u.exec(e))?.[1]?.trim()||`Brooklyn`}function formatToolOutput(e){if(typeof e==`string`)return e;try{return JSON.stringify(e)}catch{return String(e)}}function getTrailingUserText(e){let r=[];for(let i of[...e].reverse()){if(i.role===`system`)continue;if(i.role!==`user`)break;let e=getPromptContentText(i.content);isAgentsAnnouncementText(e.trim())||r.unshift(e)}return r.join(`
3
3
  `)}function getLoadedSkillResultTexts(t){return t.flatMap(t=>t.role!==`tool`&&t.role!==`assistant`?[]:(typeof t.content==`string`?[t.content]:t.content).flatMap(t=>typeof t==`string`||t.type!==`tool-result`||t.toolName!==LOAD_SKILL_TOOL_NAME||t.output.type===`execution-denied`?[]:[formatToolOutput(t.output.value)]))}function resolveExactFixtureReply(e){let t=matchExactValue(/\breply\s+with\s+the\s+exact\s+string\s+(`([^`]+)`|"([^"]+)"|'([^']+)'|([^\s.]+))\s+and\s+nothing\s+else\b/iu,e);if(t!==null)return t;let n=e.split(/\r?\n/u);for(let e=0;e<n.length;e+=1){let t=n[e]?.trim()??``,r=/\breply\s+with\s+exactly(?:\s+the\s+following\s+text\s+and\s+nothing\s+else)?:\s*(.+)$/iu.exec(t);if(r?.[1])return cleanExactValue(r[1]);if(/\breply\s+with\s+exactly\s+the\s+following\s+text\s+and\s+nothing\s+else:\s*$/iu.test(t)||/\breply\s+with\s+exactly:\s*$/iu.test(t)){let t=n.slice(e+1).map(e=>e.trim()).find(e=>e.length>0);if(t!==void 0)return cleanExactValue(t)}}return matchExactValue(/\binclude\s+the\s+exact\s+token\s+(`([^`]+)`|"([^"]+)"|'([^']+)'|([^\s.]+))\s+verbatim\b/iu,e)}function matchExactValue(e,t){let n=e.exec(t);return n===null?null:cleanExactValue(n[2]??n[3]??n[4]??n[5]??n[1]??``)}function cleanExactValue(e){return e.trim()}function getToolInputPropertyNames(e){return!isRecord(e)||!isRecord(e.properties)?[]:Object.keys(e.properties)}function hasDeclaredInputProperties(e){return isRecord(e)&&isRecord(e.properties)}function hasProperties(e,t){return t.every(t=>e.includes(t))}function createAskQuestionInput(e){let t=parseInputOptions(e),n={prompt:resolveQuestionPrompt(e)};return t.length>0&&(n.options=t),/\ballow\s*freeform\s+(?:to\s+)?true\b|\ballowfreeform\s+(?:to\s+)?true\b/iu.test(e)&&(n.allowFreeform=!0),n}function parseInputOptions(e){return[...e.matchAll(/\bid\b\s*:?\s*"([^"]+)"\s*,\s*label\b\s*:?\s*"([^"]+)"/giu)].map(e=>({id:e[1]??``,label:e[2]??``}))}function resolveQuestionPrompt(e){let t=/\b(?:set\s+)?prompt\s+to:\s*'([^']+)'/iu.exec(e)??/\b(?:set\s+)?prompt\s+to:\s*"([^"]+)"/iu.exec(e);return t?.[1]?t[1].trim():/\bask(?:\s+me)?\s+(?:to\s+)?(.+?)(?:\.|$)/iu.exec(e)?.[1]?.trim()||`Please choose an option.`}function resolveShellCommand(e){let t=/`([^`]+)`/u.exec(e);return t?.[1]?t[1].trim():(/\b(?:run|command)\s+["']([^"']+)["']/iu.exec(e)??/\bcommand\s+(.+?)(?:\.|$)/iu.exec(e))?.[1]?.trim()||`pwd`}function resolveLookupTopic(e){return/\btopic\s+['"]?([A-Za-z0-9_.-]+)['"]?/u.exec(e)?.[1]??`demo`}function normalizeText(e){return e.toLowerCase().replace(/[^a-z0-9]+/gu,` `).trim()}function isRecord(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}export{createMockAuthoredToolInput,formatToolOutput,resolveMockFixtureToken,resolveWeatherCity};
@@ -1,2 +1,2 @@
1
1
  import{formatAvailableSkillsSection}from"#execution/skills/instructions.js";import{createWorkspacePromptSection}from"#runtime/workspace/spec.js";import{formatConnectionsSection}from"#runtime/prompt/connections.js";function composeRuntimeBasePrompt(e){return[...createInstructionsPromptBlocks(e.instructions),...createWorkspacePromptBlocks(e.workspaceSpec),...e.toolsAvailable?[`Tool execution
2
- A single tool or subagent call runs as one serial action. If you call multiple independent tools or subagents in one response, eve treats that batch as parallel work. Only batch work that is independent and does not rely on another call in the same response.`]:[],...e.subagentsAvailable&&e.persistentSubagentSessions?["Agent messaging\nAgents you have already delegated to stay available after they answer. The system-message `<agents>` list is only a record of those existing agents — their `agentId`, name, and latest status. It does not limit which subagent tools you can call: your tool list is the source of truth, and any subagent tool can always be called without `agentId` to start a new agent, including when the `<agents>` list is empty or absent. Pass `agentId` to the same subagent tool only to continue one of those existing agents' sessions."]:[],...createConnectionsPromptBlocks(e.connections),...createSkillsPromptBlocks(e.skills)]}function createInstructionsPromptBlocks(e){if(e===void 0)return[];let t=e.markdown.trim();return t.length===0?[]:[`Instructions (${e.name})\n${t}`]}function createWorkspacePromptBlocks(e){if(e===void 0)return[];let n=createWorkspacePromptSection(e);return n===void 0?[]:[n]}function createConnectionsPromptBlocks(e){return!e||e.length===0?[]:[formatConnectionsSection(e)]}function createSkillsPromptBlocks(t){if(!t||t.length===0)return[];let n=formatAvailableSkillsSection(t);return n===null?[]:[n]}export{composeRuntimeBasePrompt};
2
+ A single tool or subagent call runs as one serial action. If you call multiple independent tools or subagents in one response, eve treats that batch as parallel work. Only batch work that is independent and does not rely on another call in the same response.`]:[],...e.subagentsAvailable&&e.persistentSubagentSessions?["Agent messaging\nAgents you have already delegated to stay available after they answer. eve injects the current `<agents>` list into the conversation as a note labeled `[Agents]`; it is added automatically by the framework, not written by the user, and never requires a reply. The list is only a record of those existing agents — their `agentId`, name, and latest status. It does not limit which subagent tools you can call: your tool list is the source of truth, and any subagent tool can always be called without `agentId` to start a new agent, including when the `<agents>` list is empty or absent. Pass `agentId` to the same subagent tool only to continue one of those existing agents' sessions."]:[],...createConnectionsPromptBlocks(e.connections),...createSkillsPromptBlocks(e.skills)]}function createInstructionsPromptBlocks(e){if(e===void 0)return[];let t=e.markdown.trim();return t.length===0?[]:[`Instructions (${e.name})\n${t}`]}function createWorkspacePromptBlocks(e){if(e===void 0)return[];let n=createWorkspacePromptSection(e);return n===void 0?[]:[n]}function createConnectionsPromptBlocks(e){return!e||e.length===0?[]:[formatConnectionsSection(e)]}function createSkillsPromptBlocks(t){if(!t||t.length===0)return[];let n=formatAvailableSkillsSection(t);return n===null?[]:[n]}export{composeRuntimeBasePrompt};
@@ -1 +1 @@
1
- import{expectBoolean,expectFunction,expectObjectRecord,expectOnlyKnownKeys,expectString,getOptionalStringRecordProperty}from"#internal/authored-module.js";import{EVE_CREATE_SESSION_ROUTE_PATH}from"#protocol/routes.js";import{serializeOutputSchema}from"#shared/tool-schema.js";async function normalizeDynamicRemoteAgentConfig(t){let i=`Dynamic subagent "${t.name}" must return defineAgent(...), defineRemoteAgent(...), or null.`,a=expectObjectRecord(t.value,i);if(expectOnlyKnownKeys(a,[`auth`,`description`,`forwardPrincipal`,`headers`,`kind`,`outputSchema`,`path`,`url`],i),a.kind!==`remote`)throw Error(i);let o=await resolveUrl(a.url,i),s=readCredentialsStepId(a);if(validateCredentials(a,i),(a.auth!==void 0||a.headers!==void 0)&&s===void 0)throw Error(`${i} Dynamic remote auth and headers must be compiled by eve so credentials stay out of durable workflow state.`);let c={description:expectString(a.description,i),path:a.path===void 0?EVE_CREATE_SESSION_ROUTE_PATH:expectString(a.path,i),url:o};return s!==void 0&&(c.credentialsStepId=s),a.forwardPrincipal!==void 0&&(c.forwardPrincipal=expectBoolean(a.forwardPrincipal,i)),a.outputSchema!==void 0&&(c.outputSchema=serializeOutputSchema(a.outputSchema)),c}async function resolveUrl(e,n){let r=typeof e==`function`?await expectFunction(e,n)():expectString(e,n);if(r.length===0)throw Error(`${n} The "url" field must resolve to a non-empty string.`);return r}function validateCredentials(e,n){e.auth!==void 0&&expectFunction(e.auth,n),e.headers!==void 0&&typeof e.headers!=`function`&&getOptionalStringRecordProperty(e,`headers`,n)}function readCredentialsStepId(e){let t=e.__eveResolveRemoteAgentCredentials;if(typeof t!=`function`)return;let n=t.stepId;return typeof n==`string`?n:void 0}export{normalizeDynamicRemoteAgentConfig};
1
+ import{expectBoolean,expectFunction,expectObjectRecord,expectOnlyKnownKeys,expectString,getOptionalStringRecordProperty}from"#internal/authored-module.js";import{EVE_SESSION_ROUTE_PATH}from"#protocol/routes.js";import{serializeOutputSchema}from"#shared/tool-schema.js";async function normalizeDynamicRemoteAgentConfig(t){let i=`Dynamic subagent "${t.name}" must return defineAgent(...), defineRemoteAgent(...), or null.`,a=expectObjectRecord(t.value,i);if(expectOnlyKnownKeys(a,[`auth`,`description`,`forwardPrincipal`,`headers`,`kind`,`outputSchema`,`path`,`url`],i),a.kind!==`remote`)throw Error(i);let o=await resolveUrl(a.url,i),s=readCredentialsStepId(a);if(validateCredentials(a,i),(a.auth!==void 0||a.headers!==void 0)&&s===void 0)throw Error(`${i} Dynamic remote auth and headers must be compiled by eve so credentials stay out of durable workflow state.`);let c={description:expectString(a.description,i),path:a.path===void 0?EVE_SESSION_ROUTE_PATH:expectString(a.path,i),url:o};return s!==void 0&&(c.credentialsStepId=s),a.forwardPrincipal!==void 0&&(c.forwardPrincipal=expectBoolean(a.forwardPrincipal,i)),a.outputSchema!==void 0&&(c.outputSchema=serializeOutputSchema(a.outputSchema)),c}async function resolveUrl(e,n){let r=typeof e==`function`?await expectFunction(e,n)():expectString(e,n);if(r.length===0)throw Error(`${n} The "url" field must resolve to a non-empty string.`);return r}function validateCredentials(e,n){e.auth!==void 0&&expectFunction(e.auth,n),e.headers!==void 0&&typeof e.headers!=`function`&&getOptionalStringRecordProperty(e,`headers`,n)}function readCredentialsStepId(e){let t=e.__eveResolveRemoteAgentCredentials;if(typeof t!=`function`)return;let n=t.stepId;return typeof n==`string`?n:void 0}export{normalizeDynamicRemoteAgentConfig};
@@ -199,7 +199,7 @@ export interface ResolvedChannelDefinition extends ResolvedModuleSourceRef {
199
199
  /**
200
200
  * Universal entry point for new sessions, called by cross-channel
201
201
  * initiators (the schedule dispatcher today). Typed precisely as
202
- * {@link CompiledChannel.receive} — `(input, { send }) => Session` —
202
+ * {@link CompiledChannel.receive} — `(input, ctx) => Session` —
203
203
  * so any caller passing the wrong context shape is a typecheck error,
204
204
  * not a runtime crash.
205
205
  *
@@ -211,7 +211,7 @@ export interface ResolvedChannelDefinition extends ResolvedModuleSourceRef {
211
211
  readonly receive?: CompiledChannel["receive"];
212
212
  /**
213
213
  * Reference to the authored {@link CompiledChannel} value the channel
214
- * module exported. Preserved so callers of `args.receive(channel, …)`
214
+ * module exported. Preserved so callers of `ctx.to(channel, target)`
215
215
  * can identify a target by the same imported reference. `undefined`
216
216
  * for framework-internal channels constructed without going through
217
217
  * `defineChannel`.
@@ -5,7 +5,7 @@ import { type ApplicationInfo } from "#internal/application/paths.js";
5
5
  */
6
6
  export interface ApplicationInspectionMessaging {
7
7
  readonly createSessionRoutePath: string;
8
- readonly continueSessionRoutePattern: string;
8
+ readonly sessionMessagesRoutePattern: string;
9
9
  readonly streamRoutePattern: string;
10
10
  }
11
11
  /**
@@ -1 +1 @@
1
- import{EVE_CONTINUE_SESSION_ROUTE_PATTERN,EVE_CREATE_SESSION_ROUTE_PATH,EVE_MESSAGE_STREAM_ROUTE_PATTERN}from"#protocol/routes.js";import{getApplicationInfo}from"#internal/application/paths.js";import{DiscoveryProjectResolutionError}from"#discover/project.js";import{CompileAgentError,compileAgent}from"#compiler/compile-agent.js";async function inspectApplication(t){let n=await loadCompiledApplicationState(t);return{application:getApplicationInfo(n?.project.appRoot??t),compiledState:n,messaging:{createSessionRoutePath:EVE_CREATE_SESSION_ROUTE_PATH,continueSessionRoutePattern:EVE_CONTINUE_SESSION_ROUTE_PATTERN,streamRoutePattern:EVE_MESSAGE_STREAM_ROUTE_PATTERN}}}async function loadCompiledApplicationState(e){try{return await compileAgent({startPath:e})}catch(e){if(e instanceof CompileAgentError)return e.result;if(e instanceof DiscoveryProjectResolutionError)return null;throw e}}export{inspectApplication};
1
+ import{EVE_SESSION_ROUTE_PATH,EVE_SESSION_ROUTE_PATTERN,EVE_SESSION_STREAM_ROUTE_PATTERN}from"#protocol/routes.js";import{getApplicationInfo}from"#internal/application/paths.js";import{DiscoveryProjectResolutionError}from"#discover/project.js";import{CompileAgentError,compileAgent}from"#compiler/compile-agent.js";async function inspectApplication(t){let n=await loadCompiledApplicationState(t);return{application:getApplicationInfo(n?.project.appRoot??t),compiledState:n,messaging:{createSessionRoutePath:EVE_SESSION_ROUTE_PATH,sessionMessagesRoutePattern:EVE_SESSION_ROUTE_PATTERN,streamRoutePattern:EVE_SESSION_STREAM_ROUTE_PATTERN}}}async function loadCompiledApplicationState(e){try{return await compileAgent({startPath:e})}catch(e){if(e instanceof CompileAgentError)return e.result;if(e instanceof DiscoveryProjectResolutionError)return null;throw e}}export{inspectApplication};
@@ -1 +1 @@
1
- import{EVE_CREATE_SESSION_ROUTE_PATH}from"#protocol/routes.js";import{join}from"node:path";import{compileChannelDefinition}from"#compiler/normalize-channel.js";import{discoverAgent}from"#discover/discover-agent.js";import{isNextJsProject}from"#setup/scaffold/index.js";const SCAFFOLDED_WEB_CHANNEL_LOGICAL_PATH=`channels/eve.ts`;async function inspectExistingChannelRegistrations(a){let o=join(a,`agent`),[{manifest:s},c]=await Promise.all([discoverAgent({agentRoot:o,appRoot:a}),isNextJsProject(a)]),l=new Set,u=new Set;for(let t of s.channels){let r=await compileChannelDefinition(o,t),i=Array.isArray(r)?r:[r];for(let n of i)n.kind===`channel`&&(n.method===`POST`&&n.urlPath===EVE_CREATE_SESSION_ROUTE_PATH&&l.add(t.logicalPath),n.adapterKind===`slack`&&u.add(t.logicalPath))}let d={};return[...l].some(e=>e!==SCAFFOLDED_WEB_CHANNEL_LOGICAL_PATH)&&(d.web=`POST ${EVE_CREATE_SESSION_ROUTE_PATH} already registered`),u.size>0&&(d.slack=`Slack channel already registered`),{disabledChannelReasons:d,webRouteOwners:[...l],slackOwners:[...u],webAppPresent:c}}function assertCanAddSelectedChannels(t,n){if(t.includes(`web`)){let t=n.webRouteOwners.find(e=>e!==SCAFFOLDED_WEB_CHANNEL_LOGICAL_PATH);if(t!==void 0)throw Error(`Cannot scaffold Web Chat because agent/${t} already defines POST ${EVE_CREATE_SESSION_ROUTE_PATH}. Web Chat scaffolds the same eve session routes.`)}if(t.includes(`slack`)){let e=n.slackOwners.find(e=>e!==`channels/slack.ts`);if(e!==void 0)throw Error(`Cannot scaffold Slack because agent/${e} already defines a Slack channel. Slack scaffolding would register the channel again.`)}}export{assertCanAddSelectedChannels,inspectExistingChannelRegistrations};
1
+ import{EVE_SESSION_ROUTE_PATH}from"#protocol/routes.js";import{join}from"node:path";import{compileChannelDefinition}from"#compiler/normalize-channel.js";import{discoverAgent}from"#discover/discover-agent.js";import{isNextJsProject}from"#setup/scaffold/index.js";const SCAFFOLDED_WEB_CHANNEL_LOGICAL_PATH=`channels/eve.ts`;async function inspectExistingChannelRegistrations(a){let o=join(a,`agent`),[{manifest:s},c]=await Promise.all([discoverAgent({agentRoot:o,appRoot:a}),isNextJsProject(a)]),l=new Set,u=new Set;for(let t of s.channels){let r=await compileChannelDefinition(o,t),i=Array.isArray(r)?r:[r];for(let n of i)n.kind===`channel`&&(n.method===`POST`&&n.urlPath===EVE_SESSION_ROUTE_PATH&&l.add(t.logicalPath),n.adapterKind===`slack`&&u.add(t.logicalPath))}let d={};return[...l].some(e=>e!==SCAFFOLDED_WEB_CHANNEL_LOGICAL_PATH)&&(d.web=`POST ${EVE_SESSION_ROUTE_PATH} already registered`),u.size>0&&(d.slack=`Slack channel already registered`),{disabledChannelReasons:d,webRouteOwners:[...l],slackOwners:[...u],webAppPresent:c}}function assertCanAddSelectedChannels(t,n){if(t.includes(`web`)){let t=n.webRouteOwners.find(e=>e!==SCAFFOLDED_WEB_CHANNEL_LOGICAL_PATH);if(t!==void 0)throw Error(`Cannot scaffold Web Chat because agent/${t} already defines POST ${EVE_SESSION_ROUTE_PATH}. Web Chat scaffolds the same eve session routes.`)}if(t.includes(`slack`)){let e=n.slackOwners.find(e=>e!==`channels/slack.ts`);if(e!==void 0)throw Error(`Cannot scaffold Slack because agent/${e} already defines a Slack channel. Slack scaffolding would register the channel again.`)}}export{assertCanAddSelectedChannels,inspectExistingChannelRegistrations};
@@ -1,4 +1,4 @@
1
- import{pinnedNodeEngineMajor}from"../../node-engine.js";import{SUPPORTED_AUTHORED_MODULE_FILE_EXTENSIONS}from"../update/module-files.js";import{pathExists,writeTextFile}from"../files.js";import{blockingCreateInPlaceEntries}from"../create-in-place.js";import{resolveVersionToken}from"../version-tokens.js";import{applyPackageManagerWorkspaceConfiguration,isPackageManagerWorkspaceMember,patchWorkspaceRootPackageJson}from"../workspace-root.js";import{WEB_APP_TEMPLATE_FILES}from"./web-template.js";import{mkdir,readdir,stat}from"node:fs/promises";import{basename,join,resolve}from"node:path";const CURRENT_DIRECTORY_PROJECT_NAME=`.`,DEFAULT_AI_PACKAGE_VERSION=`^7.0.38`,DEFAULT_CONNECT_PACKAGE_VERSION=`0.4.3`,DEFAULT_ZOD_PACKAGE_VERSION=`4.4.3`,DEFAULT_EVE_PACKAGE_CONTRACT={version:`0.30.8`,nodeEngine:`>=24`};function resolveEvePackageContract(e=DEFAULT_EVE_PACKAGE_CONTRACT){return{version:resolveVersionToken(`evePackage.version`,e.version),nodeEngine:resolveVersionToken(`evePackage.nodeEngine`,e.nodeEngine)}}function modelProviderSlug(e){let t=(e.split(`/`)[0]??``).replaceAll(/[^A-Za-z0-9._-]/gu,``);return t.length>0?t:`anthropic`}function byokProviderEnvVar(e){let t=modelProviderSlug(e).toUpperCase().replaceAll(/[^A-Z0-9]/gu,`_`);return`${/^[0-9]/.test(t)?`_`:``}${t}_API_KEY`}function agentTemplateFiles(e){return{"agent/agent.ts":BASE_AGENT_TEMPLATE.replaceAll(`__EVE_INIT_MODEL__`,e),"agent/channels/eve.ts":WEB_APP_TEMPLATE_FILES[`agent/channels/eve.ts`],"agent/instructions.md":AGENT_INSTRUCTIONS_TEMPLATE}}function renderTemplate(e,t){return e.replaceAll(`__EVE_INIT_APP_NAME__`,t.appName).replaceAll(`__EVE_INIT_MODEL__`,t.model).replaceAll(`__EVE_INIT_BYOK_PROVIDER__`,modelProviderSlug(t.model)).replaceAll(`__EVE_INIT_BYOK_ENV_VAR__`,byokProviderEnvVar(t.model)).replaceAll(`__EVE_INIT_PACKAGE_VERSION__`,formatEveDependencySpecifier(t.eveVersion)).replaceAll(`__EVE_INIT_AI_SDK_VERSION__`,t.aiPackageVersion).replaceAll(`__EVE_INIT_CONNECT_VERSION__`,t.connectPackageVersion).replaceAll(`__EVE_INIT_ZOD_VERSION__`,t.zodPackageVersion).replaceAll(`__EVE_INIT_TYPESCRIPT_VERSION__`,t.typescriptPackageVersion).replaceAll(`__EVE_INIT_TYPES_NODE_VERSION__`,t.nodeTypesVersion).replaceAll(`__EVE_INIT_NODE_ENGINE__`,t.nodeEngine)}function formatEveDependencySpecifier(e){return/^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z-.]+)?$/.test(e)?`^${e}`:e}const BASE_AGENT_TEMPLATE=`import { defineAgent } from "eve";
1
+ import{pinnedNodeEngineMajor}from"../../node-engine.js";import{SUPPORTED_AUTHORED_MODULE_FILE_EXTENSIONS}from"../update/module-files.js";import{pathExists,writeTextFile}from"../files.js";import{blockingCreateInPlaceEntries}from"../create-in-place.js";import{resolveVersionToken}from"../version-tokens.js";import{applyPackageManagerWorkspaceConfiguration,isPackageManagerWorkspaceMember,patchWorkspaceRootPackageJson}from"../workspace-root.js";import{WEB_APP_TEMPLATE_FILES}from"./web-template.js";import{mkdir,readdir,stat}from"node:fs/promises";import{basename,join,resolve}from"node:path";const CURRENT_DIRECTORY_PROJECT_NAME=`.`,DEFAULT_AI_PACKAGE_VERSION=`^7.0.38`,DEFAULT_CONNECT_PACKAGE_VERSION=`0.4.3`,DEFAULT_ZOD_PACKAGE_VERSION=`4.4.3`,DEFAULT_EVE_PACKAGE_CONTRACT={version:`0.31.0`,nodeEngine:`>=24`};function resolveEvePackageContract(e=DEFAULT_EVE_PACKAGE_CONTRACT){return{version:resolveVersionToken(`evePackage.version`,e.version),nodeEngine:resolveVersionToken(`evePackage.nodeEngine`,e.nodeEngine)}}function modelProviderSlug(e){let t=(e.split(`/`)[0]??``).replaceAll(/[^A-Za-z0-9._-]/gu,``);return t.length>0?t:`anthropic`}function byokProviderEnvVar(e){let t=modelProviderSlug(e).toUpperCase().replaceAll(/[^A-Z0-9]/gu,`_`);return`${/^[0-9]/.test(t)?`_`:``}${t}_API_KEY`}function agentTemplateFiles(e){return{"agent/agent.ts":BASE_AGENT_TEMPLATE.replaceAll(`__EVE_INIT_MODEL__`,e),"agent/channels/eve.ts":WEB_APP_TEMPLATE_FILES[`agent/channels/eve.ts`],"agent/instructions.md":AGENT_INSTRUCTIONS_TEMPLATE}}function renderTemplate(e,t){return e.replaceAll(`__EVE_INIT_APP_NAME__`,t.appName).replaceAll(`__EVE_INIT_MODEL__`,t.model).replaceAll(`__EVE_INIT_BYOK_PROVIDER__`,modelProviderSlug(t.model)).replaceAll(`__EVE_INIT_BYOK_ENV_VAR__`,byokProviderEnvVar(t.model)).replaceAll(`__EVE_INIT_PACKAGE_VERSION__`,formatEveDependencySpecifier(t.eveVersion)).replaceAll(`__EVE_INIT_AI_SDK_VERSION__`,t.aiPackageVersion).replaceAll(`__EVE_INIT_CONNECT_VERSION__`,t.connectPackageVersion).replaceAll(`__EVE_INIT_ZOD_VERSION__`,t.zodPackageVersion).replaceAll(`__EVE_INIT_TYPESCRIPT_VERSION__`,t.typescriptPackageVersion).replaceAll(`__EVE_INIT_TYPES_NODE_VERSION__`,t.nodeTypesVersion).replaceAll(`__EVE_INIT_NODE_ENGINE__`,t.nodeEngine)}function formatEveDependencySpecifier(e){return/^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z-.]+)?$/.test(e)?`^${e}`:e}const BASE_AGENT_TEMPLATE=`import { defineAgent } from "eve";
2
2
 
3
3
  export default defineAgent({
4
4
  model: "__EVE_INIT_MODEL__",
@@ -1,6 +1,6 @@
1
1
  export declare const WEB_APP_TEMPLATE_FILES: {
2
2
  readonly "agent/channels/eve.ts": 'import { eveChannel } from "eve/channels/eve";\nimport { localDev, placeholderAuth, vercelOidc } from "eve/channels/auth";\n\nexport default eveChannel({\n auth: [\n // Lets the eve TUI and your Vercel deployments reach the deployed agent.\n vercelOidc(),\n // Open on localhost for `eve dev` and the REPL; ignored in production.\n localDev(),\n // This placeholder will not allow browser requests in production.\n // Replace it with your app\'s auth provider, like Auth.js or Clerk,\n // or use none() for a public demo.\n placeholderAuth(),\n ],\n});\n';
3
- readonly "app/_components/agent-chat.tsx": '"use client";\n\nimport type { UserContent } from "ai";\nimport { Client, type MessageStreamEvent } from "eve/client";\nimport { useEveAgent } from "eve/react";\nimport { AlertCircleIcon } from "lucide-react";\nimport { useCallback, useRef, useState } from "react";\nimport {\n Conversation,\n ConversationContent,\n ConversationScrollButton,\n} from "@/components/ai-elements/conversation";\nimport {\n PromptInput,\n type PromptInputMessage,\n PromptInputSubmit,\n PromptInputTextarea,\n} from "@/components/ai-elements/prompt-input";\nimport { cn } from "@/lib/utils";\nimport { AgentMessage } from "./agent-message";\n\nconst AGENT_NAME = "__EVE_INIT_APP_NAME__";\n\ntype AgentStatus = ReturnType<typeof useEveAgent>["status"];\ntype CancellationState = "idle" | "requested" | "cancelling";\n\ntype Cancellation = {\n requested: boolean;\n sentTurnId?: string;\n turnId?: string;\n};\n\nexport function AgentChat() {\n const [session] = useState(() =>\n new Client({ host: "", preserveCompletedSessions: true }).session(),\n );\n const cancellationRef = useRef<Cancellation>({ requested: false });\n const [cancellationError, setCancellationError] = useState<string>();\n const [cancellationState, setCancellationState] = useState<CancellationState>("idle");\n\n const cancelTurn = useCallback(\n (turnId: string) => {\n const cancellation = cancellationRef.current;\n if (!cancellation.requested || cancellation.sentTurnId === turnId) {\n return;\n }\n\n cancellation.sentTurnId = turnId;\n setCancellationState("cancelling");\n\n void session.cancel({ turnId }).catch((error: unknown) => {\n if (cancellationRef.current !== cancellation) {\n return;\n }\n\n cancellation.requested = false;\n cancellation.sentTurnId = undefined;\n setCancellationError(toErrorMessage(error));\n setCancellationState("idle");\n });\n },\n [session],\n );\n\n const handleEvent = useCallback(\n (event: MessageStreamEvent) => {\n if (event.type !== "turn.started") {\n return;\n }\n\n const cancellation = cancellationRef.current;\n cancellation.turnId = event.data.turnId;\n cancelTurn(event.data.turnId);\n },\n [cancelTurn],\n );\n\n const agent = useEveAgent({ onEvent: handleEvent, session });\n const isBusy = agent.status === "submitted" || agent.status === "streaming";\n const isEmpty = agent.data.messages.length === 0;\n const errorMessage = cancellationError ?? agent.error?.message;\n const submitStatus = isBusy && cancellationState !== "idle" ? "submitted" : agent.status;\n\n const prepareTurn = () => {\n cancellationRef.current = { requested: false };\n setCancellationError(undefined);\n setCancellationState("idle");\n };\n\n const requestCancellation = () => {\n if (!isBusy || cancellationState !== "idle") {\n return;\n }\n\n const cancellation = cancellationRef.current;\n cancellation.requested = true;\n setCancellationError(undefined);\n setCancellationState("requested");\n\n if (cancellation.turnId !== undefined) {\n cancelTurn(cancellation.turnId);\n }\n };\n\n const handleSubmit = async (message: PromptInputMessage) => {\n const text = message.text.trim();\n if ((text.length === 0 && message.files.length === 0) || isBusy) return;\n\n prepareTurn();\n\n if (message.files.length === 0) {\n await agent.send({ message: text });\n return;\n }\n\n const parts: UserContent = [];\n if (text.length > 0) {\n parts.push({ text, type: "text" });\n }\n for (const file of message.files) {\n parts.push({\n data: file.url,\n filename: file.filename,\n mediaType: file.mediaType,\n type: "file",\n });\n }\n\n await agent.send({ message: parts });\n };\n\n const composer = (\n <PromptInput onSubmit={handleSubmit}>\n <PromptInputTextarea placeholder="Send a message…" />\n <PromptInputSubmit onStop={requestCancellation} status={submitStatus} />\n </PromptInput>\n );\n\n return (\n <main className="flex h-dvh flex-col overflow-hidden bg-background text-foreground">\n {isEmpty ? null : (\n <header className="flex h-14 shrink-0 items-center justify-center gap-3 pl-4 pr-2">\n <span className="flex min-w-0 items-center gap-2">\n <span className="truncate text-muted-foreground text-sm">{AGENT_NAME}</span>\n <StatusDot status={agent.status} />\n </span>\n </header>\n )}\n\n {errorMessage ? (\n <div className="mx-auto w-full max-w-3xl shrink-0 px-4 pt-2 sm:px-6">\n <div className="flex items-start gap-3 rounded-lg border border-destructive/30 bg-destructive/5 px-3 py-2.5 text-sm">\n <AlertCircleIcon className="mt-0.5 size-4 shrink-0 text-destructive" />\n <div>\n <p className="font-medium">Request failed</p>\n <p className="mt-0.5 text-muted-foreground">{errorMessage}</p>\n </div>\n </div>\n </div>\n ) : null}\n\n {isEmpty ? null : (\n <Conversation className="min-h-0 flex-1">\n <ConversationContent className="mx-auto w-full max-w-3xl gap-6 px-4 py-6 sm:px-6">\n {agent.data.messages.map((message, index) => (\n <AgentMessage\n canRespond={!isBusy}\n isStreaming={\n agent.status === "streaming" && index === agent.data.messages.length - 1\n }\n key={message.id}\n message={message}\n onInputResponses={(inputResponses) => {\n prepareTurn();\n return agent.send({ inputResponses });\n }}\n />\n ))}\n </ConversationContent>\n <ConversationScrollButton />\n </Conversation>\n )}\n\n <div\n className={cn(\n "mx-auto w-full px-4 sm:px-6",\n isEmpty\n ? "flex max-w-xl flex-1 flex-col items-center justify-center gap-8 pb-[10vh]"\n : "max-w-3xl shrink-0 pb-6",\n )}\n >\n {isEmpty ? (\n <div className="flex flex-col items-center gap-3 text-center">\n <h1 className="font-medium text-5xl tracking-tighter">{AGENT_NAME}</h1>\n </div>\n ) : null}\n <div className="w-full">{composer}</div>\n </div>\n </main>\n );\n}\n\nfunction toErrorMessage(error: unknown): string {\n return error instanceof Error ? error.message : "Unable to cancel the response.";\n}\n\nfunction StatusDot({ status }: { readonly status: AgentStatus }) {\n const isLive = status === "submitted" || status === "streaming";\n const tone =\n status === "error"\n ? "bg-destructive"\n : isLive\n ? "bg-emerald-500"\n : status === "ready"\n ? "bg-muted-foreground"\n : "bg-muted-foreground/50";\n\n return (\n <span className="relative flex size-1">\n {isLive ? (\n <span\n className={cn(\n "absolute inline-flex size-full animate-ping rounded-full opacity-75",\n tone,\n )}\n />\n ) : null}\n <span className={cn("relative inline-flex size-1 rounded-full transition-colors", tone)} />\n </span>\n );\n}\n';
3
+ readonly "app/_components/agent-chat.tsx": '"use client";\n\nimport type { UserContent } from "ai";\nimport { Client, type MessageStreamEvent } from "eve/client";\nimport { useEveAgent } from "eve/react";\nimport { AlertCircleIcon } from "lucide-react";\nimport { useCallback, useRef, useState } from "react";\nimport {\n Conversation,\n ConversationContent,\n ConversationScrollButton,\n} from "@/components/ai-elements/conversation";\nimport {\n PromptInput,\n type PromptInputMessage,\n PromptInputSubmit,\n PromptInputTextarea,\n} from "@/components/ai-elements/prompt-input";\nimport { cn } from "@/lib/utils";\nimport { AgentMessage } from "./agent-message";\n\nconst AGENT_NAME = "__EVE_INIT_APP_NAME__";\n\ntype AgentStatus = ReturnType<typeof useEveAgent>["status"];\ntype CancellationState = "idle" | "requested" | "cancelling";\n\ntype Cancellation = {\n requested: boolean;\n sentTurnId?: string;\n turnId?: string;\n};\n\nexport function AgentChat() {\n const [client] = useState(() => new Client({ host: "" }));\n const sessionIdRef = useRef<string | undefined>(undefined);\n const cancellationRef = useRef<Cancellation>({ requested: false });\n const [cancellationError, setCancellationError] = useState<string>();\n const [cancellationState, setCancellationState] = useState<CancellationState>("idle");\n\n const cancelTurn = useCallback(\n (turnId: string) => {\n const cancellation = cancellationRef.current;\n if (!cancellation.requested || cancellation.sentTurnId === turnId) {\n return;\n }\n\n cancellation.sentTurnId = turnId;\n setCancellationState("cancelling");\n\n const sessionId = sessionIdRef.current;\n if (sessionId === undefined) {\n return;\n }\n\n void client.sessions\n .attach(sessionId)\n .cancel({ turnId })\n .catch((error: unknown) => {\n if (cancellationRef.current !== cancellation) {\n return;\n }\n\n cancellation.requested = false;\n cancellation.sentTurnId = undefined;\n setCancellationError(toErrorMessage(error));\n setCancellationState("idle");\n });\n },\n [client],\n );\n\n const handleEvent = useCallback(\n (event: MessageStreamEvent) => {\n if (event.type !== "turn.started") {\n return;\n }\n\n const cancellation = cancellationRef.current;\n cancellation.turnId = event.data.turnId;\n cancelTurn(event.data.turnId);\n },\n [cancelTurn],\n );\n\n const agent = useEveAgent({\n onEvent: handleEvent,\n onSessionChange(session) {\n sessionIdRef.current = session?.sessionId;\n },\n });\n const isBusy = agent.status === "submitted" || agent.status === "streaming";\n const isEmpty = agent.data.messages.length === 0;\n const errorMessage = cancellationError ?? agent.error?.message;\n const submitStatus = isBusy && cancellationState !== "idle" ? "submitted" : agent.status;\n\n const prepareTurn = () => {\n cancellationRef.current = { requested: false };\n setCancellationError(undefined);\n setCancellationState("idle");\n };\n\n const requestCancellation = () => {\n if (!isBusy || cancellationState !== "idle") {\n return;\n }\n\n const cancellation = cancellationRef.current;\n cancellation.requested = true;\n setCancellationError(undefined);\n setCancellationState("requested");\n\n if (cancellation.turnId !== undefined) {\n cancelTurn(cancellation.turnId);\n }\n };\n\n const handleSubmit = async (message: PromptInputMessage) => {\n const text = message.text.trim();\n if ((text.length === 0 && message.files.length === 0) || isBusy) return;\n\n prepareTurn();\n\n if (message.files.length === 0) {\n await agent.send(text);\n return;\n }\n\n const parts: UserContent = [];\n if (text.length > 0) {\n parts.push({ text, type: "text" });\n }\n for (const file of message.files) {\n parts.push({\n data: file.url,\n filename: file.filename,\n mediaType: file.mediaType,\n type: "file",\n });\n }\n\n await agent.send(parts);\n };\n\n const composer = (\n <PromptInput onSubmit={handleSubmit}>\n <PromptInputTextarea placeholder="Send a message…" />\n <PromptInputSubmit onStop={requestCancellation} status={submitStatus} />\n </PromptInput>\n );\n\n return (\n <main className="flex h-dvh flex-col overflow-hidden bg-background text-foreground">\n {isEmpty ? null : (\n <header className="flex h-14 shrink-0 items-center justify-center gap-3 pl-4 pr-2">\n <span className="flex min-w-0 items-center gap-2">\n <span className="truncate text-muted-foreground text-sm">{AGENT_NAME}</span>\n <StatusDot status={agent.status} />\n </span>\n </header>\n )}\n\n {errorMessage ? (\n <div className="mx-auto w-full max-w-3xl shrink-0 px-4 pt-2 sm:px-6">\n <div className="flex items-start gap-3 rounded-lg border border-destructive/30 bg-destructive/5 px-3 py-2.5 text-sm">\n <AlertCircleIcon className="mt-0.5 size-4 shrink-0 text-destructive" />\n <div>\n <p className="font-medium">Request failed</p>\n <p className="mt-0.5 text-muted-foreground">{errorMessage}</p>\n </div>\n </div>\n </div>\n ) : null}\n\n {isEmpty ? null : (\n <Conversation className="min-h-0 flex-1">\n <ConversationContent className="mx-auto w-full max-w-3xl gap-6 px-4 py-6 sm:px-6">\n {agent.data.messages.map((message, index) => (\n <AgentMessage\n canRespond={!isBusy}\n isStreaming={\n agent.status === "streaming" && index === agent.data.messages.length - 1\n }\n key={message.id}\n message={message}\n onInputResponses={(inputResponses) => {\n prepareTurn();\n return agent.respond(inputResponses);\n }}\n />\n ))}\n </ConversationContent>\n <ConversationScrollButton />\n </Conversation>\n )}\n\n <div\n className={cn(\n "mx-auto w-full px-4 sm:px-6",\n isEmpty\n ? "flex max-w-xl flex-1 flex-col items-center justify-center gap-8 pb-[10vh]"\n : "max-w-3xl shrink-0 pb-6",\n )}\n >\n {isEmpty ? (\n <div className="flex flex-col items-center gap-3 text-center">\n <h1 className="font-medium text-5xl tracking-tighter">{AGENT_NAME}</h1>\n </div>\n ) : null}\n <div className="w-full">{composer}</div>\n </div>\n </main>\n );\n}\n\nfunction toErrorMessage(error: unknown): string {\n return error instanceof Error ? error.message : "Unable to cancel the response.";\n}\n\nfunction StatusDot({ status }: { readonly status: AgentStatus }) {\n const isLive = status === "submitted" || status === "streaming";\n const tone =\n status === "error"\n ? "bg-destructive"\n : isLive\n ? "bg-emerald-500"\n : status === "ready"\n ? "bg-muted-foreground"\n : "bg-muted-foreground/50";\n\n return (\n <span className="relative flex size-1">\n {isLive ? (\n <span\n className={cn(\n "absolute inline-flex size-full animate-ping rounded-full opacity-75",\n tone,\n )}\n />\n ) : null}\n <span className={cn("relative inline-flex size-1 rounded-full transition-colors", tone)} />\n </span>\n );\n}\n';
4
4
  readonly "app/_components/agent-message.tsx": '"use client";\n\nimport type {\n EveAuthorizationPart,\n EveDynamicToolPart,\n EveMessage,\n EveMessagePart,\n} from "eve/react";\nimport {\n CheckCircleIcon,\n ExternalLinkIcon,\n FileIcon,\n ImageIcon,\n KeyRoundIcon,\n XCircleIcon,\n} from "lucide-react";\nimport { Message, MessageContent, MessageResponse } from "@/components/ai-elements/message";\nimport { Reasoning, ReasoningContent, ReasoningTrigger } from "@/components/ai-elements/reasoning";\nimport {\n Tool,\n ToolContent,\n ToolHeader,\n ToolInput,\n ToolOutput,\n} from "@/components/ai-elements/tool";\nimport { Button } from "@/components/ui/button";\nimport { cn } from "@/lib/utils";\n\nexport type AgentInputResponse = {\n readonly optionId?: string;\n readonly requestId: string;\n readonly text?: string;\n};\n\ntype EveFilePart = Extract<EveMessagePart, { type: "file" }>;\n\nexport function AgentMessage({\n canRespond,\n isStreaming,\n message,\n onInputResponses,\n}: {\n readonly canRespond: boolean;\n readonly isStreaming: boolean;\n readonly message: EveMessage;\n readonly onInputResponses: (responses: readonly AgentInputResponse[]) => void | Promise<void>;\n}) {\n const lastTextIndex = message.parts.reduce(\n (last, part, index) => (part.type === "text" ? index : last),\n -1,\n );\n\n return (\n <Message\n data-optimistic={message.metadata?.optimistic ? "true" : undefined}\n from={message.role}\n >\n <MessageContent>\n {message.parts.map((part, index) => (\n <AgentMessagePart\n canRespond={canRespond}\n key={partKey(part, index)}\n onInputResponses={onInputResponses}\n part={part}\n showCaret={isStreaming && message.role === "assistant" && index === lastTextIndex}\n />\n ))}\n </MessageContent>\n </Message>\n );\n}\n\nfunction AgentMessagePart({\n canRespond,\n onInputResponses,\n part,\n showCaret,\n}: {\n readonly canRespond: boolean;\n readonly onInputResponses: (responses: readonly AgentInputResponse[]) => void | Promise<void>;\n readonly part: EveMessagePart;\n readonly showCaret: boolean;\n}) {\n switch (part.type) {\n case "step-start":\n return null;\n case "text":\n return (\n <MessageResponse caret="block" isAnimating={showCaret}>\n {part.text}\n </MessageResponse>\n );\n case "reasoning":\n return (\n <Reasoning defaultOpen isStreaming={part.state === "streaming"}>\n <ReasoningTrigger />\n <ReasoningContent>{part.text}</ReasoningContent>\n </Reasoning>\n );\n case "file":\n return <AttachmentPart part={part} />;\n case "authorization":\n return <AuthorizationPrompt part={part} />;\n case "dynamic-tool":\n return (\n <Tool\n defaultOpen={part.state === "approval-requested" || part.state === "approval-responded"}\n >\n <ToolHeader\n state={part.state}\n title={part.toolName}\n toolName={part.toolName}\n type="dynamic-tool"\n />\n <ToolContent>\n <ToolInput input={part.input} />\n <InputRequestActions\n canRespond={canRespond}\n part={part}\n onInputResponses={onInputResponses}\n />\n <ToolOutput errorText={part.errorText} output={part.output} />\n </ToolContent>\n </Tool>\n );\n }\n}\n\nfunction AttachmentPart({ part }: { readonly part: EveFilePart }) {\n const label = part.filename ?? "Attachment";\n const detail = [part.mediaType, formatBytes(part.size)].filter(Boolean).join(" - ");\n const isImage = part.mediaType.startsWith("image/") && part.url !== undefined;\n const Icon = isImage ? ImageIcon : FileIcon;\n const body = (\n <span className="flex max-w-sm items-center gap-3 rounded-md border bg-background/60 p-2 text-sm">\n {isImage ? (\n <img alt={label} className="size-12 shrink-0 rounded-sm object-cover" src={part.url} />\n ) : (\n <span className="flex size-10 shrink-0 items-center justify-center rounded-sm bg-muted text-muted-foreground">\n <Icon className="size-4" />\n </span>\n )}\n <span className="min-w-0 flex-1">\n <span className="block truncate font-medium">{label}</span>\n {detail ? <span className="block truncate text-muted-foreground">{detail}</span> : null}\n </span>\n {part.url ? <ExternalLinkIcon className="size-4 shrink-0 text-muted-foreground" /> : null}\n </span>\n );\n\n return part.url ? (\n <a href={part.url} rel="noreferrer" target="_blank">\n {body}\n </a>\n ) : (\n body\n );\n}\n\nfunction AuthorizationPrompt({ part }: { readonly part: EveAuthorizationPart }) {\n const isAuthorized = part.state === "completed" && part.outcome === "authorized";\n const isCompleted = part.state === "completed";\n const Icon = isAuthorized ? CheckCircleIcon : isCompleted ? XCircleIcon : KeyRoundIcon;\n const instructions = part.authorization?.instructions;\n const shouldShowInstructions = instructions !== undefined && instructions !== part.description;\n\n return (\n <div\n className={cn(\n "space-y-3 rounded-md border p-3",\n isAuthorized\n ? "border-emerald-500/30 bg-emerald-500/5"\n : isCompleted\n ? "border-destructive/30 bg-destructive/5"\n : "border-blue-500/30 bg-blue-500/5",\n )}\n >\n <div className="flex items-start gap-3">\n <span\n className={cn(\n "mt-0.5 flex size-8 shrink-0 items-center justify-center rounded-full",\n isAuthorized\n ? "bg-emerald-500/10 text-emerald-700 dark:text-emerald-300"\n : isCompleted\n ? "bg-destructive/10 text-destructive"\n : "bg-blue-500/10 text-blue-700 dark:text-blue-300",\n )}\n >\n <Icon className="size-4" />\n </span>\n <div className="min-w-0 flex-1 space-y-2">\n <p className="font-medium text-sm">{authorizationTitle(part)}</p>\n <p className="text-muted-foreground text-sm">{authorizationDescription(part)}</p>\n {shouldShowInstructions ? (\n <p className="text-muted-foreground text-sm">{instructions}</p>\n ) : null}\n {part.state === "required" && part.authorization?.userCode ? (\n <div className="flex flex-wrap items-center gap-2 text-sm">\n <span className="text-muted-foreground">Code</span>\n <code className="rounded-md bg-background px-2 py-1 font-mono">\n {part.authorization.userCode}\n </code>\n </div>\n ) : null}\n {part.state === "required" && part.authorization?.url ? (\n <Button asChild size="sm">\n <a href={part.authorization.url} rel="noreferrer" target="_blank">\n <ExternalLinkIcon className="size-4" />\n Sign in with {part.displayName}\n </a>\n </Button>\n ) : null}\n </div>\n </div>\n </div>\n );\n}\n\nfunction authorizationTitle(part: EveAuthorizationPart): string {\n if (part.state === "required") {\n return `Connect ${part.displayName}`;\n }\n if (part.outcome === "authorized") {\n return `${part.displayName} connected`;\n }\n return `${part.displayName} authorization ${formatAuthorizationOutcome(part.outcome)}`;\n}\n\nfunction authorizationDescription(part: EveAuthorizationPart): string {\n if (part.state === "required") {\n return part.description;\n }\n if (part.outcome === "authorized") {\n return `${part.displayName} connected.`;\n }\n const tail = part.reason !== undefined ? ` (${part.reason})` : "";\n return `${part.displayName} authorization ${formatAuthorizationOutcome(part.outcome)}${tail}.`;\n}\n\nfunction formatAuthorizationOutcome(outcome: NonNullable<EveAuthorizationPart["outcome"]>): string {\n switch (outcome) {\n case "authorized":\n return "authorized";\n case "declined":\n return "declined";\n case "failed":\n return "failed";\n case "timed-out":\n return "timed out";\n }\n}\n\nfunction formatBytes(size: number | undefined): string | undefined {\n if (size === undefined) {\n return undefined;\n }\n if (size < 1024) {\n return `${size} B`;\n }\n if (size < 1024 * 1024) {\n return `${(size / 1024).toFixed(1)} KB`;\n }\n return `${(size / (1024 * 1024)).toFixed(1)} MB`;\n}\n\nfunction InputRequestActions({\n canRespond,\n onInputResponses,\n part,\n}: {\n readonly canRespond: boolean;\n readonly onInputResponses: (responses: readonly AgentInputResponse[]) => void | Promise<void>;\n readonly part: EveDynamicToolPart;\n}) {\n const inputRequest = part.toolMetadata?.eve?.inputRequest;\n if (!inputRequest) {\n return null;\n }\n\n const inputResponse = part.toolMetadata?.eve?.inputResponse;\n const selectedOption = inputRequest.options?.find(\n (option) => option.id === inputResponse?.optionId,\n );\n\n return (\n <div className="space-y-3 rounded-md border border-yellow-500/30 bg-yellow-500/5 p-3">\n <p className="text-muted-foreground text-sm">{inputRequest.prompt}</p>\n {inputResponse ? (\n <p className="font-medium text-sm">\n Responded: {selectedOption?.label ?? inputResponse.text ?? inputResponse.optionId}\n </p>\n ) : (\n <div className="flex flex-wrap gap-2">\n {inputRequest.options?.map((option) => (\n <Button\n disabled={!canRespond}\n key={option.id}\n onClick={() => {\n void onInputResponses([\n {\n optionId: option.id,\n requestId: inputRequest.requestId,\n },\n ]);\n }}\n size="sm"\n type="button"\n variant={option.style === "danger" ? "destructive" : "default"}\n >\n {option.label}\n </Button>\n ))}\n </div>\n )}\n </div>\n );\n}\n\nfunction partKey(part: EveMessagePart, index: number): string {\n switch (part.type) {\n case "authorization":\n return `authorization:${part.turnId}:${part.stepIndex}:${part.name}`;\n case "dynamic-tool":\n return part.toolCallId;\n default:\n return `${part.type}:${index}`;\n }\n}\n';
5
5
  readonly "app/globals.css": '@import "tailwindcss";\n@source "../node_modules/streamdown/dist/*.js";\n\n@theme inline {\n --color-background: var(--background);\n --color-foreground: var(--foreground);\n --color-card: var(--card);\n --color-card-foreground: var(--card-foreground);\n --color-popover: var(--popover);\n --color-popover-foreground: var(--popover-foreground);\n --color-primary: var(--primary);\n --color-primary-foreground: var(--primary-foreground);\n --color-secondary: var(--secondary);\n --color-secondary-foreground: var(--secondary-foreground);\n --color-muted: var(--muted);\n --color-muted-foreground: var(--muted-foreground);\n --color-accent: var(--accent);\n --color-accent-foreground: var(--accent-foreground);\n --color-destructive: var(--destructive);\n --color-border: var(--border);\n --color-input: var(--input);\n --color-ring: var(--ring);\n --radius-sm: calc(var(--radius) - 4px);\n --radius-md: calc(var(--radius) - 2px);\n --radius-lg: var(--radius);\n --radius-xl: calc(var(--radius) + 4px);\n --font-sans: "Geist", "Geist Fallback", ui-sans-serif, system-ui, sans-serif;\n --font-mono: "Geist Mono", "Geist Mono Fallback", ui-monospace, monospace;\n}\n\n:root {\n color-scheme: light;\n /* Soft neutral page with white elevated surfaces so cards/composer pop. */\n --background: oklch(0.971 0 0);\n --foreground: oklch(0.16 0 0);\n --card: oklch(1 0 0);\n --card-foreground: oklch(0.16 0 0);\n --popover: oklch(1 0 0);\n --popover-foreground: oklch(0.16 0 0);\n --primary: oklch(0.19 0 0);\n --primary-foreground: oklch(0.985 0 0);\n --secondary: oklch(0.94 0 0);\n --secondary-foreground: oklch(0.19 0 0);\n --muted: oklch(0.94 0 0);\n --muted-foreground: oklch(0.6 0 0);\n --accent: oklch(0.94 0 0);\n --accent-foreground: oklch(0.19 0 0);\n --destructive: oklch(0.577 0.245 27.325);\n --border: oklch(0.916 0 0);\n --input: oklch(0.916 0 0);\n --ring: oklch(0.708 0 0);\n --radius: 0.625rem;\n}\n\n@media (prefers-color-scheme: dark) {\n :root {\n color-scheme: dark;\n --background: oklch(0.145 0 0);\n --foreground: oklch(0.985 0 0);\n --card: oklch(0.205 0 0);\n --card-foreground: oklch(0.985 0 0);\n --popover: oklch(0.205 0 0);\n --popover-foreground: oklch(0.985 0 0);\n --primary: oklch(0.922 0 0);\n --primary-foreground: oklch(0.205 0 0);\n --secondary: oklch(0.269 0 0);\n --secondary-foreground: oklch(0.985 0 0);\n --muted: oklch(0.269 0 0);\n --muted-foreground: oklch(0.708 0 0);\n --accent: oklch(0.269 0 0);\n --accent-foreground: oklch(0.985 0 0);\n --destructive: oklch(0.704 0.191 22.216);\n --border: oklch(1 0 0 / 10%);\n --input: oklch(1 0 0 / 15%);\n --ring: oklch(0.556 0 0);\n }\n}\n\n* {\n border-color: var(--border);\n}\n\nhtml {\n height: 100%;\n}\n\nbody {\n min-height: 100%;\n margin: 0;\n background: var(--background);\n font-family: var(--font-sans);\n}\n\nbutton,\ninput,\ntextarea {\n font: inherit;\n}\n';
6
6
  readonly "app/layout.tsx": 'import type { Metadata } from "next";\nimport { Geist, Geist_Mono } from "next/font/google";\nimport type { ReactNode } from "react";\nimport { TooltipProvider } from "@/components/ui/tooltip";\nimport { cn } from "@/lib/utils";\nimport "./globals.css";\n\nconst sans = Geist({\n variable: "--font-sans",\n subsets: ["latin"],\n weight: "variable",\n display: "swap",\n});\n\nconst mono = Geist_Mono({\n variable: "--font-mono",\n subsets: ["latin"],\n weight: "variable",\n display: "swap",\n});\n\nexport const metadata: Metadata = {\n title: "__EVE_INIT_APP_NAME__",\n description: "A Next.js starter for eve agents with AI Elements.",\n};\n\nexport default function RootLayout({ children }: { readonly children: ReactNode }) {\n return (\n <html className={cn(sans.variable, mono.variable)} lang="en">\n <body>\n <TooltipProvider>{children}</TooltipProvider>\n </body>\n </html>\n );\n}\n';