eve 0.81.1 → 0.82.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 (285) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/dist/src/channel/channel-address.d.ts +21 -2
  3. package/dist/src/channel/channel-address.js +1 -1
  4. package/dist/src/channel/channel-operations.d.ts +32 -1
  5. package/dist/src/channel/channel-operations.js +1 -1
  6. package/dist/src/channel/delivery-idempotency.d.ts +4 -0
  7. package/dist/src/channel/delivery-idempotency.js +1 -0
  8. package/dist/src/channel/routes.d.ts +6 -0
  9. package/dist/src/channel/session.d.ts +5 -0
  10. package/dist/src/channel/session.js +1 -1
  11. package/dist/src/channel/types.d.ts +14 -11
  12. package/dist/src/chunks/{use-eve-agent-Bp6nbhfV.js → use-eve-agent-DTu78IAF.js} +36 -0
  13. package/dist/src/chunks/{use-eve-agent-DLkjJIm3.js → use-eve-agent-DlznYwQk.js} +36 -0
  14. package/dist/src/cli/dev/command-options.d.ts +1 -0
  15. package/dist/src/cli/dev/diagnostic-dump.js +1 -1
  16. package/dist/src/cli/run.d.ts +1 -0
  17. package/dist/src/cli/run.js +1 -1
  18. package/dist/src/client/index.d.ts +1 -1
  19. package/dist/src/client/message-reducer-types.d.ts +7 -3
  20. package/dist/src/client/message-reducer.js +1 -1
  21. package/dist/src/client/transcript-reducer.d.ts +6 -3
  22. package/dist/src/client/transcript-reducer.js +1 -1
  23. package/dist/src/compiled/.vendor-stamp.json +1 -1
  24. package/dist/src/compiler/extension-compatibility.d.ts +19 -18
  25. package/dist/src/compiler/extension-compatibility.js +1 -1
  26. package/dist/src/compiler/load-binding-namespace.d.ts +2 -0
  27. package/dist/src/compiler/load-binding-namespace.js +1 -1
  28. package/dist/src/compiler/manifest.js +1 -1
  29. package/dist/src/compiler/module-lifecycle.d.ts +1 -1
  30. package/dist/src/compiler/module-lifecycle.js +1 -1
  31. package/dist/src/compiler/module-map.js +1 -1
  32. package/dist/src/compiler/normalize-agent-config.js +1 -1
  33. package/dist/src/compiler/normalize-manifest.js +1 -1
  34. package/dist/src/compiler/project-sources.d.ts +6 -0
  35. package/dist/src/compiler/project-sources.js +1 -1
  36. package/dist/src/context/keys.d.ts +2 -0
  37. package/dist/src/context/keys.js +1 -1
  38. package/dist/src/evals/cli/eval-state-directory.d.ts +7 -0
  39. package/dist/src/evals/cli/eval-state-directory.js +1 -0
  40. package/dist/src/evals/cli/eval.js +2 -2
  41. package/dist/src/eve-channel/index.js +1 -1
  42. package/dist/src/eve-channel/support.d.ts +2 -0
  43. package/dist/src/eve-channel/support.js +1 -1
  44. package/dist/src/eve-channel/types.d.ts +7 -0
  45. package/dist/src/execution/agent-sessions/context.d.ts +2 -13
  46. package/dist/src/execution/agent-sessions/context.js +1 -1
  47. package/dist/src/execution/agent-sessions/runtime-overrides.d.ts +5 -0
  48. package/dist/src/execution/agent-sessions/runtime-overrides.js +1 -0
  49. package/dist/src/execution/agent-sessions/session.d.ts +2 -2
  50. package/dist/src/execution/agent-sessions/session.js +1 -1
  51. package/dist/src/execution/agent-sessions/steps.d.ts +2 -0
  52. package/dist/src/execution/agent-sessions/steps.js +1 -1
  53. package/dist/src/execution/coordination-dispatch-shared.d.ts +5 -5
  54. package/dist/src/execution/coordination-dispatch-step.d.ts +17 -2
  55. package/dist/src/execution/coordination-dispatch-step.js +1 -1
  56. package/dist/src/execution/create-session-step.d.ts +5 -2
  57. package/dist/src/execution/create-session-step.js +1 -1
  58. package/dist/src/execution/deliver-payloads.js +1 -1
  59. package/dist/src/execution/durable-session-store.d.ts +0 -1
  60. package/dist/src/execution/dynamic-connection-recovery.js +1 -1
  61. package/dist/src/execution/dynamic-workflow/tool.js +1 -1
  62. package/dist/src/execution/effective-agent-config.d.ts +8 -2
  63. package/dist/src/execution/effective-agent-config.js +1 -1
  64. package/dist/src/execution/install-workflow-deployment-id.d.ts +3 -0
  65. package/dist/src/execution/install-workflow-deployment-id.js +1 -0
  66. package/dist/src/execution/legacy-session/turn-workflow.js +1 -1
  67. package/dist/src/execution/node-step.d.ts +1 -0
  68. package/dist/src/execution/node-step.js +1 -1
  69. package/dist/src/execution/runtime-context.d.ts +2 -0
  70. package/dist/src/execution/runtime-context.js +1 -1
  71. package/dist/src/execution/session/active-turn.js +1 -1
  72. package/dist/src/execution/session/admission.js +1 -1
  73. package/dist/src/execution/session/checkpoint-migrations.js +1 -1
  74. package/dist/src/execution/session/entry-input.d.ts +1 -3
  75. package/dist/src/execution/session/entry.js +1 -1
  76. package/dist/src/execution/session/finalization.js +1 -1
  77. package/dist/src/execution/session/handoff.d.ts +6 -9
  78. package/dist/src/execution/session/handoff.js +1 -1
  79. package/dist/src/execution/session/input-queue.d.ts +5 -1
  80. package/dist/src/execution/session/input-queue.js +1 -1
  81. package/dist/src/execution/session/pending-history.d.ts +5 -0
  82. package/dist/src/execution/session/pending-history.js +1 -0
  83. package/dist/src/execution/session/pending-turn-state.js +1 -1
  84. package/dist/src/execution/session/program.d.ts +1 -1
  85. package/dist/src/execution/session/program.js +1 -1
  86. package/dist/src/execution/session/timeout-control.d.ts +18 -4
  87. package/dist/src/execution/session/timeout-control.js +1 -1
  88. package/dist/src/execution/session/timeout.d.ts +1 -2
  89. package/dist/src/execution/session/timeout.js +1 -1
  90. package/dist/src/execution/session/turn-event-handler.js +1 -1
  91. package/dist/src/execution/session/turn-step-result.js +1 -1
  92. package/dist/src/execution/session/turn-step.js +1 -1
  93. package/dist/src/execution/session/turn-waiting-step.js +1 -1
  94. package/dist/src/execution/session/turn.js +1 -1
  95. package/dist/src/execution/session-inbox/protocol.js +1 -1
  96. package/dist/src/execution/session.d.ts +0 -12
  97. package/dist/src/execution/session.js +2 -2
  98. package/dist/src/execution/settle-cancelled-turn-step.js +1 -1
  99. package/dist/src/execution/tasks/model-step.js +1 -1
  100. package/dist/src/execution/tasks/start.d.ts +4 -4
  101. package/dist/src/execution/tasks/start.js +1 -1
  102. package/dist/src/execution/tasks/steps.js +1 -1
  103. package/dist/src/execution/terminate-child-sessions-step.js +1 -1
  104. package/dist/src/execution/tools/agent-router-workflow.js +1 -1
  105. package/dist/src/execution/tools/workflow/body.d.ts +2 -2
  106. package/dist/src/execution/workflow-runtime.d.ts +5 -1
  107. package/dist/src/execution/workflow-runtime.js +1 -1
  108. package/dist/src/harness/hitl/approvals.js +1 -1
  109. package/dist/src/harness/hitl/budget-request.d.ts +12 -6
  110. package/dist/src/harness/hitl/budget-request.js +1 -1
  111. package/dist/src/harness/hitl/budget.d.ts +7 -1
  112. package/dist/src/harness/hitl/budget.js +1 -1
  113. package/dist/src/harness/hitl/coordinator.js +1 -1
  114. package/dist/src/harness/hitl/delivery.d.ts +1 -1
  115. package/dist/src/harness/hitl/delivery.js +1 -1
  116. package/dist/src/harness/hitl/index.js +1 -1
  117. package/dist/src/harness/hitl/intake.d.ts +2 -2
  118. package/dist/src/harness/hitl/intake.js +1 -1
  119. package/dist/src/harness/messages.d.ts +5 -0
  120. package/dist/src/harness/messages.js +1 -1
  121. package/dist/src/harness/model-call/call.d.ts +2 -2
  122. package/dist/src/harness/model-call/request.d.ts +2 -2
  123. package/dist/src/harness/session-machine/transitions.d.ts +3 -1
  124. package/dist/src/harness/session-machine/transitions.js +1 -1
  125. package/dist/src/harness/step/context.d.ts +3 -0
  126. package/dist/src/harness/step/context.js +1 -1
  127. package/dist/src/harness/step/intake.d.ts +5 -2
  128. package/dist/src/harness/step/intake.js +1 -1
  129. package/dist/src/harness/tool-loop.js +1 -1
  130. package/dist/src/harness/turn-tag-state.d.ts +7 -26
  131. package/dist/src/harness/turn-tag-state.js +1 -1
  132. package/dist/src/harness/types.d.ts +10 -25
  133. package/dist/src/internal/application/build-profile.d.ts +3 -0
  134. package/dist/src/internal/application/build-profile.js +1 -1
  135. package/dist/src/internal/application/compiled-artifacts.js +2 -2
  136. package/dist/src/internal/application/dev-environment.d.ts +13 -0
  137. package/dist/src/internal/application/dev-environment.js +1 -1
  138. package/dist/src/internal/application/stamped-package-version.js +1 -1
  139. package/dist/src/internal/authored-definition/core.js +1 -1
  140. package/dist/src/internal/authored-module-build-options.d.ts +7 -0
  141. package/dist/src/internal/authored-module-build-options.js +1 -0
  142. package/dist/src/internal/authored-module-graph.d.ts +13 -0
  143. package/dist/src/internal/authored-module-graph.js +1 -0
  144. package/dist/src/internal/authored-module-loader.d.ts +22 -1
  145. package/dist/src/internal/authored-module-loader.js +1 -3
  146. package/dist/src/internal/authored-module.d.ts +7 -0
  147. package/dist/src/internal/authored-module.js +1 -1
  148. package/dist/src/internal/authored-package-boundary.js +1 -1
  149. package/dist/src/internal/bundler/nitro-rolldown.d.ts +5 -1
  150. package/dist/src/internal/bundler/nitro-rolldown.js +1 -1
  151. package/dist/src/internal/development-programmatic-source-loader.d.ts +1 -0
  152. package/dist/src/internal/development-programmatic-source-loader.js +1 -1
  153. package/dist/src/internal/nitro/dev-runtime-artifacts.js +1 -1
  154. package/dist/src/internal/nitro/dev-runtime-generation-metadata.js +1 -1
  155. package/dist/src/internal/nitro/host/build-application.js +1 -1
  156. package/dist/src/internal/nitro/host/build-deployment-id.d.ts +8 -0
  157. package/dist/src/internal/nitro/host/build-deployment-id.js +1 -0
  158. package/dist/src/internal/nitro/host/create-application-nitro.js +1 -1
  159. package/dist/src/internal/nitro/host/dev-server-state.js +1 -1
  160. package/dist/src/internal/nitro/host/skill-server-assets.js +1 -1
  161. package/dist/src/internal/nitro/host/stage-build-deployment-id.d.ts +2 -0
  162. package/dist/src/internal/nitro/host/stage-build-deployment-id.js +1 -0
  163. package/dist/src/internal/nitro/host/start-production-server.d.ts +1 -0
  164. package/dist/src/internal/nitro/host/start-production-server.js +3 -3
  165. package/dist/src/internal/nitro/routes/schedule-task.d.ts +3 -0
  166. package/dist/src/internal/nitro/routes/schedule-task.js +1 -1
  167. package/dist/src/internal/programmatic-source-loader.d.ts +1 -0
  168. package/dist/src/internal/programmatic-source-loader.js +1 -1
  169. package/dist/src/internal/schedules/disabled.d.ts +2 -0
  170. package/dist/src/internal/schedules/disabled.js +1 -0
  171. package/dist/src/internal/workflow/development-world-server.js +1 -1
  172. package/dist/src/internal/workflow/local-world-data-directory.d.ts +2 -1
  173. package/dist/src/internal/workflow/local-world-data-directory.js +1 -1
  174. package/dist/src/internal/workflow-bundle/builder.js +1 -1
  175. package/dist/src/protocol/message.d.ts +27 -1
  176. package/dist/src/protocol/message.js +2 -2
  177. package/dist/src/public/channels/chat-sdk/chatSdkChannel.d.ts +13 -0
  178. package/dist/src/public/channels/chat-sdk/chatSdkChannel.js +2 -2
  179. package/dist/src/public/channels/chat-sdk/fetch-message.d.ts +10 -0
  180. package/dist/src/public/channels/chat-sdk/fetch-message.js +1 -0
  181. package/dist/src/public/channels/chat-sdk/index.d.ts +1 -1
  182. package/dist/src/public/channels/chat-sdk/reply-context.d.ts +15 -0
  183. package/dist/src/public/channels/chat-sdk/reply-context.js +2 -0
  184. package/dist/src/public/channels/discord/discordChannel.d.ts +3 -0
  185. package/dist/src/public/channels/discord/discordChannel.js +1 -1
  186. package/dist/src/public/channels/github/dispatch.js +1 -1
  187. package/dist/src/public/channels/github/githubChannel.d.ts +3 -0
  188. package/dist/src/public/channels/imessage-tapbacks.d.ts +74 -0
  189. package/dist/src/public/channels/imessage-tapbacks.js +1 -0
  190. package/dist/src/public/channels/index.d.ts +2 -1
  191. package/dist/src/public/channels/index.js +1 -1
  192. package/dist/src/public/channels/linear/linearChannel.d.ts +3 -0
  193. package/dist/src/public/channels/linear/linearChannel.js +1 -1
  194. package/dist/src/public/channels/linq/inboundContent.d.ts +7 -0
  195. package/dist/src/public/channels/linq/inboundContent.js +1 -1
  196. package/dist/src/public/channels/linq/index.d.ts +1 -0
  197. package/dist/src/public/channels/linq/index.js +1 -1
  198. package/dist/src/public/channels/linq/linqChannel.d.ts +17 -1
  199. package/dist/src/public/channels/linq/linqChannel.js +1 -1
  200. package/dist/src/public/channels/photon/inboundContent.d.ts +7 -0
  201. package/dist/src/public/channels/photon/inboundContent.js +2 -1
  202. package/dist/src/public/channels/photon/index.d.ts +1 -0
  203. package/dist/src/public/channels/photon/index.js +1 -1
  204. package/dist/src/public/channels/photon/photonIMessageChannel.d.ts +17 -1
  205. package/dist/src/public/channels/photon/photonIMessageChannel.js +1 -1
  206. package/dist/src/public/channels/slack/api.d.ts +6 -0
  207. package/dist/src/public/channels/slack/api.js +1 -1
  208. package/dist/src/public/channels/slack/model-context.d.ts +7 -0
  209. package/dist/src/public/channels/slack/model-context.js +1 -1
  210. package/dist/src/public/channels/slack/reply-delivery.d.ts +5 -0
  211. package/dist/src/public/channels/slack/reply-delivery.js +1 -1
  212. package/dist/src/public/channels/slack/slackChannel.d.ts +17 -3
  213. package/dist/src/public/channels/slack/slackChannel.js +1 -1
  214. package/dist/src/public/channels/teams/teamsChannel.d.ts +3 -0
  215. package/dist/src/public/channels/teams/teamsChannel.js +1 -1
  216. package/dist/src/public/channels/telegram/telegramChannel.d.ts +3 -0
  217. package/dist/src/public/channels/telegram/telegramChannel.js +1 -1
  218. package/dist/src/public/definitions/agent.d.ts +1 -1
  219. package/dist/src/public/definitions/channel.d.ts +2 -2
  220. package/dist/src/public/definitions/channel.js +1 -1
  221. package/dist/src/public/definitions/hook.d.ts +1 -0
  222. package/dist/src/public/index.d.ts +1 -1
  223. package/dist/src/public/tools/index.d.ts +1 -1
  224. package/dist/src/runtime/agent/resolve-model.d.ts +4 -0
  225. package/dist/src/runtime/agent/resolve-model.js +1 -1
  226. package/dist/src/runtime/resolve-agent.js +1 -1
  227. package/dist/src/runtime/sessions/compiled-agent-cache.js +1 -1
  228. package/dist/src/runtime/subagents/dynamic-agent-config.d.ts +2 -1
  229. package/dist/src/runtime/subagents/dynamic-agent-config.js +1 -1
  230. package/dist/src/runtime/types.d.ts +3 -2
  231. package/dist/src/setup/scaffold/create/project.js +1 -1
  232. package/dist/src/shared/agent-definition.d.ts +31 -42
  233. package/dist/src/shared/session-history.d.ts +22 -0
  234. package/dist/src/shared/session-history.js +1 -0
  235. package/dist/src/subagents/tool.d.ts +1 -3
  236. package/dist/src/subagents/tool.js +1 -1
  237. package/dist/src/svelte/index.js +1 -1
  238. package/dist/src/svelte/use-eve-agent.js +1 -1
  239. package/dist/src/tools/provided/ask-question-workflow.js +1 -1
  240. package/dist/src/tools/provided/sleep-workflow.js +1 -1
  241. package/dist/src/tools/workflow-definition.d.ts +14 -1
  242. package/dist/src/tracing/eve/conversation-context.d.ts +4 -1
  243. package/dist/src/tracing/eve/conversation-context.js +1 -1
  244. package/dist/src/tracing/eve/invoke-tool-span.js +1 -1
  245. package/dist/src/tracing/eve/operation-input.d.ts +0 -5
  246. package/dist/src/tracing/eve/operation-input.js +1 -1
  247. package/dist/src/tracing/eve/otel-registration.js +1 -1
  248. package/dist/src/tracing/eve/session.d.ts +3 -2
  249. package/dist/src/tracing/eve/session.js +1 -1
  250. package/dist/src/vue/index.js +1 -1
  251. package/dist/src/vue/use-eve-agent.js +1 -1
  252. package/docs/agent-config.md +86 -65
  253. package/docs/channels/chat-sdk.mdx +6 -1
  254. package/docs/channels/custom.mdx +38 -6
  255. package/docs/channels/eve.mdx +46 -0
  256. package/docs/channels/linq.mdx +51 -0
  257. package/docs/channels/photon.mdx +64 -0
  258. package/docs/channels/slack.mdx +4 -2
  259. package/docs/concepts/built-in-tools.md +1 -1
  260. package/docs/concepts/execution-model-and-durability.mdx +12 -5
  261. package/docs/concepts/sessions-runs-and-streaming.md +9 -8
  262. package/docs/connections/overview.mdx +1 -1
  263. package/docs/experimental/dynamic-schedules.mdx +186 -0
  264. package/docs/experimental/meta.json +4 -0
  265. package/docs/guides/client/streaming.mdx +1 -0
  266. package/docs/guides/deployment/self-hosting.md +3 -0
  267. package/docs/guides/hooks.md +21 -1
  268. package/docs/memory/overview.mdx +2 -1
  269. package/docs/patterns/dynamic-scheduling.md +3 -1
  270. package/docs/reference/cli.md +14 -7
  271. package/docs/schedules.mdx +2 -0
  272. package/docs/subagents/index.mdx +2 -0
  273. package/docs/tools/overview.mdx +2 -1
  274. package/docs/tools/tasks-upgrade.md +12 -7
  275. package/docs/tools/tasks.md +10 -6
  276. package/docs/tools/workflows.mdx +36 -5
  277. package/docs/tutorial/connect-a-warehouse.mdx +1 -1
  278. package/docs/tutorial/run-analysis.mdx +1 -1
  279. package/package.json +1 -1
  280. package/dist/src/execution/run-session-limits.d.ts +0 -12
  281. package/dist/src/execution/run-session-limits.js +0 -1
  282. package/dist/src/harness/session-usage-limits.d.ts +0 -49
  283. package/dist/src/harness/session-usage-limits.js +0 -1
  284. package/dist/src/subagents/token-budget.d.ts +0 -15
  285. package/dist/src/subagents/token-budget.js +0 -1
@@ -1,6 +1,7 @@
1
1
  import type { StandardJSONSchemaV1, StandardSchemaV1 } from "#compiled/@standard-schema/spec/index.js";
2
2
  import type { ToolApproval } from "#approval/definition.js";
3
3
  import type { MessageResult, SendTurnOptions } from "#client/types.js";
4
+ import type { AgentModelOptionsDefinition, AgentReasoningDefinition } from "#shared/agent-definition.js";
4
5
  import type { JsonObject } from "#shared/json.js";
5
6
  import { type PublicToolDefinition, type ToolContext, type ToolInputRequest, type ToolInputRequestOptions, type ToolInputResponse } from "#tools/definition.js";
6
7
  import type { ToolModelOutput } from "#tools/model-output.js";
@@ -9,6 +10,18 @@ export type { WorkflowToolEntryPoint };
9
10
  export interface WorkflowAgentMetadata {
10
11
  readonly description: string;
11
12
  }
13
+ /** A serializable model selection for a local `ctx.agent` session. */
14
+ export type AgentSessionModelSelection = string | {
15
+ readonly model: string;
16
+ readonly modelContextWindowTokens?: number;
17
+ readonly modelOptions?: AgentModelOptionsDefinition;
18
+ readonly reasoning?: AgentReasoningDefinition;
19
+ };
20
+ /** Options that bind to a `ctx.agent` session when it opens. */
21
+ export interface AgentSessionOptions {
22
+ /** Override the model for every turn in this local agent session. */
23
+ readonly model?: AgentSessionModelSelection;
24
+ }
12
25
  /** Context capabilities available inside an authored `"use step"` helper. */
13
26
  export type WorkflowStepToolContext = Pick<ToolContext, "abortSignal" | "callId" | "session" | "toolName" | "getToken" | "requireAuth">;
14
27
  /** Options for one message to a `ctx.agent` session. */
@@ -54,7 +67,7 @@ export type WorkflowSharedContext = Pick<ToolContext, "session" | "toolName" | "
54
67
  * Returns a new session with the agent of this invocation name. Nothing
55
68
  * starts until the first `send`.
56
69
  */
57
- agent(name: string): AgentSession;
70
+ agent(name: string, options?: AgentSessionOptions): AgentSession;
58
71
  /** Metadata for agents callable by this workflow, including hidden agents. */
59
72
  agents: Readonly<Record<string, WorkflowAgentMetadata>>;
60
73
  /**
@@ -3,10 +3,13 @@ export declare function withConversationId(context: Context, conversationId: str
3
3
  interface OperationConversation {
4
4
  readonly rootSessionId?: string;
5
5
  readonly sessionId: string;
6
+ readonly traceSessionId?: string;
6
7
  }
8
+ export declare function traceSessionIdOf(scope: OperationConversation): string;
7
9
  export declare function operationConversationId(input: OperationConversation): string;
8
- export declare function withOperationConversation(context: Context, input: OperationConversation): Context;
10
+ export declare function withOperationTraceContext(context: Context, input: OperationConversation): Context;
9
11
  export declare function conversationIdFromContext(context: unknown): string | undefined;
12
+ export declare function traceSessionIdFromContext(context: unknown): string | undefined;
10
13
  export declare function readConversationBaggage(value: string | null): string | undefined;
11
14
  export declare function writeConversationBaggage(value: string | undefined, conversationId: string | undefined): string | undefined;
12
15
  export {};
@@ -1 +1 @@
1
- import{readBaggageMember,replaceBaggageMember}from"#protocol/baggage.js";import{readConversationId,resolveConversationId}from"#shared/conversation-identity.js";import{createContextKey}from"#compiled/@opentelemetry/api/index.js";const BAGGAGE_KEY=`eve.conversation.id`,CONVERSATION_KEY=createContextKey(`eve.trace.conversation.id`);function withConversationId(e,t){return e.setValue(CONVERSATION_KEY,t)}function operationConversationId(e){return resolveConversationId(e.rootSessionId??e.sessionId)}function withOperationConversation(e,t){return withConversationId(e,operationConversationId(t))}function conversationIdFromContext(e){if(typeof e!=`object`||!e)return;let t=Reflect.get(e,`getValue`);return typeof t==`function`?readConversationId(Reflect.apply(t,e,[CONVERSATION_KEY])):void 0}function readConversationBaggage(e){let t=readBaggageMember(e,BAGGAGE_KEY);return typeof t==`string`?void 0:readConversationId(t.value)}function writeConversationBaggage(e,t){let n=readConversationId(t);return n===void 0?e:replaceBaggageMember(e,BAGGAGE_KEY,encodeURIComponent(n))}export{conversationIdFromContext,operationConversationId,readConversationBaggage,withConversationId,withOperationConversation,writeConversationBaggage};
1
+ import{readBaggageMember,replaceBaggageMember}from"#protocol/baggage.js";import{readConversationId,resolveConversationId}from"#shared/conversation-identity.js";import{createContextKey}from"#compiled/@opentelemetry/api/index.js";const BAGGAGE_KEY=`eve.conversation.id`,CONVERSATION_KEY=createContextKey(`eve.trace.conversation.id`),TRACE_SESSION_KEY=createContextKey(`eve.trace.session.id`);function withConversationId(e,t){return e.setValue(CONVERSATION_KEY,t)}function traceSessionIdOf(e){return e.traceSessionId??e.rootSessionId??e.sessionId}function operationConversationId(e){return resolveConversationId(e.rootSessionId??e.sessionId)}function withOperationTraceContext(e,t){return withConversationId(e,operationConversationId(t)).setValue(TRACE_SESSION_KEY,traceSessionIdOf(t))}function conversationIdFromContext(e){return readConversationId(readContextValue(e,CONVERSATION_KEY))}function traceSessionIdFromContext(e){let t=readContextValue(e,TRACE_SESSION_KEY);return typeof t==`string`&&t.length>0?t:void 0}function readContextValue(e,t){if(typeof e!=`object`||!e)return;let n=Reflect.get(e,`getValue`);if(typeof n==`function`)return Reflect.apply(n,e,[t])}function readConversationBaggage(e){let t=readBaggageMember(e,BAGGAGE_KEY);return typeof t==`string`?void 0:readConversationId(t.value)}function writeConversationBaggage(e,t){let n=readConversationId(t);return n===void 0?e:replaceBaggageMember(e,BAGGAGE_KEY,encodeURIComponent(n))}export{conversationIdFromContext,operationConversationId,readConversationBaggage,traceSessionIdFromContext,traceSessionIdOf,withConversationId,withOperationTraceContext,writeConversationBaggage};
@@ -1 +1 @@
1
- import{createLogger,formatError}from"#internal/logging.js";import{applyLiveDeliveryAudienceCeiling}from"#shared/forwarded-trace-policy.js";import{DIRECT_TOOL_CALL_ATTRIBUTE,DIRECT_TOOL_CALL_VALUE}from"#tracing/local/inspection.js";import{resolveInstrumentationEnvironment}from"#internal/application/dev-environment.js";import{operationConversationId}from"#tracing/eve/conversation-context.js";import{resolveTracePolicy}from"#shared/trace-policy.js";import{context}from"#compiled/@opentelemetry/api/index.js";import{buildConversationContext}from"#channel/conversation-context.js";import{markAgentTraceContext}from"#tracing/eve/agent-trace-context.js";import{toolCallIdempotencyKey}from"#instrumentation/lifecycle.js";import{contentAttribute,mcpLifecycle,withErrorContent}from"#compiled/@vercel/agent-runs/otel.js";import{otelTelemetry}from"#compiled/@vercel/agent-runs/index.js";import{getInstrumentationRuntime}from"#instrumentation/runtime-global.js";import{MCP_SERIALIZER}from"#tracing/eve/mcp.js";import{withChannelAudience}from"#tracing/eve/channel-audience-context.js";import{eveOutputMapping}from"#tracing/eve/profile.js";const log=createLogger(`invoke-tool`),agentTelemetry=()=>otelTelemetry({tracerName:`eve.agent`,mapping:eveOutputMapping()});async function withInvokeToolSpan(e,t){let n=withErrorContent(context.active(),!1);return await context.with(n,()=>traced(e,n,t))}async function traced(e,t,n){let r=getInstrumentationRuntime();if(r===void 0)return await n(silentObserver);let i=agentTelemetry(),a=buildConversationContext({adapter:e.origin?.adapter??{kind:`channel`},auth:e.auth,channelName:e.origin?.channelName},resolveInstrumentationEnvironment()),o=toolCallEvents(r.hooks.forTrace?.({agentName:e.agentName,...a})??r.hooks,{attemptId:e.callId,attemptIndex:0,channelAudience:a.audience,functionId:e.agentName,rootSessionId:e.sessionId,sessionId:e.sessionId,stepIndex:0,traceSessionId:e.sessionId,turnId:e.callId},e),s=r.otelSettings;if(s===void 0)return await n(o.observer(void 0));let c=resolveTracePolicy(s.tracePolicy,{agentName:e.agentName,...a},e=>log.warn(`tracePolicy threw; dropping the tool call's trace`,{error:formatError(e)}));if(c.action===`drop`)return await i.suppressed(()=>n(o.observer(void 0)));let l=applyLiveDeliveryAudienceCeiling({...c,recordInputs:s.recordInputs&&c.recordInputs,recordOutputs:s.recordOutputs&&c.recordOutputs},a.audience,void 0,a.environment),u=l.action===`record`&&l.recordInputs,d=l.action===`record`&&l.recordOutputs,f=`execute_tool ${e.toolName}`,p=withChannelAudience(t,a.audience),m={"agent.tool.is_framework":!1,"gen_ai.agent.name":e.agentName,"gen_ai.operation.name":`execute_tool`,"gen_ai.tool.call.id":e.callId,"gen_ai.tool.name":e.toolName,"gen_ai.tool.type":`function`,[DIRECT_TOOL_CALL_ATTRIBUTE]:DIRECT_TOOL_CALL_VALUE,"operation.name":`execute_tool`,"resource.name":f,"agent.run.id":e.sessionId,"agent.trace.schema.version":4,"gen_ai.conversation.id":operationConversationId({sessionId:e.sessionId})};process.env.VERCEL_ENV!==void 0&&(m[`vercel.session_id`]=e.sessionId),e.origin!==void 0&&(m[`eve.channel.kind`]=a.channel.kind,m[`eve.channel.name`]=e.origin.channelName);let h=i.startSpan({type:`tool`,operationId:e.callId,name:f,kind:`INTERNAL`,attributes:m},{context:p}),g={emit:!0,recordInputs:u,recordOutputs:d},_=markAgentTraceContext(withErrorContent(p,d)),v=mcpLifecycle({serializer:MCP_SERIALIZER,...g,write:e=>setDefined(h,e),error:(e,t)=>h.fail(d?e:void 0,t)}),y,b=o.observer({failedWith:e=>{y={error:e}},recordInputs:u,span:h});try{let e=await i.run({type:`tool`,reference:h.reference,capture:g,mcp:v},()=>n(b),_);if(h.setAttribute(`eve.tool.outcome`,e.status),e.status===`completed`&&d){let t=contentAttribute(e.output);t!==void 0&&h.setAttribute(`gen_ai.tool.call.result`,t)}return e.status===`invalid-input`?h.fail(void 0,e.status):e.status===`failed`&&h.fail(d?y?.error:void 0,y===void 0?e.status:void 0),e}catch(e){throw h.fail(d?e:void 0),e}finally{h.end(),await r.forceFlush().catch(e=>{log.warn(`flushing a tool call's trace failed`,{error:formatError(e)})})}}const silentObserver={executed:async()=>{},executing:async()=>{},failedWith:()=>{}};function toolCallEvents(e,t,n){let r=e.capturesInputs??e.capturesContent,i=e.capturesOutputs??e.capturesContent,a=toolCallIdempotencyKey(t,n.callId,0);return{observer(o){return{async executing(i){if(o?.recordInputs){let e=contentAttribute(i);e!==void 0&&o.span.setAttribute(`gen_ai.tool.call.arguments`,e)}await e.publish(Object.freeze({callId:n.callId,idempotencyKey:a,input:r?i:void 0,scope:t,toolName:n.toolName,type:`tool.call.started`}))},async executed(n){o?.span.setAttribute(`gen_ai.execute_tool.duration`,n.durationMs/1e3);let r=n.type===`result`?i?{output:n.output,type:`result`}:{type:`result`}:i?{error:n.error,type:`error`}:{type:`error`};await e.publish(Object.freeze({durationMs:n.durationMs,idempotencyKey:a,output:Object.freeze(r),scope:t,type:`tool.call.completed`,outcome:n.type===`result`?`completed`:`failed`}))},failedWith(e){o?.failedWith(e)}}}}}function setDefined(e,t){for(let[n,r]of Object.entries(t))r!==void 0&&e.setAttribute(n,r)}export{withInvokeToolSpan};
1
+ import{createLogger,formatError}from"#internal/logging.js";import{applyLiveDeliveryAudienceCeiling}from"#shared/forwarded-trace-policy.js";import{DIRECT_TOOL_CALL_ATTRIBUTE,DIRECT_TOOL_CALL_VALUE}from"#tracing/local/inspection.js";import{resolveInstrumentationEnvironment}from"#internal/application/dev-environment.js";import{operationConversationId,withOperationTraceContext}from"#tracing/eve/conversation-context.js";import{resolveTracePolicy}from"#shared/trace-policy.js";import{context}from"#compiled/@opentelemetry/api/index.js";import{buildConversationContext}from"#channel/conversation-context.js";import{markAgentTraceContext}from"#tracing/eve/agent-trace-context.js";import{toolCallIdempotencyKey}from"#instrumentation/lifecycle.js";import{contentAttribute,mcpLifecycle,withErrorContent}from"#compiled/@vercel/agent-runs/otel.js";import{otelTelemetry}from"#compiled/@vercel/agent-runs/index.js";import{getInstrumentationRuntime}from"#instrumentation/runtime-global.js";import{MCP_SERIALIZER}from"#tracing/eve/mcp.js";import{withChannelAudience}from"#tracing/eve/channel-audience-context.js";import{eveOutputMapping}from"#tracing/eve/profile.js";const log=createLogger(`invoke-tool`),agentTelemetry=()=>otelTelemetry({tracerName:`eve.agent`,mapping:eveOutputMapping()});async function withInvokeToolSpan(e,t){let n=withErrorContent(context.active(),!1);return await context.with(n,()=>traced(e,n,t))}async function traced(e,t,n){let r=getInstrumentationRuntime();if(r===void 0)return await n(silentObserver);let i=agentTelemetry(),a=buildConversationContext({adapter:e.origin?.adapter??{kind:`channel`},auth:e.auth,channelName:e.origin?.channelName},resolveInstrumentationEnvironment()),o=r.hooks.forTrace?.({agentName:e.agentName,...a})??r.hooks,s={attemptId:e.callId,attemptIndex:0,channelAudience:a.audience,functionId:e.agentName,rootSessionId:e.sessionId,sessionId:e.sessionId,stepIndex:0,traceSessionId:e.sessionId,turnId:e.callId},c=toolCallEvents(o,s,e),l=r.otelSettings;if(l===void 0)return await n(c.observer(void 0));let u=resolveTracePolicy(l.tracePolicy,{agentName:e.agentName,...a},e=>log.warn(`tracePolicy threw; dropping the tool call's trace`,{error:formatError(e)}));if(u.action===`drop`)return await i.suppressed(()=>n(c.observer(void 0)));let d=applyLiveDeliveryAudienceCeiling({...u,recordInputs:l.recordInputs&&u.recordInputs,recordOutputs:l.recordOutputs&&u.recordOutputs},a.audience,void 0,a.environment),f=d.action===`record`&&d.recordInputs,p=d.action===`record`&&d.recordOutputs,m=`execute_tool ${e.toolName}`,h=withOperationTraceContext(withChannelAudience(t,a.audience),s),g={"agent.tool.is_framework":!1,"gen_ai.agent.name":e.agentName,"gen_ai.operation.name":`execute_tool`,"gen_ai.tool.call.id":e.callId,"gen_ai.tool.name":e.toolName,"gen_ai.tool.type":`function`,[DIRECT_TOOL_CALL_ATTRIBUTE]:DIRECT_TOOL_CALL_VALUE,"operation.name":`execute_tool`,"resource.name":m,"agent.run.id":e.sessionId,"agent.trace.schema.version":4,"gen_ai.conversation.id":operationConversationId({sessionId:e.sessionId})};process.env.VERCEL_ENV!==void 0&&(g[`vercel.session_id`]=e.sessionId),e.origin!==void 0&&(g[`eve.channel.kind`]=a.channel.kind,g[`eve.channel.name`]=e.origin.channelName);let _=i.startSpan({type:`tool`,operationId:e.callId,name:m,kind:`INTERNAL`,attributes:g},{context:h}),v={emit:!0,recordInputs:f,recordOutputs:p},y=markAgentTraceContext(withErrorContent(h,p)),b=mcpLifecycle({serializer:MCP_SERIALIZER,...v,write:e=>setDefined(_,e),error:(e,t)=>_.fail(p?e:void 0,t)}),x,S=c.observer({failedWith:e=>{x={error:e}},recordInputs:f,span:_});try{let e=await i.run({type:`tool`,reference:_.reference,capture:v,mcp:b},()=>n(S),y);if(_.setAttribute(`eve.tool.outcome`,e.status),e.status===`completed`&&p){let t=contentAttribute(e.output);t!==void 0&&_.setAttribute(`gen_ai.tool.call.result`,t)}return e.status===`invalid-input`?_.fail(void 0,e.status):e.status===`failed`&&_.fail(p?x?.error:void 0,x===void 0?e.status:void 0),e}catch(e){throw _.fail(p?e:void 0),e}finally{_.end(),await r.forceFlush().catch(e=>{log.warn(`flushing a tool call's trace failed`,{error:formatError(e)})})}}const silentObserver={executed:async()=>{},executing:async()=>{},failedWith:()=>{}};function toolCallEvents(e,t,n){let r=e.capturesInputs??e.capturesContent,i=e.capturesOutputs??e.capturesContent,a=toolCallIdempotencyKey(t,n.callId,0);return{observer(o){return{async executing(i){if(o?.recordInputs){let e=contentAttribute(i);e!==void 0&&o.span.setAttribute(`gen_ai.tool.call.arguments`,e)}await e.publish(Object.freeze({callId:n.callId,idempotencyKey:a,input:r?i:void 0,scope:t,toolName:n.toolName,type:`tool.call.started`}))},async executed(n){o?.span.setAttribute(`gen_ai.execute_tool.duration`,n.durationMs/1e3);let r=n.type===`result`?i?{output:n.output,type:`result`}:{type:`result`}:i?{error:n.error,type:`error`}:{type:`error`};await e.publish(Object.freeze({durationMs:n.durationMs,idempotencyKey:a,output:Object.freeze(r),scope:t,type:`tool.call.completed`,outcome:n.type===`result`?`completed`:`failed`}))},failedWith(e){o?.failedWith(e)}}}}}function setDefined(e,t){for(let[n,r]of Object.entries(t))r!==void 0&&e.setAttribute(n,r)}export{withInvokeToolSpan};
@@ -1,10 +1,5 @@
1
1
  import type { AgentTraceStateStore } from "#tracing/eve/agent-trace-state.js";
2
2
  import { type AgentTelemetry, type AgentRun } from "#compiled/@vercel/agent-runs/index.js";
3
- export declare function traceSessionIdOf(scope: {
4
- readonly traceSessionId?: string;
5
- readonly rootSessionId?: string;
6
- readonly sessionId: string;
7
- }): string;
8
3
  export declare function checkpointContent(value: string | undefined): unknown;
9
4
  /** Identity of one eve turn within the shared tracing library. */
10
5
  export declare function eveTurnIdentity(input: {
@@ -1 +1 @@
1
- import{resolveConversationId}from"#shared/conversation-identity.js";import{createAgentRun}from"#compiled/@vercel/agent-runs/index.js";function traceSessionIdOf(e){return e.traceSessionId??e.rootSessionId??e.sessionId}function checkpointContent(e){if(e!==void 0)try{return JSON.parse(e)}catch{return}}function eveTurnIdentity(e){return{conversationId:resolveConversationId(e.rootSessionId??e.sessionId),runId:e.sessionId,turnId:e.turnId}}function createEveTracing(e){return createAgentRun({telemetry:e.telemetry,checkpointer:{get:t=>e.stateStore.get(`checkpoint`,t),set:(t,n)=>e.stateStore.set(`checkpoint`,t,n),delete:t=>e.stateStore.delete(`checkpoint`,t)}})}export{checkpointContent,createEveTracing,eveTurnIdentity,traceSessionIdOf};
1
+ import{resolveConversationId}from"#shared/conversation-identity.js";import{createAgentRun}from"#compiled/@vercel/agent-runs/index.js";function checkpointContent(e){if(e!==void 0)try{return JSON.parse(e)}catch{return}}function eveTurnIdentity(e){return{conversationId:resolveConversationId(e.rootSessionId??e.sessionId),runId:e.sessionId,turnId:e.turnId}}function createEveTracing(e){return createAgentRun({telemetry:e.telemetry,checkpointer:{get:t=>e.stateStore.get(`checkpoint`,t),set:(t,n)=>e.stateStore.set(`checkpoint`,t,n),delete:t=>e.stateStore.delete(`checkpoint`,t)}})}export{checkpointContent,createEveTracing,eveTurnIdentity};
@@ -1 +1 @@
1
- import{createRequire}from"node:module";import{conversationIdFromContext}from"#tracing/eve/conversation-context.js";import{SpanKind,context,metrics,propagation,trace}from"#compiled/@opentelemetry/api/index.js";import{invocationName}from"#compiled/@vercel/agent-runs/otel.js";import{AgentSpanIdGenerator}from"#compiled/@vercel/agent-runs/index.js";import{registerOTel}from"#compiled/@vercel/otel/index.js";const REGISTRATION_SPAN_NAME=`eve.otel.registration`,REPLAY_DEDUPLICATION_LIMIT=1e5,REPLAY_DEDUPLICATION_KEY=Symbol.for(`eve.otel.replay-deduplication`),require=createRequire(import.meta.url),replayDeduplicationGlobal=globalThis;var RegistrationMarkerPropagator=class{#e=!1;extract(e){return e}fields(){return[]}inject(){this.#e=!0}isInstalled(){return this.#e=!1,propagation.inject(context.active(),{},{set:()=>{}}),this.#e}},PrivateSpanFilteringProcessor=class{endedSpans;forwardedSpans=new Set;pendingByParent=new Map;pendingSpanCount=0;processors;startedSpans=new Set;constructor(e,t){this.processors=e,this.endedSpans=t}async forceFlush(){this.drainPendingSpans(),await Promise.all(this.processors.map(e=>e.forceFlush()))}onEnd(e){if(isRegistrationSpan(e))return;let t=spanIdentity(e);if(t!==void 0){if(this.endedSpans.has(t))return;if(this.endedSpans.size>=REPLAY_DEDUPLICATION_LIMIT){let e=this.endedSpans.values().next().value;e!==void 0&&this.endedSpans.delete(e)}this.endedSpans.add(t)}let n=parentIdentity(e);if(n!==void 0&&this.startedSpans.has(n)&&!this.forwardedSpans.has(n)){let t=this.pendingByParent.get(n)??[];t.push(e),this.pendingByParent.set(n,t),this.pendingSpanCount+=1,this.pendingSpanCount>1e4&&this.releaseOldestPendingParent();return}this.forward(e,t)}onStart(e,t){if(isRegistrationSpan(e))return;let n=conversationIdFromContext(t);n!==void 0&&e.attributes?.[`gen_ai.conversation.id`]===void 0&&e.setAttribute(`gen_ai.conversation.id`,n);let r=spanIdentity(e);r!==void 0&&addBounded(this.startedSpans,r);for(let n of this.processors)n.onStart(e,t)}async shutdown(){this.drainPendingSpans(),await Promise.all(this.processors.map(e=>e.shutdown()))}drainPendingSpans(){for(;this.pendingByParent.size>0;)this.releaseOldestPendingParent()}releaseOldestPendingParent(){let e=this.pendingByParent.keys().next().value;e!==void 0&&this.releaseChildren(e)}releaseChildren(e){let t=this.pendingByParent.get(e);if(t!==void 0){this.pendingByParent.delete(e),this.pendingSpanCount-=t.length;for(let e of t)this.forward(e,spanIdentity(e))}}forward(e,t){for(let t of this.processors)t.onEnd(e);t!==void 0&&(addBounded(this.forwardedSpans,t),this.releaseChildren(t))}};function registerOtelPipeline(e){let t=e.otel,n=captureOptionalPeerTracerProxy(),r=new AgentSpanIdGenerator,i=new RegistrationMarkerPropagator,a=privateSpanProcessors(t.spanProcessors),o={attributes:t.resource,autoDetectResources:!1,idGenerator:r,instrumentations:t.instrumentations??[],metricReaders:t.metricReaders,propagators:[...t.propagators??[`auto`],i],serviceName:e.serviceName,spanProcessors:a};registerOTel(t.sampler===void 0?o:{...o,traceSampler:t.sampler});let s=globalTracerUses(r),c=i.isInstalled();if((!s||!c)&&rollbackRegistration({ownsPropagator:c,ownsTracer:s}),!s)throw Error("eve could not register OpenTelemetry because another runtime already owns the global tracer provider. Remove the other `registerOTel` call, or move its exporters into eve's `otelIntegration({ spanProcessors: [...] })`.");if(!c)throw Error("eve could not register OpenTelemetry because another runtime already owns the global propagator. Remove the other global propagator registration and declare propagators through eve's `otel()` instead.");let l=runtimeTracerProvider();if(typeof l.forceFlush!=`function`||typeof l.shutdown!=`function`)throw rollbackRegistration({ownsPropagator:c,ownsTracer:s}),Error(`The registered OpenTelemetry tracer provider has no lifecycle methods.`);n?.setDelegate(l);let u=runtimeMeterProvider();return{provider:trace.getTracerProvider(),forceFlush:async()=>{await Promise.all([l.forceFlush(),u.forceFlush?.()])},idGenerator:r,samplesTrace:(e,t)=>samplerAdmitsTrace(r,e,t),shutdown:async()=>{disableInstrumentations(t.instrumentations),await Promise.all([l.shutdown(),u.shutdown?.()])}}}function privateSpanProcessors(e){let t=e.filter(isSpanProcessor);if(t.length===0)return[...e];let n=new PrivateSpanFilteringProcessor(t,replayDeduplicationRegistry()),r=[],i=!1;for(let t of e){if(!isSpanProcessor(t)){r.push(t);continue}i||(i=!0,r.push(n))}return r}function replayDeduplicationRegistry(){let e=replayDeduplicationGlobal[REPLAY_DEDUPLICATION_KEY];if(e!==void 0)return e;let t=new Set;return replayDeduplicationGlobal[REPLAY_DEDUPLICATION_KEY]=t,t}const registerOtel=registerOtelPipeline;function samplerAdmitsTrace(e,t,n={name:invocationName(void 0)}){return(e.withTraceId(t,()=>trace.getTracer(`eve.registration`).startSpan(n.name,{attributes:n.attributes,kind:SpanKind.INTERNAL,root:!0})).spanContext().traceFlags&1)==1}function rollbackRegistration(e){if(e.ownsPropagator&&propagation.disable(),!e.ownsTracer)return;let t=runtimeTracerProvider();if(typeof t.shutdown==`function`)try{t.shutdown().catch(()=>{})}catch{}trace.disable()}function runtimeTracerProvider(){let e=trace.getTracerProvider();return e.getDelegate?.()??e}function runtimeMeterProvider(){let e=metrics.getMeterProvider();return{forceFlush:typeof e?.forceFlush==`function`?()=>e.forceFlush():void 0,shutdown:typeof e?.shutdown==`function`?()=>e.shutdown():void 0}}function disableInstrumentations(e){for(let t of e??[]){let e=t?.disable;if(typeof e==`function`)try{e.call(t)}catch{}}}function globalTracerUses(e){let t=e.allocateSpanId();return e.withSpanId(t,()=>trace.getTracer(`eve.registration`).startSpan(REGISTRATION_SPAN_NAME)).spanContext().spanId===t}function isRegistrationSpan(e){return typeof e==`object`&&!!e&&(`name`in e&&e.name===REGISTRATION_SPAN_NAME||`instrumentationScope`in e&&e.instrumentationScope?.name===`eve.registration`)}function spanIdentity(e){if(typeof e!=`object`||!e||!(`spanContext`in e)||typeof e.spanContext!=`function`)return;let t=e.spanContext();return typeof t.traceId==`string`&&typeof t.spanId==`string`?`${t.traceId}:${t.spanId}`:void 0}function parentIdentity(e){if(typeof e!=`object`||!e||!(`parentSpanContext`in e))return;let t=e.parentSpanContext;return typeof t?.traceId==`string`&&typeof t.spanId==`string`?`${t.traceId}:${t.spanId}`:void 0}function addBounded(e,t){if(e.size>=REPLAY_DEDUPLICATION_LIMIT){let t=e.values().next().value;t!==void 0&&e.delete(t)}e.add(t)}function isSpanProcessor(e){return e!==`auto`}function captureOptionalPeerTracerProxy(){try{let e=require("@opentelemetry/api"),t=e.trace.getTracerProvider();return t instanceof e.ProxyTracerProvider?t:void 0}catch{return}}export{registerOtel,registerOtelPipeline};
1
+ import{createRequire}from"node:module";import{conversationIdFromContext,traceSessionIdFromContext}from"#tracing/eve/conversation-context.js";import{SpanKind,context,metrics,propagation,trace}from"#compiled/@opentelemetry/api/index.js";import{invocationName}from"#compiled/@vercel/agent-runs/otel.js";import{AgentSpanIdGenerator}from"#compiled/@vercel/agent-runs/index.js";import{registerOTel}from"#compiled/@vercel/otel/index.js";const REGISTRATION_SPAN_NAME=`eve.otel.registration`,REPLAY_DEDUPLICATION_LIMIT=1e5,REPLAY_DEDUPLICATION_KEY=Symbol.for(`eve.otel.replay-deduplication`),require=createRequire(import.meta.url),replayDeduplicationGlobal=globalThis;var RegistrationMarkerPropagator=class{#e=!1;extract(e){return e}fields(){return[]}inject(){this.#e=!0}isInstalled(){return this.#e=!1,propagation.inject(context.active(),{},{set:()=>{}}),this.#e}},PrivateSpanFilteringProcessor=class{endedSpans;forwardedSpans=new Set;pendingByParent=new Map;pendingSpanCount=0;processors;startedSpans=new Set;constructor(e,t){this.processors=e,this.endedSpans=t}async forceFlush(){this.drainPendingSpans(),await Promise.all(this.processors.map(e=>e.forceFlush()))}onEnd(e){if(isRegistrationSpan(e))return;let t=spanIdentity(e);if(t!==void 0){if(this.endedSpans.has(t))return;if(this.endedSpans.size>=REPLAY_DEDUPLICATION_LIMIT){let e=this.endedSpans.values().next().value;e!==void 0&&this.endedSpans.delete(e)}this.endedSpans.add(t)}let n=parentIdentity(e);if(n!==void 0&&this.startedSpans.has(n)&&!this.forwardedSpans.has(n)){let t=this.pendingByParent.get(n)??[];t.push(e),this.pendingByParent.set(n,t),this.pendingSpanCount+=1,this.pendingSpanCount>1e4&&this.releaseOldestPendingParent();return}this.forward(e,t)}onStart(e,t){if(isRegistrationSpan(e))return;let n=e,r=conversationIdFromContext(t);r!==void 0&&n.attributes?.[`gen_ai.conversation.id`]===void 0&&n.setAttribute(`gen_ai.conversation.id`,r);let i=traceSessionIdFromContext(t);process.env.VERCEL_ENV!==void 0&&i!==void 0&&n.attributes?.[`vercel.session_id`]===void 0&&n.setAttribute(`vercel.session_id`,i);let a=spanIdentity(e);a!==void 0&&addBounded(this.startedSpans,a);for(let n of this.processors)n.onStart(e,t)}async shutdown(){this.drainPendingSpans(),await Promise.all(this.processors.map(e=>e.shutdown()))}drainPendingSpans(){for(;this.pendingByParent.size>0;)this.releaseOldestPendingParent()}releaseOldestPendingParent(){let e=this.pendingByParent.keys().next().value;e!==void 0&&this.releaseChildren(e)}releaseChildren(e){let t=this.pendingByParent.get(e);if(t!==void 0){this.pendingByParent.delete(e),this.pendingSpanCount-=t.length;for(let e of t)this.forward(e,spanIdentity(e))}}forward(e,t){for(let t of this.processors)t.onEnd(e);t!==void 0&&(addBounded(this.forwardedSpans,t),this.releaseChildren(t))}};function registerOtelPipeline(e){let t=e.otel,n=captureOptionalPeerTracerProxy(),r=new AgentSpanIdGenerator,i=new RegistrationMarkerPropagator,a=privateSpanProcessors(t.spanProcessors),o={attributes:t.resource,autoDetectResources:!1,idGenerator:r,instrumentations:t.instrumentations??[],metricReaders:t.metricReaders,propagators:[...t.propagators??[`auto`],i],serviceName:e.serviceName,spanProcessors:a};registerOTel(t.sampler===void 0?o:{...o,traceSampler:t.sampler});let s=globalTracerUses(r),c=i.isInstalled();if((!s||!c)&&rollbackRegistration({ownsPropagator:c,ownsTracer:s}),!s)throw Error("eve could not register OpenTelemetry because another runtime already owns the global tracer provider. Remove the other `registerOTel` call, or move its exporters into eve's `otelIntegration({ spanProcessors: [...] })`.");if(!c)throw Error("eve could not register OpenTelemetry because another runtime already owns the global propagator. Remove the other global propagator registration and declare propagators through eve's `otel()` instead.");let l=runtimeTracerProvider();if(typeof l.forceFlush!=`function`||typeof l.shutdown!=`function`)throw rollbackRegistration({ownsPropagator:c,ownsTracer:s}),Error(`The registered OpenTelemetry tracer provider has no lifecycle methods.`);n?.setDelegate(l);let u=runtimeMeterProvider();return{provider:trace.getTracerProvider(),forceFlush:async()=>{await Promise.all([l.forceFlush(),u.forceFlush?.()])},idGenerator:r,samplesTrace:(e,t)=>samplerAdmitsTrace(r,e,t),shutdown:async()=>{disableInstrumentations(t.instrumentations),await Promise.all([l.shutdown(),u.shutdown?.()])}}}function privateSpanProcessors(e){let t=e.filter(isSpanProcessor);if(t.length===0)return[...e];let n=new PrivateSpanFilteringProcessor(t,replayDeduplicationRegistry()),r=[],i=!1;for(let t of e){if(!isSpanProcessor(t)){r.push(t);continue}i||(i=!0,r.push(n))}return r}function replayDeduplicationRegistry(){let e=replayDeduplicationGlobal[REPLAY_DEDUPLICATION_KEY];if(e!==void 0)return e;let t=new Set;return replayDeduplicationGlobal[REPLAY_DEDUPLICATION_KEY]=t,t}const registerOtel=registerOtelPipeline;function samplerAdmitsTrace(e,t,n={name:invocationName(void 0)}){return(e.withTraceId(t,()=>trace.getTracer(`eve.registration`).startSpan(n.name,{attributes:n.attributes,kind:SpanKind.INTERNAL,root:!0})).spanContext().traceFlags&1)==1}function rollbackRegistration(e){if(e.ownsPropagator&&propagation.disable(),!e.ownsTracer)return;let t=runtimeTracerProvider();if(typeof t.shutdown==`function`)try{t.shutdown().catch(()=>{})}catch{}trace.disable()}function runtimeTracerProvider(){let e=trace.getTracerProvider();return e.getDelegate?.()??e}function runtimeMeterProvider(){let e=metrics.getMeterProvider();return{forceFlush:typeof e?.forceFlush==`function`?()=>e.forceFlush():void 0,shutdown:typeof e?.shutdown==`function`?()=>e.shutdown():void 0}}function disableInstrumentations(e){for(let t of e??[]){let e=t?.disable;if(typeof e==`function`)try{e.call(t)}catch{}}}function globalTracerUses(e){let t=e.allocateSpanId();return e.withSpanId(t,()=>trace.getTracer(`eve.registration`).startSpan(REGISTRATION_SPAN_NAME)).spanContext().spanId===t}function isRegistrationSpan(e){return typeof e==`object`&&!!e&&(`name`in e&&e.name===REGISTRATION_SPAN_NAME||`instrumentationScope`in e&&e.instrumentationScope?.name===`eve.registration`)}function spanIdentity(e){if(typeof e!=`object`||!e||!(`spanContext`in e)||typeof e.spanContext!=`function`)return;let t=e.spanContext();return typeof t.traceId==`string`&&typeof t.spanId==`string`?`${t.traceId}:${t.spanId}`:void 0}function parentIdentity(e){if(typeof e!=`object`||!e||!(`parentSpanContext`in e))return;let t=e.parentSpanContext;return typeof t?.traceId==`string`&&typeof t.spanId==`string`?`${t.traceId}:${t.spanId}`:void 0}function addBounded(e,t){if(e.size>=REPLAY_DEDUPLICATION_LIMIT){let t=e.values().next().value;t!==void 0&&e.delete(t)}e.add(t)}function isSpanProcessor(e){return e!==`auto`}function captureOptionalPeerTracerProxy(){try{let e=require("@opentelemetry/api"),t=e.trace.getTracerProvider();return t instanceof e.ProxyTracerProvider?t:void 0}catch{return}}export{registerOtel,registerOtelPipeline};
@@ -1,9 +1,10 @@
1
+ import type { Context } from "#compiled/@opentelemetry/api/index.js";
1
2
  import { type InstrumentationSessionStartedEvent, type InstrumentationTraceSeed, type InstrumentationTurnStartedEvent, type InstrumentationTurnTerminalEvent, type InstrumentationSessionTransitionEvent } from "#instrumentation/lifecycle.js";
2
3
  import type { TraceCapturePolicy } from "#tracing/eve/otel-declaration.js";
3
4
  import type { AgentSessionTraceState, AgentTraceStateStore } from "#tracing/eve/agent-trace-state.js";
4
5
  import type { createEveCapturePolicy } from "#tracing/eve/policy.js";
5
6
  import type { ConversationEnvironment } from "#shared/conversation-context.js";
6
- import type { AgentSpanIdGenerator, AgentRun, ExecutionContext, TurnOperation } from "#compiled/@vercel/agent-runs/index.js";
7
+ import type { AgentSpanIdGenerator, AgentRun, TurnOperation } from "#compiled/@vercel/agent-runs/index.js";
7
8
  interface EveSessionTracingInput {
8
9
  readonly tracing: AgentRun;
9
10
  readonly idGenerator: AgentSpanIdGenerator;
@@ -19,7 +20,7 @@ interface EveSessionTracing {
19
20
  readonly prepareSessionTrace: (event: InstrumentationSessionStartedEvent) => Promise<InstrumentationTraceSeed>;
20
21
  readonly prepareTurnTrace: (event: InstrumentationTurnStartedEvent) => Promise<InstrumentationTraceSeed>;
21
22
  /** Hydrates a turn this process or an earlier one started. */
22
- turnFor(sessionId: string, turnId: string, context?: ExecutionContext): Promise<TurnOperation | undefined>;
23
+ turnFor(sessionId: string, turnId: string, context?: Context): Promise<TurnOperation | undefined>;
23
24
  /** Whether the trace policy dropped this turn, so its work must not record spans. */
24
25
  dropped(sessionId: string, turnId: string): Promise<boolean>;
25
26
  turnTerminal(event: InstrumentationTurnTerminalEvent): Promise<void>;
@@ -1 +1 @@
1
- import{normalizeChannelAudience}from"#shared/channel-audience.js";import{normalizeInstrumentationChannelKind}from"#internal/instrumentation.js";import{withOperationConversation}from"#tracing/eve/conversation-context.js";import{isSampledTrace,resolveTracePolicy,resolveTracePolicyDecision}from"#shared/trace-policy.js";import{ROOT_CONTEXT}from"#compiled/@opentelemetry/api/index.js";import"#instrumentation/lifecycle.js";import{readInstrumentationDecision}from"#shared/instrumentation-decision.js";import{applyPrincipalTraceDecision}from"#instrumentation/principal-summary.js";import{withChannelAudience}from"#tracing/eve/channel-audience-context.js";import{eveTurnIdentity,traceSessionIdOf}from"#tracing/eve/operation-input.js";import{eveActivationMetadata}from"#tracing/eve/metadata.js";function createEveSessionTracing(e){let ensureSessionContext=async t=>{let n=await e.stateStore.get(`session`,t.sessionId);if(n===void 0){let r=normalizeChannelAudience(t.channelAudience),i=resolveSessionTraceDecision(t,r,e.environment,e.tracePolicy);n={agentName:t.agentName,channelAudience:r,channelKind:t.channelKind,channelType:t.channelType,decision:i,context:initialSessionContext(e,t,i),parentLineage:t.parentLineage,rootSessionId:t.rootSessionId,traceSessionId:traceSessionIdOf(t),scheduleId:t.scheduleId,title:t.title},await e.stateStore.set(`session`,t.sessionId,n)}return n},prepareSessionTrace=async e=>{let t=await ensureSessionContext(e);return portableSpanContext(t.context,t.decision)},turnKey=(e,t)=>JSON.stringify([e,t]);async function turnFor(t,n,r){let i=await e.stateStore.get(`turn`,turnKey(t,n));if(i===void 0||!isSampledTrace(i.context))return;let a=await e.stateStore.get(`session`,t);return e.tracing.resume({identity:eveTurnIdentity({sessionId:t,rootSessionId:i.rootSessionId,turnId:n}),context:r??hostContext(a?.channelAudience,{sessionId:t,...i})})}async function dropped(t,n){let r=await e.stateStore.get(`turn`,turnKey(t,n));return r!==void 0&&!isSampledTrace(r.context)}let prepareTurnTrace=async t=>{let n=await e.stateStore.get(`turn`,turnKey(t.sessionId,t.turnId));if(n!==void 0){let r=await e.stateStore.get(`session`,t.sessionId);return portableSpanContext(n.context,r?.decision)}let r=await ensureSessionContext(t),i=t.sequence===0,a=i?t.parentTraceContext:void 0,o=r.decision?.action===`record`,s=a!==void 0&&!(`isRemote`in a&&a.isRemote===!0),c=i?{...r.context,traceId:s?a.traceId:r.context.traceId,isRemote:!1}:{traceId:e.idGenerator.deriveTraceId(`turn:${t.idempotencyKey}`),spanId:e.idGenerator.deriveSpanId(`turn:${t.idempotencyKey}`),traceFlags:+!!o,isRemote:!1},l=r.agentName??(t.parentLineage??r.parentLineage)?.subagentName,u={agentName:l,caller:a===void 0?void 0:adoptedSpanContext(a),context:c,currentPrincipal:applyPrincipalTraceDecision(t.currentPrincipal,r.decision),initiatorPrincipal:applyPrincipalTraceDecision(t.initiatorPrincipal,r.decision),parentLineage:t.parentLineage??r.parentLineage,rootSessionId:t.rootSessionId,traceSessionId:traceSessionIdOf(t),sequence:t.sequence,startTimeMs:Date.now(),subagentName:(t.parentLineage??r.parentLineage)?.subagentName};if(isSampledTrace(c)){let n=await e.tracing.turn({...eveActivationMetadata({session:r,turn:u,sessionId:t.sessionId}),agentName:l,identity:eveTurnIdentity({...t,sessionId:t.sessionId}),framework:{name:`eve`,version:e.frameworkVersion},capture:{emit:!0,...await e.capturePolicy.forOperation(t)},reference:c,parent:s?adoptedSpanContext(a):void 0,links:activationLinks(u),startTimeMs:u.startTimeMs,context:hostContext(r.channelAudience,t)});u={...u,context:{...c,traceFlags:n.reference.traceFlags}}}return await e.stateStore.set(`turn`,turnKey(t.sessionId,t.turnId),u),portableSpanContext(u.context,r.decision)};async function recordTerminal(t,n,r,i){await e.stateStore.update(`turn`,turnKey(t,n),e=>({...e,terminal:r.outcome===`failed`?{outcome:`failed`,errorName:i instanceof Error?i.name:void 0,errorMessage:i instanceof Error?i.message:void 0}:r}))}return{ensureSessionContext,prepareSessionTrace,prepareTurnTrace,turnFor,dropped,async turnTerminal(e){await recordTerminal(e.sessionId,e.turnId,{outcome:e.type===`turn.failed`?`failed`:e.type===`turn.cancelled`?`cancelled`:`completed`},e.type===`turn.failed`?e.error:void 0)},async sessionTransition(t){if(t.turnId===void 0)return;t.type===`session.failed`&&await recordTerminal(t.sessionId,t.turnId,{outcome:`failed`},t.error);let n=await e.stateStore.get(`turn`,turnKey(t.sessionId,t.turnId));if(n===void 0)return;let r=await e.stateStore.get(`session`,t.sessionId),i=await turnFor(t.sessionId,t.turnId);if(i!==void 0){let e=eveActivationMetadata({session:r,turn:n,sessionId:t.sessionId});i.attributes(e.attributes??{}),i.links(activationLinks(n)??[]);let a=n.terminal;if(a===void 0)await i.complete({outcomeUnknown:!0});else if(a.outcome===`failed`){let e=Error(a.errorMessage);e.name=a.errorName??`Error`,await i.complete({outcome:`failed`,failed:!0,error:e,errorType:a.errorName})}else await i.complete({outcome:a.outcome})}await e.stateStore.delete(`turn`,turnKey(t.sessionId,t.turnId))}}}function hostContext(e,t){return withOperationConversation(withChannelAudience(ROOT_CONTEXT,e),t)}function activationLinks(e){let t=[];return e.caller?.isRemote===!0&&t.push({context:e.caller,relationship:`agent.dispatch`}),e.channelDelivery?.requestTraceContext!==void 0&&t.push({context:e.channelDelivery.requestTraceContext,relationship:`channel.request`}),t.length===0?void 0:t}function portableSpanContext(e,t){return{decision:t,spanId:e.spanId,traceFlags:e.traceFlags,traceId:e.traceId}}function adoptedSpanContext(e){return{isRemote:`isRemote`in e&&e.isRemote===!0,spanId:e.spanId,traceFlags:e.traceFlags,traceId:e.traceId}}function initialSessionContext(e,t,n){let r=t.traceSeed;if(r!==void 0)return{...adoptedSpanContext(r),traceFlags:n.action===`drop`?0:r.traceFlags};let i=`session:${t.sessionId}`,a=t.parentTraceContext;return{traceId:a!==void 0&&!(`isRemote`in a&&a.isRemote===!0)?a.traceId:e.idGenerator.deriveTraceId(i),spanId:e.idGenerator.deriveSpanId(i),traceFlags:+(n.action===`record`)}}function resolveSessionTraceDecision(e,t,n,r){let i={audience:t,environment:n};return e.parentTraceContext!==void 0&&!isSampledTrace(e.parentTraceContext)?{action:`drop`}:e.traceSeed?.decision===void 0?e.traceSeed===void 0?e.parentTraceContext===void 0?e.agentName===void 0?r===void 0?resolveTracePolicyDecision(!0,i):{action:`drop`}:resolveTracePolicy(r,{agentName:e.agentName,audience:t,channel:{kind:normalizeInstrumentationChannelKind(e.channelKind??e.channelType)},environment:n,principalType:`unknown`}):resolveTracePolicyDecision(isSampledTrace(e.parentTraceContext),i):resolveTracePolicyDecision(isSampledTrace(e.traceSeed),i):readInstrumentationDecision(e.traceSeed.decision)??{action:`drop`}}export{createEveSessionTracing};
1
+ import{normalizeChannelAudience}from"#shared/channel-audience.js";import{normalizeInstrumentationChannelKind}from"#internal/instrumentation.js";import{traceSessionIdOf,withOperationTraceContext}from"#tracing/eve/conversation-context.js";import{isSampledTrace,resolveTracePolicy,resolveTracePolicyDecision}from"#shared/trace-policy.js";import{ROOT_CONTEXT}from"#compiled/@opentelemetry/api/index.js";import"#instrumentation/lifecycle.js";import{readInstrumentationDecision}from"#shared/instrumentation-decision.js";import{applyPrincipalTraceDecision}from"#instrumentation/principal-summary.js";import{withChannelAudience}from"#tracing/eve/channel-audience-context.js";import{eveTurnIdentity}from"#tracing/eve/operation-input.js";import{eveActivationMetadata}from"#tracing/eve/metadata.js";function createEveSessionTracing(e){let ensureSessionContext=async t=>{let n=await e.stateStore.get(`session`,t.sessionId);if(n===void 0){let r=normalizeChannelAudience(t.channelAudience),i=resolveSessionTraceDecision(t,r,e.environment,e.tracePolicy);n={agentName:t.agentName,channelAudience:r,channelKind:t.channelKind,channelType:t.channelType,decision:i,context:initialSessionContext(e,t,i),parentLineage:t.parentLineage,rootSessionId:t.rootSessionId,traceSessionId:traceSessionIdOf(t),scheduleId:t.scheduleId,title:t.title},await e.stateStore.set(`session`,t.sessionId,n)}return n},prepareSessionTrace=async e=>{let t=await ensureSessionContext(e);return portableSpanContext(t.context,t.decision)},turnKey=(e,t)=>JSON.stringify([e,t]);async function turnFor(t,n,r){let i=await e.stateStore.get(`turn`,turnKey(t,n));if(i===void 0||!isSampledTrace(i.context))return;let a=await e.stateStore.get(`session`,t);return e.tracing.resume({identity:eveTurnIdentity({sessionId:t,rootSessionId:i.rootSessionId,turnId:n}),context:withOperationTraceContext(r??withChannelAudience(ROOT_CONTEXT,a?.channelAudience),{sessionId:t,...i})})}async function dropped(t,n){let r=await e.stateStore.get(`turn`,turnKey(t,n));return r!==void 0&&!isSampledTrace(r.context)}let prepareTurnTrace=async t=>{let n=await e.stateStore.get(`turn`,turnKey(t.sessionId,t.turnId));if(n!==void 0){let r=await e.stateStore.get(`session`,t.sessionId);return portableSpanContext(n.context,r?.decision)}let r=await ensureSessionContext(t),i=t.sequence===0,a=i?t.parentTraceContext:void 0,o=r.decision?.action===`record`,s=a!==void 0&&!(`isRemote`in a&&a.isRemote===!0),c=i?{...r.context,traceId:s?a.traceId:r.context.traceId,isRemote:!1}:{traceId:e.idGenerator.deriveTraceId(`turn:${t.idempotencyKey}`),spanId:e.idGenerator.deriveSpanId(`turn:${t.idempotencyKey}`),traceFlags:+!!o,isRemote:!1},l=r.agentName??(t.parentLineage??r.parentLineage)?.subagentName,u={agentName:l,caller:a===void 0?void 0:adoptedSpanContext(a),context:c,currentPrincipal:applyPrincipalTraceDecision(t.currentPrincipal,r.decision),initiatorPrincipal:applyPrincipalTraceDecision(t.initiatorPrincipal,r.decision),parentLineage:t.parentLineage??r.parentLineage,rootSessionId:t.rootSessionId,traceSessionId:traceSessionIdOf(t),sequence:t.sequence,startTimeMs:Date.now(),subagentName:(t.parentLineage??r.parentLineage)?.subagentName};if(isSampledTrace(c)){let n=await e.tracing.turn({...eveActivationMetadata({session:r,turn:u,sessionId:t.sessionId}),agentName:l,identity:eveTurnIdentity({...t,sessionId:t.sessionId}),framework:{name:`eve`,version:e.frameworkVersion},capture:{emit:!0,...await e.capturePolicy.forOperation(t)},reference:c,parent:s?adoptedSpanContext(a):void 0,links:activationLinks(u),startTimeMs:u.startTimeMs,context:hostContext(r.channelAudience,t)});u={...u,context:{...c,traceFlags:n.reference.traceFlags}}}return await e.stateStore.set(`turn`,turnKey(t.sessionId,t.turnId),u),portableSpanContext(u.context,r.decision)};async function recordTerminal(t,n,r,i){await e.stateStore.update(`turn`,turnKey(t,n),e=>({...e,terminal:r.outcome===`failed`?{outcome:`failed`,errorName:i instanceof Error?i.name:void 0,errorMessage:i instanceof Error?i.message:void 0}:r}))}return{ensureSessionContext,prepareSessionTrace,prepareTurnTrace,turnFor,dropped,async turnTerminal(e){await recordTerminal(e.sessionId,e.turnId,{outcome:e.type===`turn.failed`?`failed`:e.type===`turn.cancelled`?`cancelled`:`completed`},e.type===`turn.failed`?e.error:void 0)},async sessionTransition(t){if(t.turnId===void 0)return;t.type===`session.failed`&&await recordTerminal(t.sessionId,t.turnId,{outcome:`failed`},t.error);let n=await e.stateStore.get(`turn`,turnKey(t.sessionId,t.turnId));if(n===void 0)return;let r=await e.stateStore.get(`session`,t.sessionId),i=await turnFor(t.sessionId,t.turnId);if(i!==void 0){let e=eveActivationMetadata({session:r,turn:n,sessionId:t.sessionId});i.attributes(e.attributes??{}),i.links(activationLinks(n)??[]);let a=n.terminal;if(a===void 0)await i.complete({outcomeUnknown:!0});else if(a.outcome===`failed`){let e=Error(a.errorMessage);e.name=a.errorName??`Error`,await i.complete({outcome:`failed`,failed:!0,error:e,errorType:a.errorName})}else await i.complete({outcome:a.outcome})}await e.stateStore.delete(`turn`,turnKey(t.sessionId,t.turnId))}}}function hostContext(e,t){return withOperationTraceContext(withChannelAudience(ROOT_CONTEXT,e),t)}function activationLinks(e){let t=[];return e.caller?.isRemote===!0&&t.push({context:e.caller,relationship:`agent.dispatch`}),e.channelDelivery?.requestTraceContext!==void 0&&t.push({context:e.channelDelivery.requestTraceContext,relationship:`channel.request`}),t.length===0?void 0:t}function portableSpanContext(e,t){return{decision:t,spanId:e.spanId,traceFlags:e.traceFlags,traceId:e.traceId}}function adoptedSpanContext(e){return{isRemote:`isRemote`in e&&e.isRemote===!0,spanId:e.spanId,traceFlags:e.traceFlags,traceId:e.traceId}}function initialSessionContext(e,t,n){let r=t.traceSeed;if(r!==void 0)return{...adoptedSpanContext(r),traceFlags:n.action===`drop`?0:r.traceFlags};let i=`session:${t.sessionId}`,a=t.parentTraceContext;return{traceId:a!==void 0&&!(`isRemote`in a&&a.isRemote===!0)?a.traceId:e.idGenerator.deriveTraceId(i),spanId:e.idGenerator.deriveSpanId(i),traceFlags:+(n.action===`record`)}}function resolveSessionTraceDecision(e,t,n,r){let i={audience:t,environment:n};return e.parentTraceContext!==void 0&&!isSampledTrace(e.parentTraceContext)?{action:`drop`}:e.traceSeed?.decision===void 0?e.traceSeed===void 0?e.parentTraceContext===void 0?e.agentName===void 0?r===void 0?resolveTracePolicyDecision(!0,i):{action:`drop`}:resolveTracePolicy(r,{agentName:e.agentName,audience:t,channel:{kind:normalizeInstrumentationChannelKind(e.channelKind??e.channelType)},environment:n,principalType:`unknown`}):resolveTracePolicyDecision(isSampledTrace(e.parentTraceContext),i):resolveTracePolicyDecision(isSampledTrace(e.traceSeed),i):readInstrumentationDecision(e.traceSeed.decision)??{action:`drop`}}export{createEveSessionTracing};
@@ -1,4 +1,4 @@
1
- import { a as conversationProjection, i as openConversationInputs, n as conversationReducer, o as callStatus, r as defaultMessageReducer, t as useEveAgent } from "../chunks/use-eve-agent-Bp6nbhfV.js";
1
+ import { a as conversationProjection, i as openConversationInputs, n as conversationReducer, o as callStatus, r as defaultMessageReducer, t as useEveAgent } from "../chunks/use-eve-agent-DTu78IAF.js";
2
2
 
3
3
  //#region src/client/tool-call-state.ts
4
4
  function toolCallState(conversation, callId, options = {}) {
@@ -1,3 +1,3 @@
1
- import { t as useEveAgent } from "../chunks/use-eve-agent-Bp6nbhfV.js";
1
+ import { t as useEveAgent } from "../chunks/use-eve-agent-DTu78IAF.js";
2
2
 
3
3
  export { useEveAgent };
@@ -3,7 +3,7 @@ title: "Agent Configuration"
3
3
  description: "Configure an eve agent's model, reasoning effort, compaction, limits, and runtime behavior in agent.ts."
4
4
  ---
5
5
 
6
- An eve app has one root agent assembled from the files under `agent/`. Its optional `agent.ts` calls `defineAgent` (from `eve`) when you need to configure the model or other runtime behavior. Declared [subagents](./subagents) have their own `agent.ts` and capabilities; this page covers the configuration shared by root agents and subagents.
6
+ An eve app's root agent uses files under `agent/` by default; a [flat layout](./reference/agent-files#flat-layout) places them directly in the app root instead. Its optional `agent.ts` calls `defineAgent` (from `eve`) when you need to configure the model or other runtime behavior. Declared [subagents](./subagents) have their own `agent.ts` and capabilities; this page covers the configuration shared by root agents and subagents.
7
7
 
8
8
  ## Set the model
9
9
 
@@ -137,7 +137,7 @@ export default defineAgent({
137
137
  starting points on Ollama.
138
138
  - **Usage.** `includeUsage: true` lets token usage reach eve's
139
139
  [session limits](#runtime-limits). Local models report no cost, so
140
- `maxTokenCostUsdPerSession` does not apply.
140
+ `costUsd` stays unset in a `sessionUsage` check.
141
141
  - **Other servers.** Change `baseURL`, for example to
142
142
  `http://localhost:1234/v1` for LM Studio. Pass `apiKey` for a remote
143
143
  OpenAI-compatible server that requires one.
@@ -262,45 +262,88 @@ See [Default harness](./concepts/default-harness#compaction) for how the loop ap
262
262
 
263
263
  ## Runtime limits
264
264
 
265
- Use `limits` for framework-owned runtime caps. Session usage limits stop the
266
- current durable session from starting another model call after accumulated
267
- provider-reported tokens or model token cost reaches a configured limit:
265
+ Use `limits` for framework-owned runtime caps. `sessionUsage` decides when the
266
+ current durable session must stop starting model calls. It receives the
267
+ session's usage and returns `true` when the limit is reached:
268
268
 
269
269
  ```ts title="agent/agent.ts"
270
270
  export default defineAgent({
271
271
  model: "anthropic/claude-opus-5.5",
272
272
  limits: {
273
- maxInputTokensPerSession: 200_000,
274
- maxOutputTokensPerSession: 20_000,
275
- maxTokenCostUsdPerSession: 1.5,
273
+ sessionUsage: ({ window }) =>
274
+ window.inputTokens - window.cacheReadTokens >= 200_000 ||
275
+ window.outputTokens >= 20_000 ||
276
+ (window.costUsd ?? 0) >= 1.5,
276
277
  sessionTimeoutMs: 7 * 24 * 60 * 60 * 1_000,
277
278
  },
278
279
  });
279
280
  ```
280
281
 
281
- `sessionTimeoutMs` sets the lifetime for every session, including delegated
282
- sessions. It defaults to 30 days and starts at creation. Each successful
283
- deployment handoff or legacy-session import restarts the original configured
284
- duration. Process restarts, ordinary messages, compaction handoffs, and failed
285
- or skipped handoffs keep the existing deadline. At the deadline, eve lets an active turn settle,
286
- then emits `session.completed` and releases every continuation address; the next
287
- qualifying channel message starts fresh. Set it to `false` to disable the
288
- timeout. Session expiration follows [run-data retention](#run-data-retention);
289
- a zero-retention session loses its stored payloads when it ends.
290
-
291
- Input tokens, output tokens, and model token cost are checked independently.
292
- The model call that crosses a limit is allowed to finish because exact usage
293
- arrives after the call completes. Before the next model call, eve pauses the
294
- turn (`turn.waiting`) and sends a deterministic continuation prompt with two options:
295
- **Continue** grants a fresh window of each configured size and resumes the same
296
- turn, and **Stop**
297
- cancels the in-flight turn through the standard cancellation path
298
- (`turn.cancelled` → `session.waiting`) — a user decision, not an error. The session stays resumable; because it is
299
- still over budget after Stop, the next message raises a new prompt. Declining a
282
+ `sessionTimeoutMs` sets how long a session may sit idle before eve completes it,
283
+ for every session, including delegated sessions. It defaults to 30 days. The
284
+ idle window starts at creation and restarts each time a turn settles, including
285
+ turns that answer a message, clear or compact the context, or end in
286
+ cancellation. A session never expires while a turn is open, including a turn
287
+ held open while its [tasks](./tools/tasks) work or while it waits for a person
288
+ to answer; the window restarts when that turn settles. Process restarts do not
289
+ change the window. When the window elapses, eve emits `session.completed` and
290
+ releases every continuation address; the next qualifying channel message starts
291
+ fresh. To carry an earlier conversation into the fresh session, pass it as
292
+ [prior history](./channels/eve#start-from-prior-history). Set it to `false` to
293
+ disable the timeout. Session expiration follows
294
+ [run-data retention](#run-data-retention); a zero-retention session loses its
295
+ stored payloads when it ends.
296
+
297
+ `sessionUsage` gets two usage records with `inputTokens`, `outputTokens`,
298
+ `cacheReadTokens`, `cacheWriteTokens`, and `costUsd`: `total` is everything
299
+ the session has spent, and `window` is what it spent since the last approved
300
+ continuation. `inputTokens` includes cache reads and writes. Subtract
301
+ `cacheReadTokens` to count only new input; cache reads are the history a
302
+ provider replays from its prompt cache on every step. `costUsd` is the model
303
+ token cost in US dollars that AI Gateway reports with each step, not tool or
304
+ infrastructure spend; it is unset when no step reported a cost.
305
+
306
+ When `sessionUsage` is omitted, the limit is `40_000_000` new input tokens per
307
+ window:
308
+
309
+ ```ts
310
+ ({ window }) => window.inputTokens - window.cacheReadTokens >= 40_000_000;
311
+ ```
312
+
313
+ `sessionUsage` can raise its threshold after each approval. This limit asks
314
+ at 20,000 new input tokens, then at 40,000, 80,000, and so on:
315
+
316
+ ```ts title="agent/agent.ts"
317
+ export default defineAgent({
318
+ model: "anthropic/claude-opus-5.5",
319
+ limits: {
320
+ sessionUsage: ({ total, window }) => {
321
+ const used = total.inputTokens - total.cacheReadTokens;
322
+ // Usage when the last continuation was approved; 0 before the first.
323
+ const approvedAt = used - (window.inputTokens - window.cacheReadTokens);
324
+ // Double past it, so each approval allows twice the usage before the next prompt.
325
+ let next = 20_000;
326
+ while (next <= approvedAt) next *= 2;
327
+ return used >= next;
328
+ },
329
+ },
330
+ });
331
+ ```
332
+
333
+ Set `sessionUsage: () => false` to leave sessions uncapped; `sessionUsage:
334
+ false` is not accepted. eve calls `sessionUsage` before each model call once
335
+ the window has usage. The model call that crosses a limit is allowed to finish
336
+ because exact usage arrives after the call completes. Before the next model
337
+ call, eve pauses the turn (`turn.waiting`) and sends a deterministic
338
+ continuation prompt with two options: **Continue** starts a new window and
339
+ resumes the same turn, and **Stop** cancels the in-flight turn through the
340
+ standard cancellation path (`turn.cancelled` → `session.waiting`). Stop is a
341
+ user decision, not an error. The session stays resumable; because it is still
342
+ over budget after Stop, the next message raises a new prompt. Declining a
300
343
  delegated child's prompt cancels the root turn, which cascades to the whole
301
- delegation tree — the delegating parent never receives an error result it
302
- could retry against a fresh quota share. A reply that answers neither option
303
- is queued while the existing prompt stays pending; eve does not raise another
344
+ delegation tree, so the delegating parent never receives an error result it
345
+ could retry. A reply that answers neither option is queued while the existing
346
+ prompt stays pending; eve does not raise another
304
347
  copy or start another turn. The reply is received (`message.received`) and
305
348
  processed in the held turn once the budget is granted.
306
349
 
@@ -312,44 +355,22 @@ turn or duplicate the prompt.
312
355
 
313
356
  Sessions that cannot request input from a human, such as markdown schedules and
314
357
  delegated runs without input proxying, skip the prompt and fail the next model
315
- call with `SESSION_TOKEN_LIMIT_REACHED` for token budgets or
316
- `SESSION_TOKEN_COST_LIMIT_REACHED` for model token cost. A delegated task with
317
- no inherited quota also fails instead of raising a continuation prompt that
318
- could only grant another zero-value window.
319
-
320
- When `maxInputTokensPerSession` is omitted, root sessions apply a default
321
- input budget of `40_000_000` provider-reported input tokens.
322
- `maxOutputTokensPerSession` and `maxTokenCostUsdPerSession` are unset by
323
- default. `maxTokenCostUsdPerSession` is a US-dollar limit on model token cost,
324
- not tool or infrastructure spend. It uses the cost reported with each model
325
- step; AI Gateway supplies this value, while model steps without reported cost
326
- do not add to the limit. Set any usage limit to `false` to uncap that axis.
327
-
328
- Delegated subagent sessions have no fixed default. Each child receives a share
329
- of the delegating parent's remaining quota when it starts: the remainder in
330
- the current budget window split evenly across the agent tasks that one model
331
- step starts. A session that a workflow tool opens with `ctx.agent` receives
332
- the share of the model step that called the tool, or the whole remainder when
333
- that step starts no agent tasks; eve does not divide that share among several
334
- sessions one call opens. A child keeps its grant for its whole session,
335
- including turns that later calls with `taskId` start. Remote agent tasks count
336
- toward the split but receive no grant: they run under their own deployment's
337
- limits.
338
-
339
- A child's usage, including what the child's own subagents spent, counts
340
- against the parent's quota. An agent task's usage counts with each reply it
358
+ call with `SESSION_USAGE_LIMIT_REACHED`. Its details carry the `total` and
359
+ `window` usage the check saw.
360
+
361
+ Each subagent session checks its own usage against its own `sessionUsage`, or
362
+ the root agent's when it authors none. A dynamic subagent can't select
363
+ `sessionUsage` at runtime and always uses the root agent's. Remote agents run
364
+ under their own deployment's limits.
365
+
366
+ A child's usage, including what the child's own subagents spent, also counts
367
+ in the parent's usage. An agent task's usage counts with each reply it
341
368
  sends. A turn it doesn't reply to, such as one a cancel stopped, counts with
342
369
  the next reply, or when the turn ends if no call waits for a reply. Sessions
343
370
  that any other `serve` workflow tool opens with `ctx.agent` count the same
344
371
  way; those of an `execute` or `task` tool count when the tool finishes. Remote
345
- agents' reported usage counts the same way. Later children draw from what
346
- remains, and the parent's own limit and continuation prompt include delegated
347
- spend. Token-cost budgets follow the same rules, including splitting the
348
- remaining US-dollar budget and adding child cost back to the parent. Approving
349
- a continuation opens a fresh parent window for later child grants without
350
- erasing lifetime usage. An authored child limit applies only when it is
351
- tighter than the parent's grant; an uncapped parent delegates uncapped
352
- children.
372
+ agents' reported usage counts the same way, cost included. Approving a
373
+ continuation starts a new window without erasing `total`.
353
374
 
354
375
  Some delegated usage doesn't count against the parent: a `ctx.agent` turn
355
376
  still running when its workflow tool finishes or is cancelled; the `ctx.agent`
@@ -496,7 +517,7 @@ keeps the data. Confirm support with your World provider. See
496
517
  | -------------- | ------------------------------------- | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
497
518
  | `reasoning` | `AgentReasoningDefinition` | provider default | Provider-agnostic reasoning effort forwarded to the agent's turn model calls. |
498
519
  | `modelOptions` | `AgentModelOptionsDefinition` | none | Provider option overrides forwarded to the model call, and [`promptCache`](#prompt-caching) settings. |
499
- | `limits` | `AgentLimitsDefinition` | field-specific | Framework-owned runtime limits. Sessions complete after 30 days by default; usage-limit defaults and inheritance are described above. Set a limit to `false` to disable it. |
520
+ | `limits` | `AgentLimitsDefinition` | field-specific | Framework-owned runtime limits. Sessions complete after 30 idle days by default; usage-limit defaults and inheritance are described above. Set a limit to `false` to disable it. |
500
521
  | `experimental` | `AgentExperimentalDefinition` | unset | Unstable opt-ins. `workflow.world` selects the Workflow world package on the root agent; `workflow.modelCallsPerStep` batches sequential model calls into a wider replay unit; `workflow.retention` controls how long the durable runtime keeps run data. |
501
522
  | `build` | `{ externalDependencies?: string[] }` | none | Hosted-build packaging controls. `externalDependencies` keeps listed packages external while eve compiles authored modules such as tools and channels, and traces those packages into the hosted output. |
502
523
  | `tool` | `boolean \| "deferred"` | `true` | Exposes this agent to its parent model as a tool. `"deferred"` keeps it out of the model's tool list; the model finds it with `eve__search` and calls it with `eve__tool`. On the root agent, controls the built-in `agent` tool. A subagent with `tool: false` remains callable from authored workflow tools through `ctx.agent()`. |
@@ -53,6 +53,11 @@ export default channel;
53
53
 
54
54
  `adapters` is a map of adapter name to adapter instance; each entry mounts its own webhook (see below). `state` takes any Chat SDK state adapter: `createMemoryState()` is fine for local development, but use a durable adapter (Redis, Upstash, etc.) in production so thread subscriptions and inbound deduplication survive restarts. `send` accepts a plain string or an AI SDK `UserContent` array, and must be called from inside a Chat SDK handler — it dispatches the turn on the webhook that is currently running.
55
55
 
56
+ Pass `idempotencyKey: message.id` to `send` to prevent duplicate agent input
57
+ within the session's [recent-key window](./custom#retried-deliveries). Chat SDK's
58
+ separate duplicate check can mark a message as seen before eve accepts it, so
59
+ a shared state adapter alone does not guarantee delivery.
60
+
56
61
  Deploy once the channel file is in place:
57
62
 
58
63
  ```bash
@@ -104,7 +109,7 @@ bot.onNewMention(async (thread, message) => {
104
109
  });
105
110
  ```
106
111
 
107
- `options` accepts `thread` and `adapterName`, plus the channel send options `auth`, `context`, `outputSchema`, `title`, `callback`, and `turnPolicy`. `title` sets the eve session's display title without changing the model message; `auth` attaches an authenticated principal to the turn. `auth` defaults to `null`.
112
+ `options` accepts `thread` and `adapterName`, plus the channel send options `auth`, `context`, `outputSchema`, `title`, `callback`, `turnPolicy`, and `idempotencyKey`. `title` sets the eve session's display title without changing the model message; `auth` attaches an authenticated principal to the turn. `auth` defaults to `null`.
108
113
 
109
114
  To answer pending input requests from a handler you render yourself, call `respond(inputResponses, { thread, auth?, context? })`. Like a channel's `respond()`, it never creates a session. This example answers a custom button whose `value` carries the eve request id:
110
115
 
@@ -104,11 +104,11 @@ part of the authored channel API.
104
104
  ## Channel operations and session handles
105
105
 
106
106
  Channel operations are dynamic: every call targets whichever session currently
107
- owns the address. Only `send()` can create a session when the address is unowned.
108
- Cold-start sends return their accepted candidate without waiting for address
109
- ownership. If simultaneous sends race, eve forwards the losing candidate's
110
- message to the winner; resolve the address after startup when you need a fixed
111
- handle to the canonical owner.
107
+ owns the address. `create()` and `send()` can create a session when the address is unowned.
108
+ Without an [idempotency key](#retried-deliveries), a new session's handle can
109
+ return before it claims the address. If another send wins the address, eve
110
+ forwards the message to that session. Call `resolveSession(address)` after
111
+ startup to get the winning session's handle.
112
112
 
113
113
  ```ts
114
114
  const source = from(threadId);
@@ -206,6 +206,38 @@ Attaching does no lookup. The first operation reports whether the ID is active.
206
206
  Call `resolveSession(address)` only when you explicitly need to snapshot an
207
207
  address's current owner as a fixed handle.
208
208
 
209
+ ## Retried deliveries
210
+
211
+ After verifying a webhook, pass its stable event ID as `idempotencyKey`. Reuse the key
212
+ when retrying a failed or timed-out send:
213
+
214
+ ```ts
215
+ const session = await from(conversationId).send(message, {
216
+ auth,
217
+ idempotencyKey: providerEventId,
218
+ });
219
+ ```
220
+
221
+ Channel and fixed-session `send()` and `respond()` calls accept this option,
222
+ as does the Chat SDK bridge. Keys must contain 1–256 characters and identify one
223
+ delivery. Prefix IDs with the provider or event type if they can overlap.
224
+ Reusing a retained key ignores the new input, even if the message changed.
225
+
226
+ Each session remembers its last 1,024 distinct keys. Retries do not extend
227
+ retention and can run again after eviction. Aliases share this window; replay
228
+ and owner handoffs preserve it. Other sessions have separate windows, including
229
+ those created after reset, expiration, or replacement. Replicas must share the
230
+ same durable Workflow World.
231
+
232
+ A known duplicate does not interrupt generation, call `deliver`, or start a
233
+ turn. A keyed send that creates a session waits up to 30 seconds for the winning
234
+ session's handle. Sends to existing sessions return after eve stores the
235
+ delivery, without waiting for a turn or reporting whether it was a duplicate.
236
+
237
+ Await `send()` before acknowledging a webhook when the provider allows it.
238
+ Acknowledging sooner can lose work. This does not make tool calls, outbound
239
+ posts, or work done before `send()` exactly once.
240
+
209
241
  ## Wrap an existing channel's routes
210
242
 
211
243
  A channel value can be spread into a new object with replaced `routes`. eve keeps the channel's adapter, events, and build metadata (such as the Slack app manifest) on the spread copy, so `{ ...channel, routes }` compiles and runs like the original.
@@ -374,7 +406,7 @@ Before sending:
374
406
 
375
407
  - Verify the provider's signature and validate the payload, including size limits. Derive `event.source` from the verified sender, not an untrusted payload field.
376
408
  - Filter out events that should not reach the agent.
377
- - Deduplicate retried events in your application if duplicates would cause unwanted sessions or posts. `send(...)` does not deduplicate them.
409
+ - Deduplicate retries in your application unless the destination's `receive` hook passes a [delivery key](#retried-deliveries) to `from(address).send()`.
378
410
 
379
411
  The supplied `auth` identifies who started the session, available to tools and event handlers as `session.auth.initiator`.
380
412
 
@@ -368,6 +368,52 @@ export default eveChannel({
368
368
  - eve labels client-supplied entries `Client context:` for the model. Returned context is sent without the label.
369
369
  - `onMessage` runs only for requests with a message. An input response keeps the context its request sent.
370
370
 
371
+ ### Start from prior history
372
+
373
+ Pass `history` to bring in conversation eve did not produce, such as a transcript your app stored, a conversation moving from another system, or a branch of an earlier exchange. The model sees each entry as a real user or assistant turn, not as a transcript inside one message.
374
+
375
+ Create a session that starts from stored history and waits for its first message with `create()` on a channel address. No turn runs until a message arrives:
376
+
377
+ ```ts title="agent/channels/app.ts"
378
+ import { defineChannel, POST } from "eve/channels";
379
+
380
+ export default defineChannel({
381
+ routes: [
382
+ POST("/conversations/:id/session", async (req, { from, params }) => {
383
+ const auth = await authenticate(req);
384
+ // Load only conversations this caller may read.
385
+ const conversation = await db.conversations.findForUser(params.id!, auth);
386
+ const { created, session } = await from(`conversation:${conversation.id}`).create({
387
+ auth,
388
+ history: conversation.messages.map((message) => ({
389
+ id: message.id,
390
+ role: message.role, // "user" | "assistant"
391
+ text: message.body,
392
+ })),
393
+ });
394
+ if (!created) {
395
+ return Response.json({ error: "Conversation already has a session." }, { status: 409 });
396
+ }
397
+ return Response.json({ sessionId: session.id });
398
+ }),
399
+ ],
400
+ });
401
+ ```
402
+
403
+ The client then resumes that session by id, for example with `useEveAgent({ initialSession: { sessionId, streamIndex: 0 }, resume: true })`. `created` is `false` when a session already owned the address, or another `create()` or `send()` claimed it first. That session comes back unchanged and your `history` was not added, so check `created` before treating the session as seeded. Use a new address for each new conversation or branch.
404
+
405
+ When the session at the address is [stranded](../concepts/execution-model-and-durability#stranded-sessions), `create()` throws `SessionStrandedError` instead of replacing it, because that session may hold the conversation you meant to import. Call `reset()` on the address, then `create()` again.
406
+
407
+ `create()` returns once the new session claims its address, so a `send()` right after it reaches that session. It throws if no session claims the address within 15 seconds.
408
+
409
+ `send()` accepts the same `history` option. The entries are added right before that message and its `context`, whether the send creates the session or continues it. The eve channel's `onMessage` can return `history` the same way. It applies to every message it is returned for, so return it only when the message should carry those turns.
410
+
411
+ Each entry has a `role` of `"user"` or `"assistant"`, non-empty `text`, and an optional `id` that is unique within the call. Invalid history throws an `InvalidSessionHistoryError`, exported from `eve/channels`, that names the entry and the rule it broke. eve doesn't cap how many entries or how much text one call carries. Your route decides how much stored conversation to load, so trim long conversations there, for example to the newest messages. Tool calls, files, and reasoning are not supported.
412
+
413
+ eve never accepts `history` from a client request body. Resolve it on the server and authorize the caller against the stored conversation.
414
+
415
+ The stream publishes added entries in `history.imported`, right before the `message.received` of the turn they join. Each event message has the same `role`, `text`, and `id` you passed. `transcriptReducer()` from `eve/client` includes them, so its `{ role, text }` messages can be passed straight back as `history` to branch a session. The default client reducer renders them ahead of that turn's message with `metadata.imported` set and your `id` in `metadata.historyId`, so you can rejoin your own annotations. Message ids stay unique even when a later call reuses an `id`. After that, the entries are ordinary history: compaction, `clear()`, and handoffs treat them like any other turn.
416
+
371
417
  ## Clients
372
418
 
373
419
  The browser side of this API lives in the [Frontend](../guides/frontend/overview) docs, where `useEveAgent` drives the eve channel from React UI.