eve 0.53.1 → 0.54.2

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 (230) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/dist/src/channel/types.d.ts +2 -0
  3. package/dist/src/chunks/{use-eve-agent-BR8EpIOX.js → use-eve-agent-CxPlg0KL.js} +0 -1
  4. package/dist/src/chunks/{use-eve-agent-XnfjQt1Z.js → use-eve-agent-D-KQzzyW.js} +0 -1
  5. package/dist/src/cli/commands/trace-detail.js +1 -1
  6. package/dist/src/cli/commands/trace.d.ts +2 -2
  7. package/dist/src/cli/commands/trace.js +3 -3
  8. package/dist/src/cli/dev/tui/runner.js +1 -1
  9. package/dist/src/cli/dev/tui/tool-presentation.js +1 -1
  10. package/dist/src/cli/dev/tui/traces/trace-content.d.ts +1 -3
  11. package/dist/src/cli/dev/tui/traces/trace-content.js +2 -2
  12. package/dist/src/cli/dev/tui/traces/trace-conversation.d.ts +5 -5
  13. package/dist/src/cli/dev/tui/traces/trace-conversation.js +1 -1
  14. package/dist/src/cli/dev/tui/traces/trace-view.js +1 -1
  15. package/dist/src/cli/dev/tui/traces/trace-viewer-session.js +1 -1
  16. package/dist/src/client/agent-info-schema.d.ts +0 -1
  17. package/dist/src/client/agent-info-schema.js +1 -1
  18. package/dist/src/compiled/.vendor-stamp.json +1 -1
  19. package/dist/src/compiled/@opentelemetry/api/index.d.ts +1 -0
  20. package/dist/src/compiler/default-tool-policy.js +1 -1
  21. package/dist/src/compiler/extension-compatibility.d.ts +4 -4
  22. package/dist/src/compiler/extension-compatibility.js +1 -1
  23. package/dist/src/compiler/manifest.js +1 -1
  24. package/dist/src/context/dynamic-instruction-lifecycle.d.ts +2 -1
  25. package/dist/src/context/dynamic-instruction-lifecycle.js +1 -1
  26. package/dist/src/context/keys.d.ts +3 -1
  27. package/dist/src/context/keys.js +1 -1
  28. package/dist/src/context/memory-event-lifecycle.d.ts +2 -0
  29. package/dist/src/context/memory-event-lifecycle.js +1 -1
  30. package/dist/src/context/memory-lifecycle.d.ts +5 -0
  31. package/dist/src/context/memory-lifecycle.js +1 -1
  32. package/dist/src/eve-channel/index.js +1 -1
  33. package/dist/src/execution/cancelled-model-call-batch.js +1 -1
  34. package/dist/src/execution/cancelled-turn-message.js +1 -1
  35. package/dist/src/execution/compaction.d.ts +2 -2
  36. package/dist/src/execution/coordination-dispatch-shared.d.ts +0 -1
  37. package/dist/src/execution/coordination-dispatch-shared.js +1 -1
  38. package/dist/src/execution/coordination-dispatch-step.js +1 -1
  39. package/dist/src/execution/create-session-step.js +1 -1
  40. package/dist/src/execution/durable-session-store.d.ts +2 -2
  41. package/dist/src/execution/eve-workflow-attributes.d.ts +3 -3
  42. package/dist/src/execution/next-driver-action.d.ts +2 -0
  43. package/dist/src/execution/parked-delivery-wait.js +1 -1
  44. package/dist/src/execution/route-child-delivery.js +1 -1
  45. package/dist/src/execution/runtime-context.js +1 -1
  46. package/dist/src/execution/session.d.ts +0 -2
  47. package/dist/src/execution/session.js +2 -2
  48. package/dist/src/execution/tasks/parent/dispatch.d.ts +1 -12
  49. package/dist/src/execution/tasks/parent/dispatch.js +1 -1
  50. package/dist/src/execution/tasks/parent/hitl-proxy-steps.d.ts +5 -1
  51. package/dist/src/execution/tasks/parent/hitl-proxy-steps.js +1 -1
  52. package/dist/src/execution/tasks/parent/tool-execution.js +1 -1
  53. package/dist/src/execution/tools/sleep-workflow.js +1 -1
  54. package/dist/src/execution/tools/subagent/invoke-agent.d.ts +1 -2
  55. package/dist/src/execution/tools/subagent/invoke-agent.js +1 -1
  56. package/dist/src/execution/tools/subagent/invoke-step.d.ts +4 -0
  57. package/dist/src/execution/tools/subagent/invoke-step.js +1 -1
  58. package/dist/src/execution/tools/subagent/start.d.ts +2 -2
  59. package/dist/src/execution/tools/subagent/start.js +1 -1
  60. package/dist/src/execution/tools/subagent/task-agent-requests.js +1 -1
  61. package/dist/src/execution/tools/tasks.d.ts +1 -8
  62. package/dist/src/execution/tools/tasks.js +1 -1
  63. package/dist/src/execution/tools/todo.d.ts +2 -2
  64. package/dist/src/execution/tools/todo.js +2 -2
  65. package/dist/src/execution/turn-workflow.js +1 -1
  66. package/dist/src/execution/workflow-runtime.js +1 -1
  67. package/dist/src/execution/workflow-steps.js +1 -1
  68. package/dist/src/framework/sources/registry.js +1 -1
  69. package/dist/src/harness/compaction.js +1 -1
  70. package/dist/src/harness/coordination.js +1 -1
  71. package/dist/src/harness/current-messages.d.ts +7 -6
  72. package/dist/src/harness/current-messages.js +1 -1
  73. package/dist/src/harness/emission.js +1 -1
  74. package/dist/src/harness/execute-tool.d.ts +2 -4
  75. package/dist/src/harness/messages.d.ts +36 -0
  76. package/dist/src/harness/messages.js +1 -1
  77. package/dist/src/harness/model-call-error.d.ts +5 -0
  78. package/dist/src/harness/model-call-error.js +1 -1
  79. package/dist/src/harness/semantic-errors/rules/model-provider.js +1 -1
  80. package/dist/src/harness/session-limit-enforcement.d.ts +2 -15
  81. package/dist/src/harness/step-hooks.d.ts +2 -1
  82. package/dist/src/harness/step-hooks.js +1 -1
  83. package/dist/src/harness/tool-loop.js +2 -2
  84. package/dist/src/harness/types.d.ts +6 -4
  85. package/dist/src/instrumentation/ai-sdk-hook-bridge.js +1 -1
  86. package/dist/src/instrumentation/background-task-runtime.d.ts +18 -0
  87. package/dist/src/instrumentation/background-task-runtime.js +1 -0
  88. package/dist/src/instrumentation/channel-delivery.js +1 -1
  89. package/dist/src/instrumentation/content.js +1 -1
  90. package/dist/src/instrumentation/dispatch.js +1 -1
  91. package/dist/src/instrumentation/lifecycle.d.ts +19 -2
  92. package/dist/src/instrumentation/lifecycle.js +1 -1
  93. package/dist/src/instrumentation/memory.d.ts +72 -0
  94. package/dist/src/instrumentation/memory.js +1 -0
  95. package/dist/src/instrumentation/native-events.d.ts +7 -0
  96. package/dist/src/instrumentation/native-events.js +1 -1
  97. package/dist/src/instrumentation/parent-lineage.d.ts +2 -2
  98. package/dist/src/instrumentation/parent-lineage.js +1 -1
  99. package/dist/src/instrumentation/prepare-trace-context.d.ts +3 -11
  100. package/dist/src/instrumentation/prepare-trace-context.js +1 -1
  101. package/dist/src/instrumentation/principal-summary.d.ts +11 -0
  102. package/dist/src/instrumentation/principal-summary.js +1 -0
  103. package/dist/src/instrumentation/provider.d.ts +1 -0
  104. package/dist/src/instrumentation/runtime.d.ts +11 -7
  105. package/dist/src/instrumentation/runtime.js +1 -1
  106. package/dist/src/instrumentation/session-context.d.ts +22 -0
  107. package/dist/src/instrumentation/session-context.js +1 -0
  108. package/dist/src/instrumentation/state.d.ts +7 -2
  109. package/dist/src/instrumentation/state.js +1 -1
  110. package/dist/src/internal/application/package.js +1 -1
  111. package/dist/src/internal/logging.js +1 -1
  112. package/dist/src/internal/nitro/routes/channel-dispatch.js +1 -1
  113. package/dist/src/internal/nitro/routes/channel-request-instrumentation.d.ts +4 -5
  114. package/dist/src/internal/nitro/routes/channel-request-instrumentation.js +1 -1
  115. package/dist/src/protocol/baggage.d.ts +15 -2
  116. package/dist/src/protocol/baggage.js +1 -1
  117. package/dist/src/public/instrumentation/index.d.ts +5 -4
  118. package/dist/src/runtime/agent/bootstrap.d.ts +2 -2
  119. package/dist/src/runtime/agent/bootstrap.js +1 -1
  120. package/dist/src/self-modification/agent.js +1 -1
  121. package/dist/src/self-modification/extension/instructions.js +21 -20
  122. package/dist/src/self-modification/extension/tools/edit_file.js +1 -1
  123. package/dist/src/self-modification/extension/tools/search_registry.d.ts +1 -1
  124. package/dist/src/self-modification/extension/tools/search_registry.js +1 -1
  125. package/dist/src/setup/integrations/self-modification/setup.js +1 -1
  126. package/dist/src/setup/scaffold/create/project.js +1 -1
  127. package/dist/src/shared/action-types.d.ts +4 -0
  128. package/dist/src/shared/action-types.js +1 -1
  129. package/dist/src/shared/dispatch-action.d.ts +1 -1
  130. package/dist/src/shared/memory-state.js +1 -1
  131. package/dist/src/shared/serialized-observability-state.d.ts +12 -0
  132. package/dist/src/shared/serialized-observability-state.js +1 -0
  133. package/dist/src/subagents/callback-route.js +1 -1
  134. package/dist/src/subagents/callback-step.d.ts +0 -8
  135. package/dist/src/subagents/callback-step.js +1 -1
  136. package/dist/src/subagents/invocation.d.ts +9 -0
  137. package/dist/src/subagents/remote-dispatch.d.ts +3 -3
  138. package/dist/src/subagents/remote-dispatch.js +1 -1
  139. package/dist/src/subagents/start-local.d.ts +2 -6
  140. package/dist/src/subagents/start-local.js +1 -1
  141. package/dist/src/subagents/start-remote.d.ts +2 -8
  142. package/dist/src/subagents/start-remote.js +1 -1
  143. package/dist/src/subagents/tool.d.ts +3 -13
  144. package/dist/src/subagents/tool.js +1 -1
  145. package/dist/src/svelte/index.js +1 -1
  146. package/dist/src/svelte/use-eve-agent.js +1 -1
  147. package/dist/src/tasks/delivery-context.d.ts +12 -3
  148. package/dist/src/tasks/delivery-context.js +2 -2
  149. package/dist/src/tasks/session-index.d.ts +6 -3
  150. package/dist/src/tasks/session-index.js +1 -1
  151. package/dist/src/tasks/session-task-cohorts.d.ts +10 -2
  152. package/dist/src/tasks/session-task-cohorts.js +1 -1
  153. package/dist/src/tools/behavior.d.ts +1 -3
  154. package/dist/src/tools/framework/task-contract.d.ts +0 -4
  155. package/dist/src/tools/framework/task-contract.js +1 -1
  156. package/dist/src/tracing/agent-action-instrumentation.d.ts +3 -2
  157. package/dist/src/tracing/agent-action-instrumentation.js +1 -1
  158. package/dist/src/tracing/agent-approval-instrumentation.js +1 -1
  159. package/dist/src/tracing/agent-channel-delivery-instrumentation.d.ts +1 -6
  160. package/dist/src/tracing/agent-channel-delivery-instrumentation.js +1 -1
  161. package/dist/src/tracing/agent-invocation-coordinator.d.ts +28 -0
  162. package/dist/src/tracing/agent-invocation-coordinator.js +1 -0
  163. package/dist/src/tracing/agent-invocation-terminal.d.ts +18 -0
  164. package/dist/src/tracing/agent-invocation-terminal.js +1 -0
  165. package/dist/src/tracing/agent-memory-instrumentation.d.ts +13 -0
  166. package/dist/src/tracing/agent-memory-instrumentation.js +1 -0
  167. package/dist/src/tracing/agent-otel-attributes.d.ts +4 -0
  168. package/dist/src/tracing/agent-otel-attributes.js +1 -0
  169. package/dist/src/tracing/agent-otel-content.d.ts +4 -12
  170. package/dist/src/tracing/agent-otel-content.js +3 -3
  171. package/dist/src/tracing/agent-otel-provider.d.ts +4 -6
  172. package/dist/src/tracing/agent-otel-provider.js +2 -2
  173. package/dist/src/tracing/agent-otel-runtime-context.d.ts +9 -0
  174. package/dist/src/tracing/agent-otel-runtime-context.js +1 -1
  175. package/dist/src/tracing/agent-otel-session-context.d.ts +4 -3
  176. package/dist/src/tracing/agent-otel-session-context.js +1 -1
  177. package/dist/src/tracing/agent-otel-usage.d.ts +4 -10
  178. package/dist/src/tracing/agent-otel-usage.js +1 -1
  179. package/dist/src/tracing/agent-span-contract.d.ts +26 -0
  180. package/dist/src/tracing/agent-span-contract.js +1 -0
  181. package/dist/src/tracing/agent-span-error.d.ts +3 -0
  182. package/dist/src/tracing/agent-span-error.js +1 -0
  183. package/dist/src/tracing/agent-span-id-generator.d.ts +3 -0
  184. package/dist/src/tracing/agent-span-id-generator.js +1 -1
  185. package/dist/src/tracing/agent-tool-instrumentation.js +1 -1
  186. package/dist/src/tracing/agent-trace-context-codec.d.ts +12 -0
  187. package/dist/src/tracing/agent-trace-context-codec.js +1 -0
  188. package/dist/src/tracing/agent-trace-context-store.d.ts +35 -8
  189. package/dist/src/tracing/agent-trace-context-store.js +1 -1
  190. package/dist/src/tracing/agent-trace-span-processor.d.ts +5 -7
  191. package/dist/src/tracing/agent-trace-span-processor.js +1 -1
  192. package/dist/src/tracing/agent-trace-state.d.ts +43 -3
  193. package/dist/src/tracing/agent-trace-state.js +1 -1
  194. package/dist/src/tracing/bounded-error.d.ts +1 -0
  195. package/dist/src/tracing/bounded-error.js +1 -0
  196. package/dist/src/tracing/content-attributes.js +1 -1
  197. package/dist/src/tracing/content-span-processor.js +1 -1
  198. package/dist/src/tracing/conversation-context.d.ts +4 -0
  199. package/dist/src/tracing/conversation-context.js +1 -0
  200. package/dist/src/tracing/error-content-context.d.ts +3 -0
  201. package/dist/src/tracing/error-content-context.js +1 -0
  202. package/dist/src/tracing/install-instrumentation-runtime.js +1 -1
  203. package/dist/src/tracing/local-trace-reader.d.ts +6 -6
  204. package/dist/src/tracing/local-trace-reader.js +1 -1
  205. package/dist/src/tracing/local-traces.d.ts +6 -8
  206. package/dist/src/tracing/local-traces.js +1 -1
  207. package/dist/src/tracing/otel-declaration.d.ts +5 -3
  208. package/dist/src/tracing/otel-registration.d.ts +2 -1
  209. package/dist/src/tracing/otel-registration.js +1 -1
  210. package/dist/src/tracing/telemetry-budget.d.ts +4 -0
  211. package/dist/src/tracing/telemetry-budget.js +1 -0
  212. package/dist/src/vue/index.js +1 -1
  213. package/dist/src/vue/use-eve-agent.js +1 -1
  214. package/docs/concepts/built-in-tools.md +0 -20
  215. package/docs/concepts/sessions-runs-and-streaming.md +9 -1
  216. package/docs/guides/frontend/overview.mdx +1 -1
  217. package/docs/guides/instrumentation-providers.md +5 -0
  218. package/docs/guides/instrumentation.md +179 -23
  219. package/docs/guides/remote-agents.md +11 -0
  220. package/docs/reference/cli.md +16 -14
  221. package/docs/subagents/index.mdx +15 -10
  222. package/package.json +1 -6
  223. package/dist/src/execution/tasks/child/update-step.d.ts +0 -6
  224. package/dist/src/execution/tasks/child/update-step.js +0 -1
  225. package/dist/src/execution/tasks/child/update.d.ts +0 -8
  226. package/dist/src/execution/tasks/child/update.js +0 -1
  227. package/dist/src/public/tools/task-update.d.ts +0 -1
  228. package/dist/src/public/tools/task-update.js +0 -1
  229. package/dist/src/tools/framework/task-update.d.ts +0 -5
  230. package/dist/src/tools/framework/task-update.js +0 -1
@@ -1 +1 @@
1
- import{normalizeChannelAudience}from"#shared/channel-audience.js";import{hasSessionRelease}from"#tracing/local-traces.js";import{channelAudienceFromContext}from"#tracing/channel-audience-context.js";import{withoutDeclinedContent}from"#tracing/content-attributes.js";import{contentRedactionForSpan,spanExportPolicyStages}from"#tracing/span-export-policy.js";function contentFilteringProcessor(e,t){if(t===void 0)return e;let n=e;for(let e of spanExportPolicyStages(t).toReversed())n=policyFilteringProcessor(n,e);return n}function policyFilteringProcessor(e,t){let n=new WeakMap,r=new WeakSet,i={forceFlush:()=>e.forceFlush(),onEnd:i=>{if(typeof i!=`object`||!i)return;let a=facadeFor(i,t,n);if(r.has(i)||!a.exported){r.delete(i),n.delete(i);return}a.refresh();try{e.onEnd(a.value)}finally{n.delete(i)}},onStart:(i,a)=>{if(typeof i!=`object`||!i)return;let o=facadeFor(i,t,n,channelAudienceFromContext(a));if(!o.exported){r.add(i);return}e.onStart(o.value,a)},shutdown:()=>e.shutdown()};return hasSessionRelease(e)?{...i,releaseSession:t=>e.releaseSession(t)}:i}function facadeFor(e,t,n,r){let i=n.get(e);if(i!==void 0)return i;let a=spanExportContext(e,r),o=contentForSpan(a,t),s={},c=[],l={},u=Object.create(Reflect.getPrototypeOf(e)),d=new Map,refresh=()=>{refreshAttributes(s,e,o,a,t),refreshEvents(c,e,o),refreshStatus(l,e,o)},f,readOriginal=t=>{let n=Reflect.get(e,t,e);if(typeof n!=`function`||t===`constructor`)return n;let r=d.get(t);if(r!==void 0)return r;let created=(...t)=>{let r=Reflect.apply(n,e,t);return refresh(),r===e?f:r};return d.set(t,created),created};Object.defineProperty(u,"attributes",{configurable:!0,enumerable:!0,value:s}),Object.defineProperty(u,"events",{configurable:!0,enumerable:!0,value:c}),Object.defineProperty(u,"status",{configurable:!0,enumerable:!0,value:l});for(let t of Reflect.ownKeys(e)){if(t===`attributes`||t===`events`||t===`status`)continue;let n=Reflect.getOwnPropertyDescriptor(e,t);Object.defineProperty(u,t,{configurable:!0,enumerable:n?.enumerable??!1,get:()=>readOriginal(t)})}f=new Proxy(u,{get:(e,t,n)=>Object.hasOwn(e,t)?Reflect.get(e,t,n):readOriginal(t)});let p={context:a,exported:shouldExport(a,t),refresh,value:f};return p.refresh(),n.set(e,p),p}function contentForSpan(e,t){let n=contentRedactionForSpan(t,e);return{recordInputs:!n.redactInputs,recordOutputs:!n.redactOutputs}}function refreshAttributes(e,t,n,r,i){for(let t of Object.keys(e))delete e[t];let a=t.attributes;if(typeof a!=`object`||!a)return;let o=withoutDeclinedContent(a,n)??a;for(let[t,n]of Object.entries(o)){let a=attributeDecision(i,{key:t,span:r,value:n});a.action===`keep`?e[t]=n:a.action===`replace`&&(e[t]=a.value)}}function spanExportContext(e,t=`unknown`){let n=e.attributes,r=typeof n==`object`&&n?n:{},i=[r[`agent.channel.audience`],r[`ai.settings.context.eve.channel.audience`]].filter(e=>e!==void 0).map(normalizeChannelAudience),a=i.length>0&&i.every(e=>e===i[0])?i[0]:i.length>0?`unknown`:t,o=e.spanContext?.(),s=typeof o==`object`&&o?o:{},c=e.name;return{attributes:r,audience:a,name:typeof c==`string`?c:``,spanId:typeof s.spanId==`string`?s.spanId:``,traceId:typeof s.traceId==`string`?s.traceId:``}}function shouldExport(e,t){if(t===void 0)return!0;try{return t.span?.(e)!==!1}catch{return!1}}function attributeDecision(e,t){if(e?.attribute===void 0)return{action:`keep`};try{return e.attribute(t)}catch{return{action:`drop`}}}function refreshEvents(e,t,n){e.length=0;let r=t.events;if(Array.isArray(r)){if(n.recordOutputs){e.push(...r);return}for(let t of r){if(typeof t!=`object`||!t)continue;let n=t;n.name!==`exception`&&e.push({...n,attributes:void 0})}}}function refreshStatus(e,t,n){for(let t of Object.keys(e))delete e[t];let r=t.status;if(typeof r!=`object`||!r)return;let i=r;i.code!==void 0&&(e.code=i.code),n.recordOutputs&&i.message!==void 0&&(e.message=i.message)}export{contentFilteringProcessor};
1
+ import{normalizeChannelAudience}from"#shared/channel-audience.js";import{hasConversationRelease}from"#tracing/local-traces.js";import{channelAudienceFromContext}from"#tracing/channel-audience-context.js";import{withoutDeclinedContent}from"#tracing/content-attributes.js";import{contentRedactionForSpan,spanExportPolicyStages}from"#tracing/span-export-policy.js";function contentFilteringProcessor(e,t){if(t===void 0)return e;let n=e;for(let e of spanExportPolicyStages(t).toReversed())n=policyFilteringProcessor(n,e);return n}function policyFilteringProcessor(e,t){let n=new WeakMap,r=new WeakSet,i={forceFlush:()=>e.forceFlush(),onEnd:i=>{if(typeof i!=`object`||!i)return;let a=facadeFor(i,t,n);if(r.has(i)||!a.exported){r.delete(i),n.delete(i);return}a.refresh();try{e.onEnd(a.value)}finally{n.delete(i)}},onStart:(i,a)=>{if(typeof i!=`object`||!i)return;let o=facadeFor(i,t,n,channelAudienceFromContext(a));if(!o.exported){r.add(i);return}e.onStart(o.value,a)},shutdown:()=>e.shutdown()};return hasConversationRelease(e)?{...i,releaseConversation:t=>e.releaseConversation(t)}:i}function facadeFor(e,t,n,r){let i=n.get(e);if(i!==void 0)return i;let a=spanExportContext(e,r),o=contentForSpan(a,t),s={},c=[],l={},u=Object.create(Reflect.getPrototypeOf(e)),d=new Map,refresh=()=>{refreshAttributes(s,e,o,a,t),refreshEvents(c,e,o),refreshStatus(l,e,o)},f,readOriginal=t=>{let n=Reflect.get(e,t,e);if(typeof n!=`function`||t===`constructor`)return n;let r=d.get(t);if(r!==void 0)return r;let created=(...t)=>{let r=Reflect.apply(n,e,t);return refresh(),r===e?f:r};return d.set(t,created),created};Object.defineProperty(u,"attributes",{configurable:!0,enumerable:!0,value:s}),Object.defineProperty(u,"events",{configurable:!0,enumerable:!0,value:c}),Object.defineProperty(u,"status",{configurable:!0,enumerable:!0,value:l});for(let t of Reflect.ownKeys(e)){if(t===`attributes`||t===`events`||t===`status`)continue;let n=Reflect.getOwnPropertyDescriptor(e,t);Object.defineProperty(u,t,{configurable:!0,enumerable:n?.enumerable??!1,get:()=>readOriginal(t)})}f=new Proxy(u,{get:(e,t,n)=>Object.hasOwn(e,t)?Reflect.get(e,t,n):readOriginal(t)});let p={context:a,exported:shouldExport(a,t),refresh,value:f};return p.refresh(),n.set(e,p),p}function contentForSpan(e,t){let n=contentRedactionForSpan(t,e);return{recordInputs:!n.redactInputs,recordOutputs:!n.redactOutputs}}function refreshAttributes(e,t,n,r,i){for(let t of Object.keys(e))delete e[t];let a=t.attributes;if(typeof a!=`object`||!a)return;let o=withoutDeclinedContent(a,n)??a;for(let[t,n]of Object.entries(o)){let a=attributeDecision(i,{key:t,span:r,value:n});a.action===`keep`?e[t]=n:a.action===`replace`&&(e[t]=a.value)}}function spanExportContext(e,t=`unknown`){let n=e.attributes,r=typeof n==`object`&&n?n:{},i=[r[`agent.channel.audience`],r[`ai.settings.context.eve.channel.audience`]].filter(e=>e!==void 0).map(normalizeChannelAudience),a=i.length>0&&i.every(e=>e===i[0])?i[0]:i.length>0?`unknown`:t,o=e.spanContext?.(),s=typeof o==`object`&&o?o:{},c=e.name;return{attributes:r,audience:a,name:typeof c==`string`?c:``,spanId:typeof s.spanId==`string`?s.spanId:``,traceId:typeof s.traceId==`string`?s.traceId:``}}function shouldExport(e,t){if(t===void 0)return!0;try{return t.span?.(e)!==!1}catch{return!1}}function attributeDecision(e,t){if(e?.attribute===void 0)return{action:`keep`};try{return e.attribute(t)}catch{return{action:`drop`}}}function refreshEvents(e,t,n){e.length=0;let r=t.events;if(Array.isArray(r)){if(n.recordOutputs){e.push(...r);return}for(let t of r){if(typeof t!=`object`||!t)continue;let n=t;n.name!==`exception`&&e.push({...n,attributes:void 0})}}}function refreshStatus(e,t,n){for(let t of Object.keys(e))delete e[t];let r=t.status;if(typeof r!=`object`||!r)return;let i=r;i.code!==void 0&&(e.code=i.code),n.recordOutputs&&i.message!==void 0&&(e.message=i.message)}export{contentFilteringProcessor};
@@ -0,0 +1,4 @@
1
+ export declare function readConversationId(value: unknown): string | undefined;
2
+ export declare function resolveConversationId(fallback: string): string;
3
+ export declare function readConversationBaggage(value: string | null): string | undefined;
4
+ export declare function writeConversationBaggage(value: string | undefined, conversationId: string | undefined): string | undefined;
@@ -0,0 +1 @@
1
+ import{contextStorage}from"#context/container.js";import{ConversationIdKey}from"#context/keys.js";import{readBaggageMember,replaceBaggageMember}from"#protocol/baggage.js";const BAGGAGE_KEY=`eve.conversation.id`,MAX_ID_BYTES=1024,encoder=new TextEncoder;function readConversationId(e){if(!(typeof e!=`string`||e.length===0||e.length>MAX_ID_BYTES||/[\u0000-\u001f\u007f-\u009f\u2028\u2029]/u.test(e)||encoder.encode(e).byteLength>MAX_ID_BYTES))try{return e}catch{return}}function resolveConversationId(e){return readConversationId(contextStorage.getStore()?.get(ConversationIdKey))??e}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{readConversationBaggage,readConversationId,resolveConversationId,writeConversationBaggage};
@@ -0,0 +1,3 @@
1
+ import { type Context } from "#compiled/@opentelemetry/api/index.js";
2
+ export declare function withErrorContent(context: Context, allowed: boolean): Context;
3
+ export declare function capturesErrorContent(): boolean;
@@ -0,0 +1 @@
1
+ import{context,createContextKey}from"#compiled/@opentelemetry/api/index.js";const ERROR_CONTENT_KEY=createContextKey(`eve.trace.error-content`);function withErrorContent(e,t){return e.setValue(ERROR_CONTENT_KEY,t)}function capturesErrorContent(){return context.active().getValue(ERROR_CONTENT_KEY)!==!1}export{capturesErrorContent,withErrorContent};
@@ -1 +1 @@
1
- import{createLogger,formatError}from"#internal/logging.js";import{ContextAgentTraceStateStore}from"#tracing/agent-trace-context-store.js";import{registerInstrumentationRuntime}from"#instrumentation/runtime.js";import{trace}from"#compiled/@opentelemetry/api/index.js";import{createInstrumentationHooks}from"#instrumentation/lifecycle.js";import{hasSessionRelease}from"#tracing/local-traces.js";import{AgentSpanIdGenerator}from"#tracing/agent-span-id-generator.js";import{createAgentOtelInstrumentation}from"#tracing/agent-otel-provider.js";import{registerOtelPipeline}from"#tracing/otel-registration.js";const log=createLogger(`tracing.install-instrumentation-runtime`);function installInstrumentationRuntime(e){let t=[],n=[],r,i,a,runInContext=(e,t)=>t();if(e.collected.declared){r=registerOtelPipeline({pipeline:e.collected.pipeline,serviceName:e.serviceName});let o=createAgentOtelInstrumentation({frameworkVersion:e.frameworkVersion,idGenerator:r.idGenerator,recordInputs:e.collected.settings.recordInputs,recordOutputs:e.collected.settings.recordOutputs,stateStore:new ContextAgentTraceStateStore,tracer:trace.getTracer(`eve.agent`,e.frameworkVersion),tracePolicy:e.collected.settings.tracePolicy});t.push({...o.hook,stateNamespace:`internal:otel`}),i=o.prepareSessionTrace,a=o.prepareTurnTrace,runInContext=o.runInContext;let s=e.collected.pipeline.spanProcessors.filter(isSpanProcessor).filter(hasSessionRelease);s.length>0&&n.push(sessionReleaseProvider(s))}let o=[...t,...e.providers,...n],s;return registerInstrumentationRuntime({forceFlush:()=>settleAll([...r===void 0?[]:[r.forceFlush],...o.map(e=>()=>e.flush?.())]),hooks:createInstrumentationHooks({parallel:e.providers,serialAfter:n,serialBefore:t}),idGenerator:r?.idGenerator??new AgentSpanIdGenerator,instrumentationProviders:e.instrumentationProviders,otelSettings:e.collected.declared?e.collected.settings:void 0,ownsAgentSpans:r!==void 0,prepareSessionTrace:i,prepareTurnTrace:a,runtimeContextResolvers:e.runtimeContextResolvers,runInContext,samplesTrace:r?.samplesTrace,shutdown:()=>(s??=settleAll([...r===void 0?[]:[r.shutdown],...o.map(e=>()=>e.shutdown?.())]),s)})}function isSpanProcessor(e){return e!==`auto`}function sessionReleaseProvider(e){let release=async t=>{await Promise.all(e.map(e=>e.releaseSession(t.sessionId)))};return{events:{"session.completed":release,"session.failed":release},name:`eve.session-release`,stateNamespace:`internal:session-release`}}async function settleAll(e){let t=await Promise.allSettled(e.map(async e=>e()));for(let e of t)e.status===`rejected`&&log.warn(`instrumentation drain failed`,{error:formatError(e.reason)})}export{installInstrumentationRuntime};
1
+ import{createLogger,formatError}from"#internal/logging.js";import{contextStorage}from"#context/container.js";import{ConversationIdKey}from"#context/keys.js";import{readConversationId}from"#tracing/conversation-context.js";import{ContextAgentTraceStateStore}from"#tracing/agent-trace-context-store.js";import{registerInstrumentationRuntime}from"#instrumentation/runtime.js";import{trace}from"#compiled/@opentelemetry/api/index.js";import{createInstrumentationHooks}from"#instrumentation/lifecycle.js";import{AgentSpanIdGenerator}from"#tracing/agent-span-id-generator.js";import{hasConversationRelease}from"#tracing/local-traces.js";import{createAgentOtelInstrumentation}from"#tracing/agent-otel-provider.js";import{registerOtelPipeline}from"#tracing/otel-registration.js";const log=createLogger(`tracing.install-instrumentation-runtime`);function installInstrumentationRuntime(e){let t=[],n=[],r,flushSettledInvocations,i,a,runInContext=(e,t)=>t();if(e.collected.declared){r=registerOtelPipeline({pipeline:e.collected.pipeline,serviceName:e.serviceName});let o=createAgentOtelInstrumentation({frameworkVersion:e.frameworkVersion,idGenerator:r.idGenerator,recordInputs:e.collected.settings.recordInputs,recordOutputs:e.collected.settings.recordOutputs,samplesTrace:r.samplesTrace,stateStore:new ContextAgentTraceStateStore,tracer:trace.getTracer(`eve.agent`,e.frameworkVersion),tracePolicy:e.collected.settings.tracePolicy});t.push({...o.hook,stateNamespace:`internal:otel`}),flushSettledInvocations=async()=>{await o.hook.flush?.()},i=o.prepareSessionTrace,a=o.prepareTurnTrace,runInContext=o.runInContext;let s=e.collected.pipeline.spanProcessors.filter(isSpanProcessor).filter(hasConversationRelease);s.length>0&&n.push(sessionReleaseProvider(s))}let o=[...t,...e.providers,...n],s;return registerInstrumentationRuntime({flushSettledInvocations,forceFlush:async()=>{await settleAll(o.map(e=>()=>e.flush?.())),await settleAll(r===void 0?[]:[r.forceFlush])},hooks:createInstrumentationHooks({parallel:e.providers,serialAfter:n,serialBefore:t}),idGenerator:r?.idGenerator??new AgentSpanIdGenerator,instrumentationProviders:e.instrumentationProviders,memoryOperations:r!==void 0||e.providers.some(hasMemoryOperationHandler),otelSettings:e.collected.declared?e.collected.settings:void 0,ownsAgentSpans:r!==void 0,prepareSessionTrace:i,prepareTurnTrace:a,runtimeContextResolvers:e.runtimeContextResolvers,runInContext,samplesTrace:r?.samplesTrace,shutdown:()=>(s??=(async()=>{await settleAll(o.map(e=>()=>e.shutdown?.())),await settleAll(r===void 0?[]:[r.shutdown])})(),s)})}function hasMemoryOperationHandler(e){return e.events?.[`memory.operation.started`]!==void 0||e.events?.[`memory.operation.completed`]!==void 0||e.events?.[`memory.operation.failed`]!==void 0}function isSpanProcessor(e){return e!==`auto`}function sessionReleaseProvider(e){let release=async t=>{let n=readConversationId(contextStorage.getStore()?.get(ConversationIdKey))??t.sessionId;n===t.sessionId&&await Promise.all(e.map(e=>e.releaseConversation(n)))};return{events:{"session.completed":release,"session.failed":release},name:`eve.conversation-release`,stateNamespace:`internal:conversation-release`}}async function settleAll(e){let t=await Promise.allSettled(e.map(async e=>e()));for(let e of t)e.status===`rejected`&&log.warn(`instrumentation drain failed`,{error:formatError(e.reason)})}export{installInstrumentationRuntime};
@@ -31,15 +31,15 @@ export interface LocalTraceSpan {
31
31
  export interface LocalTrace {
32
32
  readonly agentName?: string;
33
33
  readonly endTimeNs: bigint;
34
- /** Session that opened the trace, which is the one the list shows. */
35
- readonly sessionId?: string;
34
+ /** Conversation that owns the trace, which is the one the list shows. */
35
+ readonly conversationId?: string;
36
36
  /**
37
- * Every session recorded in the trace, opener first.
37
+ * Every conversation identifier recorded in the trace.
38
38
  *
39
- * A subagent child records into the trace its parent opened, so one
40
- * trace can hold several sessions and any of their ids resolves to it.
39
+ * A logical conversation can contain separate root traces for the parent
40
+ * and child activations. Any matching conversation ID resolves to them.
41
41
  */
42
- readonly sessionIds: readonly string[];
42
+ readonly conversationIds: readonly string[];
43
43
  readonly spans: readonly LocalTraceSpan[];
44
44
  readonly startTimeNs: bigint;
45
45
  readonly traceId: string;
@@ -1 +1 @@
1
- import{readFile,readdir,stat}from"node:fs/promises";import{join}from"node:path";import{resolveLocalTraceSchemaDirectory,resolveLocalTraceSegmentsDirectory}from"#tracing/local-trace-span-processor.js";const TRACE_ID_PATTERN=/^[0-9a-f]{32}$/u,SPAN_FILE_PATTERN=/^[0-9a-f]{16}\.otlp\.json$/u;async function listLocalTraceIds(e){let t;try{t=await readdir(resolveLocalTraceSchemaDirectory(e),{withFileTypes:!0})}catch(e){if(isMissing(e))return[];throw e}return t.filter(e=>e.isDirectory()&&TRACE_ID_PATTERN.test(e.name)).map(e=>e.name)}async function readLocalTraceActivityMs(e,t){try{return(await stat(resolveLocalTraceSegmentsDirectory(e,t))).mtimeMs}catch(e){if(isMissing(e))return;throw e}}async function listLocalTraceSegments(e,t){let n;try{n=await readdir(resolveLocalTraceSegmentsDirectory(e,t),{withFileTypes:!0})}catch(e){if(isMissing(e))return;throw e}return n.filter(e=>e.isFile()&&SPAN_FILE_PATTERN.test(e.name)).map(e=>e.name).sort((e,t)=>e.localeCompare(t))}async function readLocalTraceSegment(e,t,n){let r=join(resolveLocalTraceSegmentsDirectory(e,t),n),i;try{if((await stat(r)).size>8388608)return[];i=await readFile(r,`utf8`)}catch{return[]}return parseLocalTraceSegment(i,t)}async function listLocalTraces(e){let t=[];for(let n of await listLocalTraceIds(e)){let r=await readLocalTrace(e,n).catch(()=>void 0);r!==void 0&&t.push(r)}return t.sort((e,t)=>e.startTimeNs===t.startTimeNs?e.traceId.localeCompare(t.traceId):e.startTimeNs>t.startTimeNs?-1:1)}async function readLocalTrace(e,t){let n=await listLocalTraceSegments(e,t);if(n===void 0)return;let r=new Map;for(let i of n)for(let n of await readLocalTraceSegment(e,t,i))r.has(n.spanId)||r.set(n.spanId,n);if(r.size!==0)return assembleLocalTrace(t,[...r.values()])}function compareLocalTraceSpans(e,t){return e.startTimeNs===t.startTimeNs?e.endTimeNs===t.endTimeNs?e.name.localeCompare(t.name)||e.spanId.localeCompare(t.spanId):e.endTimeNs<t.endTimeNs?-1:1:e.startTimeNs<t.startTimeNs?-1:1}function assembleLocalTrace(e,t){let n=[...t].sort(compareLocalTraceSpans),r=n.map(e=>e.attributes),i=distinctAttributes(r,`agent.session.id`);return{agentName:firstAttribute(r,`agent.name`),endTimeNs:n.reduce((e,t)=>t.endTimeNs>e?t.endTimeNs:e,0n),sessionId:i[0],sessionIds:i,spans:n,startTimeNs:n.reduce((e,t)=>t.startTimeNs<e?t.startTimeNs:e,n[0].startTimeNs),traceId:e}}function describeLocalTraceSpan(e){let t=[],n=stringSpanAttribute(e,`agent.turn.id`),r=valueSpanAttribute(e,`agent.step.index`),i=valueSpanAttribute(e,`agent.step.attempt`),a=stringSpanAttribute(e,`agent.action.kind`),o=stringSpanAttribute(e,`agent.action.name`),s=stringSpanAttribute(e,`agent.model.id`)??stringSpanAttribute(e,`gen_ai.request.model`);return isAgentTurnSpan(e)&&n!==void 0&&t.push(n),e.name===`agent.step`&&r!==void 0&&t.push(`step ${String(r)}${i===void 0?``:`, attempt ${String(i)}`}`),e.name===`agent.action`&&o!==void 0&&t.push(`${a??`action`}: ${o}`),s!==void 0&&e.name.includes(`do`)&&t.push(`model ${s}`),t}function isAgentTurnSpan(e){return e.name===`agent.turn`||stringSpanAttribute(e,`gen_ai.operation.name`)===`invoke_agent`&&stringSpanAttribute(e,`agent.turn.id`)!==void 0}function parseLocalTraceSegment(e,t){try{let n=JSON.parse(e);if(!isRecord(n)||!Array.isArray(n.resourceSpans))return[];let r=[];for(let e of n.resourceSpans)if(isRecord(e)&&Array.isArray(e.scopeSpans))for(let n of e.scopeSpans){if(!isRecord(n)||!Array.isArray(n.spans))continue;let e=isRecord(n.scope)&&typeof n.scope.name==`string`?n.scope.name:void 0;for(let i of n.spans){let n=parseLocalTraceSpan(i,t,e);n!==void 0&&r.push(n)}}return r}catch{return[]}}function parseLocalTraceSpan(e,t,n){if(!isRecord(e)||e.traceId!==t||typeof e.spanId!=`string`||!/^[0-9a-f]{16}$/u.test(e.spanId)||typeof e.name!=`string`)return;let r=parseNanos(e.startTimeUnixNano),i=parseNanos(e.endTimeUnixNano);if(!(r===void 0||i===void 0||i<r))return{attributes:parseAttributes(e.attributes),endTimeNs:i,events:parseEvents(e.events),kind:typeof e.kind==`number`?e.kind:void 0,name:e.name,parentSpanId:typeof e.parentSpanId==`string`&&/^[0-9a-f]{16}$/u.test(e.parentSpanId)?e.parentSpanId:void 0,scope:n,spanId:e.spanId,startTimeNs:r,statusCode:parseStatusCode(e.status),statusMessage:parseStatusMessage(e.status),traceId:t}}function parseEvents(e){if(!Array.isArray(e))return[];let t=[];for(let n of e){if(!isRecord(n)||typeof n.name!=`string`)continue;let e=parseNanos(n.timeUnixNano);e!==void 0&&t.push({attributes:parseAttributes(n.attributes),name:n.name,timeNs:e})}return t.sort((e,t)=>e.timeNs===t.timeNs?e.name.localeCompare(t.name):e.timeNs<t.timeNs?-1:1)}function parseAttributes(e){if(!Array.isArray(e))return{};let t={};for(let n of e){if(!isRecord(n)||typeof n.key!=`string`||!isRecord(n.value))continue;let e=parseAnyValue(n.value);e!==void 0&&(t[n.key]=e)}return t}function parseAnyValue(e){for(let t of[`stringValue`,`boolValue`,`intValue`,`doubleValue`])if(t in e)return e[t];if(isRecord(e.arrayValue)&&Array.isArray(e.arrayValue.values))return e.arrayValue.values.filter(isRecord).map(e=>parseAnyValue(e))}function parseNanos(e){if(typeof e==`string`||typeof e==`number`)try{let t=BigInt(e);return t>=0n&&t<=18446744073709551615n?t:void 0}catch{return}}function parseStatusCode(e){return isRecord(e)?typeof e.code==`number`?e.code:e.code===`STATUS_CODE_ERROR`?2:0:0}function parseStatusMessage(e){if(isRecord(e)&&typeof e.message==`string`)return e.message.length===0?void 0:e.message}function firstAttribute(e,t){for(let n of e){let e=n[t];if(typeof e==`string`&&e.length>0)return e}}function distinctAttributes(e,t){let n=new Set;for(let r of e){let e=r[t];typeof e==`string`&&e.length>0&&n.add(e)}return[...n]}function stringSpanAttribute(e,t){let n=e.attributes[t];return typeof n==`string`?n:void 0}function valueSpanAttribute(e,t){let n=e.attributes[t];return typeof n==`string`||typeof n==`number`?n:void 0}function isMissing(e){return e.code===`ENOENT`}function isRecord(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}export{assembleLocalTrace,compareLocalTraceSpans,describeLocalTraceSpan,isAgentTurnSpan,listLocalTraceIds,listLocalTraceSegments,listLocalTraces,parseLocalTraceSegment,readLocalTraceActivityMs,readLocalTraceSegment};
1
+ import{readFile,readdir,stat}from"node:fs/promises";import{join}from"node:path";import{isAgentActivationSpan}from"#tracing/agent-span-contract.js";import{resolveLocalTraceSchemaDirectory,resolveLocalTraceSegmentsDirectory}from"#tracing/local-trace-span-processor.js";const TRACE_ID_PATTERN=/^[0-9a-f]{32}$/u,SPAN_FILE_PATTERN=/^[0-9a-f]{16}\.otlp\.json$/u;async function listLocalTraceIds(e){let t;try{t=await readdir(resolveLocalTraceSchemaDirectory(e),{withFileTypes:!0})}catch(e){if(isMissing(e))return[];throw e}return t.filter(e=>e.isDirectory()&&TRACE_ID_PATTERN.test(e.name)).map(e=>e.name)}async function readLocalTraceActivityMs(e,t){try{return(await stat(resolveLocalTraceSegmentsDirectory(e,t))).mtimeMs}catch(e){if(isMissing(e))return;throw e}}async function listLocalTraceSegments(e,t){let n;try{n=await readdir(resolveLocalTraceSegmentsDirectory(e,t),{withFileTypes:!0})}catch(e){if(isMissing(e))return;throw e}return n.filter(e=>e.isFile()&&SPAN_FILE_PATTERN.test(e.name)).map(e=>e.name).sort((e,t)=>e.localeCompare(t))}async function readLocalTraceSegment(e,t,n){let r=join(resolveLocalTraceSegmentsDirectory(e,t),n),i;try{if((await stat(r)).size>8388608)return[];i=await readFile(r,`utf8`)}catch{return[]}return parseLocalTraceSegment(i,t)}async function listLocalTraces(e){let t=[];for(let n of await listLocalTraceIds(e)){let r=await readLocalTrace(e,n).catch(()=>void 0);r!==void 0&&t.push(r)}return t.sort((e,t)=>e.startTimeNs===t.startTimeNs?e.traceId.localeCompare(t.traceId):e.startTimeNs>t.startTimeNs?-1:1)}async function readLocalTrace(e,t){let n=await listLocalTraceSegments(e,t);if(n===void 0)return;let r=new Map;for(let i of n)for(let n of await readLocalTraceSegment(e,t,i))r.has(n.spanId)||r.set(n.spanId,n);if(r.size!==0)return assembleLocalTrace(t,[...r.values()])}function compareLocalTraceSpans(e,t){return e.startTimeNs===t.startTimeNs?e.endTimeNs===t.endTimeNs?e.name.localeCompare(t.name)||e.spanId.localeCompare(t.spanId):e.endTimeNs<t.endTimeNs?-1:1:e.startTimeNs<t.startTimeNs?-1:1}function assembleLocalTrace(e,t){let n=[...t].sort(compareLocalTraceSpans),r=n.map(e=>e.attributes),i=distinctAttributes(r,`gen_ai.conversation.id`);return{agentName:firstAttribute(r,`agent.name`),endTimeNs:n.reduce((e,t)=>t.endTimeNs>e?t.endTimeNs:e,0n),conversationId:i[0],conversationIds:i,spans:n,startTimeNs:n.reduce((e,t)=>t.startTimeNs<e?t.startTimeNs:e,n[0].startTimeNs),traceId:e}}function describeLocalTraceSpan(e){let t=[],n=stringSpanAttribute(e,`agent.turn.id`),r=valueSpanAttribute(e,`agent.step.index`),i=valueSpanAttribute(e,`agent.step.attempt`),a=stringSpanAttribute(e,`agent.action.kind`),o=stringSpanAttribute(e,`agent.action.name`),s=stringSpanAttribute(e,`agent.model.id`)??stringSpanAttribute(e,`gen_ai.request.model`);return isAgentTurnSpan(e)&&n!==void 0&&t.push(n),e.name===`agent.step`&&r!==void 0&&t.push(`step ${String(r)}${i===void 0?``:`, attempt ${String(i)}`}`),e.name===`agent.action`&&o!==void 0&&t.push(`${a??`action`}: ${o}`),s!==void 0&&e.name.includes(`do`)&&t.push(`model ${s}`),t}function isAgentTurnSpan(e){return isAgentActivationSpan(e)}function parseLocalTraceSegment(e,t){try{let n=JSON.parse(e);if(!isRecord(n)||!Array.isArray(n.resourceSpans))return[];let r=[];for(let e of n.resourceSpans)if(isRecord(e)&&Array.isArray(e.scopeSpans))for(let n of e.scopeSpans){if(!isRecord(n)||!Array.isArray(n.spans))continue;let e=isRecord(n.scope)&&typeof n.scope.name==`string`?n.scope.name:void 0;for(let i of n.spans){let n=parseLocalTraceSpan(i,t,e);n!==void 0&&r.push(n)}}return r}catch{return[]}}function parseLocalTraceSpan(e,t,n){if(!isRecord(e)||e.traceId!==t||typeof e.spanId!=`string`||!/^[0-9a-f]{16}$/u.test(e.spanId)||typeof e.name!=`string`)return;let r=parseNanos(e.startTimeUnixNano),i=parseNanos(e.endTimeUnixNano);if(!(r===void 0||i===void 0||i<r))return{attributes:parseAttributes(e.attributes),endTimeNs:i,events:parseEvents(e.events),kind:typeof e.kind==`number`?e.kind:void 0,name:e.name,parentSpanId:typeof e.parentSpanId==`string`&&/^[0-9a-f]{16}$/u.test(e.parentSpanId)?e.parentSpanId:void 0,scope:n,spanId:e.spanId,startTimeNs:r,statusCode:parseStatusCode(e.status),statusMessage:parseStatusMessage(e.status),traceId:t}}function parseEvents(e){if(!Array.isArray(e))return[];let t=[];for(let n of e){if(!isRecord(n)||typeof n.name!=`string`)continue;let e=parseNanos(n.timeUnixNano);e!==void 0&&t.push({attributes:parseAttributes(n.attributes),name:n.name,timeNs:e})}return t.sort((e,t)=>e.timeNs===t.timeNs?e.name.localeCompare(t.name):e.timeNs<t.timeNs?-1:1)}function parseAttributes(e){if(!Array.isArray(e))return{};let t={};for(let n of e){if(!isRecord(n)||typeof n.key!=`string`||!isRecord(n.value))continue;let e=parseAnyValue(n.value);e!==void 0&&(t[n.key]=e)}return t}function parseAnyValue(e){for(let t of[`stringValue`,`boolValue`,`intValue`,`doubleValue`])if(t in e)return e[t];if(isRecord(e.arrayValue)&&Array.isArray(e.arrayValue.values))return e.arrayValue.values.filter(isRecord).map(e=>parseAnyValue(e))}function parseNanos(e){if(typeof e==`string`||typeof e==`number`)try{let t=BigInt(e);return t>=0n&&t<=18446744073709551615n?t:void 0}catch{return}}function parseStatusCode(e){return isRecord(e)?typeof e.code==`number`?e.code:e.code===`STATUS_CODE_ERROR`?2:0:0}function parseStatusMessage(e){if(isRecord(e)&&typeof e.message==`string`)return e.message.length===0?void 0:e.message}function firstAttribute(e,t){for(let n of e){let e=n[t];if(typeof e==`string`&&e.length>0)return e}}function distinctAttributes(e,t){let n=new Set;for(let r of e){let e=r[t];typeof e==`string`&&e.length>0&&n.add(e)}return[...n]}function stringSpanAttribute(e,t){let n=e.attributes[t];return typeof n==`string`?n:void 0}function valueSpanAttribute(e,t){let n=e.attributes[t];return typeof n==`string`||typeof n==`number`?n:void 0}function isMissing(e){return e.code===`ENOENT`}function isRecord(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}export{assembleLocalTrace,compareLocalTraceSpans,describeLocalTraceSpan,isAgentTurnSpan,listLocalTraceIds,listLocalTraceSegments,listLocalTraces,parseLocalTraceSegment,readLocalTraceActivityMs,readLocalTraceSegment};
@@ -8,29 +8,27 @@ import type { SpanProcessor } from "#compiled/@vercel/otel/index.js";
8
8
  */
9
9
  export interface LocalTracesProcessor extends SpanProcessor {
10
10
  /**
11
- * Settles pending writes and drops one root session's liveness, then bounds
12
- * the store. A subagent child owns no traces, so releasing one is a no-op
13
- * and leaves the shared trace pinned until its root finishes.
11
+ * Settles pending writes and releases this conversation's active traces.
14
12
  */
15
- releaseSession(sessionId: string): Promise<boolean>;
13
+ releaseConversation(conversationId: string): Promise<boolean>;
16
14
  }
17
15
  /**
18
- * Reports whether a processor tracks which session owns which trace, so eve can
19
- * tell it when that session is done.
16
+ * Reports whether a processor tracks which conversation owns which trace, so
17
+ * eve can tell it when that conversation is done.
20
18
  *
21
19
  * Anything standing between eve and the spool has to answer for the spool, so
22
20
  * this is the check a wrapper uses to decide whether it must forward the call.
23
21
  *
24
22
  * @internal
25
23
  */
26
- export declare function hasSessionRelease(processor: SpanProcessor): processor is LocalTracesProcessor;
24
+ export declare function hasConversationRelease(processor: SpanProcessor): processor is LocalTracesProcessor;
27
25
  /**
28
26
  * Writes the OTLP/JSON spool under `.eve/traces/v1`.
29
27
  *
30
28
  * `EVE_TRACES=off` removes the writer but keeps the processor: eve still has
31
29
  * to observe spans to track which session owns which trace.
32
30
  *
33
- * Internal because of `releaseSession`, which eve's runtime drives off session
31
+ * Internal because of `releaseConversation`, which eve's runtime drives off session
34
32
  * lifecycle. The authored surface is `localTraces()`, which wraps this in an
35
33
  * `OtelIntegration`.
36
34
  */
@@ -1 +1 @@
1
- import{LocalTraceSpanProcessor}from"#tracing/local-trace-span-processor.js";import{AgentTraceSpanProcessor}from"#tracing/agent-trace-span-processor.js";import{requestLocalTraceStorePrune,resolveLocalTraceRetentionSettings}from"#tracing/local-trace-retention.js";function hasSessionRelease(e){return typeof e.releaseSession==`function`}function createLocalTracesProcessor(e={}){let t=e.appRoot??process.env.EVE_DEV_WORKER_APP_ROOT;if(t===void 0)return inertLocalTracesProcessor();let n=resolveLocalTraceRetentionSettings(),r=new AgentTraceSpanProcessor(n.enabled?[new LocalTraceSpanProcessor(t)]:[]),requestPrune=()=>{n.enabled&&requestLocalTraceStorePrune({activeTraceIds:r.activeTraceIds(),appRoot:t,maxAgeMs:n.maxAgeMs,maxTotalBytes:n.maxTotalBytes,retainCount:n.retainCount})};return requestPrune(),{forceFlush:()=>r.forceFlush(),onEnd:e=>r.onEnd(e),onStart:(e,t)=>r.onStart(e,t),async releaseSession(e){return await r.forceFlush(),r.releaseSession(e)?(requestPrune(),!0):!1},shutdown:()=>r.shutdown()}}function resolveLocalTracesContent(e={}){return process.env.EVE_TRACES_CONTENT===`off`?{recordInputs:!1,recordOutputs:!1}:{recordInputs:e.recordInputs!==!1,recordOutputs:e.recordOutputs!==!1}}function inertLocalTracesProcessor(){return{forceFlush:async()=>void 0,onEnd:()=>void 0,onStart:()=>void 0,releaseSession:async()=>!1,shutdown:async()=>void 0}}export{createLocalTracesProcessor,hasSessionRelease,resolveLocalTracesContent};
1
+ import{LocalTraceSpanProcessor}from"#tracing/local-trace-span-processor.js";import{AgentTraceSpanProcessor}from"#tracing/agent-trace-span-processor.js";import{requestLocalTraceStorePrune,resolveLocalTraceRetentionSettings}from"#tracing/local-trace-retention.js";function hasConversationRelease(e){return typeof e.releaseConversation==`function`}function createLocalTracesProcessor(e={}){let t=e.appRoot??process.env.EVE_DEV_WORKER_APP_ROOT;if(t===void 0)return inertLocalTracesProcessor();let n=resolveLocalTraceRetentionSettings(),r=new AgentTraceSpanProcessor(n.enabled?[new LocalTraceSpanProcessor(t)]:[]),requestPrune=()=>{n.enabled&&requestLocalTraceStorePrune({activeTraceIds:r.activeTraceIds(),appRoot:t,maxAgeMs:n.maxAgeMs,maxTotalBytes:n.maxTotalBytes,retainCount:n.retainCount})};requestPrune();let forceFlush=async()=>{await r.forceFlush(),r.releaseCompletedTraces()&&requestPrune()};return{forceFlush,onEnd:e=>r.onEnd(e),onStart:(e,t)=>r.onStart(e,t),async releaseConversation(e){return await forceFlush(),r.releaseConversation(e)?(requestPrune(),!0):!1},shutdown:()=>r.shutdown()}}function resolveLocalTracesContent(e={}){return process.env.EVE_TRACES_CONTENT===`off`?{recordInputs:!1,recordOutputs:!1}:{recordInputs:e.recordInputs!==!1,recordOutputs:e.recordOutputs!==!1}}function inertLocalTracesProcessor(){return{forceFlush:async()=>void 0,onEnd:()=>void 0,onStart:()=>void 0,releaseConversation:async()=>!1,shutdown:async()=>void 0}}export{createLocalTracesProcessor,hasConversationRelease,resolveLocalTracesContent};
@@ -28,9 +28,11 @@ export interface OtelOptions {
28
28
  */
29
29
  readonly functionId?: string;
30
30
  /**
31
- * Whether to emit the inbound HTTP `SERVER` span that wraps each channel
32
- * request — the parent of the turn trace and of any `hook.resume` or
33
- * outgoing HTTP spans. Defaults to `false`.
31
+ * Whether to emit an eve-owned HTTP `SERVER` span around each channel
32
+ * request. For a one-to-one delivery, the activation remains a separate
33
+ * trace root and links to this span; when disabled, it links to any
34
+ * already-active upstream request or function span instead. Defaults to
35
+ * `false`.
34
36
  */
35
37
  readonly traceChannelRequests?: boolean;
36
38
  /**
@@ -1,5 +1,6 @@
1
1
  import { AgentSpanIdGenerator } from "#tracing/agent-span-id-generator.js";
2
2
  import type { OtelPipeline } from "#tracing/otel-declaration.js";
3
+ import { type AgentSamplingOperation } from "#tracing/agent-span-contract.js";
3
4
  /**
4
5
  * Builds the process's one OpenTelemetry tracer provider from a merged
5
6
  * declaration, then proves it took the global slot.
@@ -18,6 +19,6 @@ export interface RegisteredOtelPipeline {
18
19
  readonly forceFlush: () => Promise<void>;
19
20
  readonly idGenerator: AgentSpanIdGenerator;
20
21
  /** Whether the installed sampler would record a trace with this id. */
21
- readonly samplesTrace: (traceId: string) => boolean;
22
+ readonly samplesTrace: (traceId: string, operation?: AgentSamplingOperation) => boolean;
22
23
  readonly shutdown: () => Promise<void>;
23
24
  }
@@ -1 +1 @@
1
- import{createRequire}from"node:module";import{context,metrics,propagation,trace}from"#compiled/@opentelemetry/api/index.js";import{AgentSpanIdGenerator}from"#tracing/agent-span-id-generator.js";import{registerOTel}from"#compiled/@vercel/otel/index.js";const REGISTRATION_SPAN_NAME=`eve.otel.registration`,REPLAY_DEDUPLICATION_LIMIT=1e5,require=createRequire(import.meta.url);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=new Set;forwardedSpans=new Set;pendingByParent=new Map;pendingSpanCount=0;processors;startedSpans=new Set;constructor(e){this.processors=e}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=spanIdentity(e);n!==void 0&&addBounded(this.startedSpans,n);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{pipeline:t}=e,n=captureOptionalPeerTracerProxy(),r=new AgentSpanIdGenerator,i=new RegistrationMarkerPropagator,a={attributes:t.resource,autoDetectResources:!1,idGenerator:r,instrumentations:t.instrumentations??[],metricReaders:t.metricReaders,propagators:[...t.propagators??[`auto`],i],serviceName:e.serviceName,spanProcessors:t.spanProcessors.map(e=>isSpanProcessor(e)?new PrivateSpanFilteringProcessor([e]):e)};registerOTel(t.sampler===void 0?a:{...a,traceSampler:t.sampler});let o=globalTracerUses(r),s=i.isInstalled();if((!o||!s)&&rollbackRegistration({ownsPropagator:s,ownsTracer:o}),!o)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(!s)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 c=runtimeTracerProvider();if(typeof c.forceFlush!=`function`||typeof c.shutdown!=`function`)throw rollbackRegistration({ownsPropagator:s,ownsTracer:o}),Error(`The registered OpenTelemetry tracer provider has no lifecycle methods.`);n?.setDelegate(c);let l=runtimeMeterProvider();return{forceFlush:async()=>{await Promise.all([c.forceFlush(),l.forceFlush?.()])},idGenerator:r,samplesTrace:e=>samplerAdmitsTrace(r,e),shutdown:async()=>{disableInstrumentations(t.instrumentations),await Promise.all([c.shutdown(),l.shutdown?.()])}}}function samplerAdmitsTrace(e,t){return(e.withTraceId(t,()=>trace.getTracer(`eve.registration`).startSpan(REGISTRATION_SPAN_NAME,{root:!0})).spanContext().traceFlags&1)==1}function captureOptionalPeerTracerProxy(){try{let e=require("@opentelemetry/api"),t=e.trace.getTracerProvider();return t instanceof e.ProxyTracerProvider?t:void 0}catch{return}}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}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`}export{registerOtelPipeline};
1
+ import{createRequire}from"node:module";import{agentInvocationSpanName}from"#tracing/agent-span-contract.js";import{SpanKind,context,metrics,propagation,trace}from"#compiled/@opentelemetry/api/index.js";import{AgentSpanIdGenerator}from"#tracing/agent-span-id-generator.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=spanIdentity(e);n!==void 0&&addBounded(this.startedSpans,n);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{pipeline:t}=e,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{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}function samplerAdmitsTrace(e,t,n={name:agentInvocationSpanName(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 captureOptionalPeerTracerProxy(){try{let e=require("@opentelemetry/api"),t=e.trace.getTracerProvider();return t instanceof e.ProxyTracerProvider?t:void 0}catch{return}}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`}export{registerOtelPipeline};
@@ -0,0 +1,4 @@
1
+ export declare const TELEMETRY_PRINCIPAL_ID_BYTES = 1024;
2
+ export declare function boundedPrincipalId(value: unknown): string | undefined;
3
+ export declare function telemetryByteLength(text: string): number;
4
+ export declare function truncateTelemetryText(text: string, maxBytes: number): string;
@@ -0,0 +1 @@
1
+ const TELEMETRY_PRINCIPAL_ID_BYTES=1024;function boundedPrincipalId(e){return typeof e==`string`&&e.length>0&&e.length<=1024&&telemetryByteLength(e)<=1024?e:void 0}const encoder=new TextEncoder,decoder=new TextDecoder;function telemetryByteLength(e){return encoder.encode(e).length}function truncateTelemetryText(e,t){let n=e.slice(0,t+1),r=encoder.encode(n);if(n.length===e.length&&r.length<=t)return e;let i=`... [truncated]`.slice(0,t),a=Math.max(0,t-i.length);for(;a>0&&(r[a]&192)==128;)--a;return decoder.decode(r.subarray(0,a))+i}export{TELEMETRY_PRINCIPAL_ID_BYTES,boundedPrincipalId,telemetryByteLength,truncateTelemetryText};
@@ -1,3 +1,3 @@
1
- import { n as defaultMessageReducer, t as useEveAgent } from "../chunks/use-eve-agent-BR8EpIOX.js";
1
+ import { n as defaultMessageReducer, t as useEveAgent } from "../chunks/use-eve-agent-CxPlg0KL.js";
2
2
 
3
3
  export { defaultMessageReducer, useEveAgent };
@@ -1,3 +1,3 @@
1
- import { t as useEveAgent } from "../chunks/use-eve-agent-BR8EpIOX.js";
1
+ import { t as useEveAgent } from "../chunks/use-eve-agent-CxPlg0KL.js";
2
2
 
3
3
  export { useEveAgent };
@@ -319,26 +319,6 @@ import { disableTool } from "eve/tools";
319
319
  export default disableTool();
320
320
  ```
321
321
 
322
- ### `task_update`
323
-
324
- `task_update` lets a background task report progress to its parent. It appears only in delegated task sessions.
325
-
326
- ```sh
327
- eve add tool/task_update
328
- ```
329
-
330
- ```ts title="agent/tools/task_update.ts"
331
- export { default } from "eve/tools/task_update";
332
- ```
333
-
334
- The framework behavior cannot be overridden. Re-export the definition above to restore it, or disable it:
335
-
336
- ```ts title="agent/tools/task_update.ts"
337
- import { disableTool } from "eve/tools";
338
-
339
- export default disableTool();
340
- ```
341
-
342
322
  ### `load_skill`
343
323
 
344
324
  `load_skill` pulls an on-demand [skill](../skills)'s instructions into the current turn. It appears only when the agent declares skills and adds no execution surface by itself.
@@ -97,10 +97,18 @@ Note: consider the privacy, confidentiality, and user-experience implications fo
97
97
 
98
98
  When a task explicitly requires conditional delivery and there is nothing new to report, the agent can finish with exactly `<eve-empty-delivery/>`. eve emits `message.completed` with `message: null` for that intentional silence. The marker must be the entire response, apart from surrounding whitespace; the HTML-escaped form `&lt;eve-empty-delivery/&gt;` is also accepted. A response that quotes the marker in prose or code is delivered normally.
99
99
 
100
- A delegated subagent publishes progress on its own child-session stream. The parent emits `subagent.called` with a `childSessionId`, which a client uses to attach. `subagent.completed` carries a working task receipt after admission; later updates and outcomes arrive as task-triggered `message.received` notifications.
100
+ A delegated subagent publishes progress on its own child-session stream. The parent emits `subagent.called` with a `childSessionId`, which a client uses to attach. `subagent.completed` carries a working task receipt after admission; terminal outcomes arrive as task-triggered `message.received` notifications.
101
101
 
102
102
  `step.failed` and `turn.failed` carry `{ code, message, details? }` for the failed fragment or turn, and `session.failed` is the terminal session-level variant. `turn.cancelled` is not a failure: the cancelled turn ends without any failure event, `session.waiting` follows, and the session accepts the next message normally. Whatever the turn streamed before cancellation stays on the stream. Durable history keeps the accepted user input and previously settled work, but discards incomplete assistant output and unfinished tool state. When a turn requested an output schema, the finalized payload lands on `result.completed` as `data.result` before the turn boundary. `authorization.required` carries the sign-in challenge (`data.authorization` may include `url`, `userCode`, `expiresAt`, `instructions`), and `authorization.completed` carries `data.outcome` (`"authorized" | "declined" | "failed" | "timed-out"`).
103
103
 
104
+ A provider response ending with `content-filter` fails with `MODEL_CALL_FAILED`,
105
+ `details.semanticErrorId: "model-response-content-filtered"`, and
106
+ `details.finishReason: "content-filter"`. Details also include the Gateway
107
+ `generationId` when available. eve does not retry the filtered response or emit
108
+ `message.completed` for its partial text; deltas already streamed remain visible.
109
+ Conversation sessions wait for another user message, while task-mode runs return
110
+ a failed result.
111
+
104
112
  ## The event envelope
105
113
 
106
114
  Alongside `type` and `data`, every event carries a `meta` envelope:
@@ -87,7 +87,7 @@ Most chat UIs only need `data.messages` and `status`. Drop down to `events` when
87
87
 
88
88
  `data.messages` are eve-owned `EveMessage[]`. Common text, reasoning, file, and dynamic-tool parts follow the [AI SDK `UIMessage`](https://ai-sdk.dev/docs/reference/ai-sdk-core/ui-message) rendering convention, but the types are not interchangeable. eve also exposes authorization and HITL metadata, and a file part's URL can be absent. Adapt those parts before passing messages to an API typed as `UIMessage[]`.
89
89
 
90
- When the root agent delegates, its stream emits `subagent.called` with the child's `childSessionId`, then `subagent.completed` after admission with a working task receipt. Later task notifications wake the parent with updates or the final result. Detailed child progress lives on the child session's stream instead of being flattened into the root `data.messages`. Use the lower-level [TypeScript client](../client/overview#sessions) to attach to that ID when your UI needs live subagent activity. See [What the parent sees](../../subagents#what-the-parent-sees) for the complete contract.
90
+ When the root agent delegates, its stream emits `subagent.called` with the child's `childSessionId`, then `subagent.completed` after admission with a working task receipt. Later task notifications wake the parent with completion, failure, or cancellation. Detailed child progress lives on the child session's stream instead of being flattened into the root `data.messages`. Use the lower-level [TypeScript client](../client/overview#sessions) to attach to that ID when your UI needs live subagent activity. See [What the parent sees](../../subagents#what-the-parent-sees) for the complete contract.
91
91
 
92
92
  ## Sending and streaming
93
93
 
@@ -153,6 +153,8 @@ export default otelIntegration({
153
153
  });
154
154
  ```
155
155
 
156
+ Custom destinations receive the schema v4 agent trace contract. Follow [Query exported traces](./instrumentation#query-exported-traces) to find activations and join sessions across traces.
157
+
156
158
  Add `agent/instrumentation/otel.ts` when you need process-wide settings or want to control which content eve writes to OpenTelemetry spans:
157
159
 
158
160
  ```ts title="agent/instrumentation/otel.ts"
@@ -235,6 +237,9 @@ An ordinary tool emits both `action.*` and `tool.call.*` events. Use `action.*`
235
237
 
236
238
  Handlers for different providers run concurrently and are failure-isolated. Do not depend on provider execution order. Use `flush` to drain buffered records and `shutdown` to release resources.
237
239
 
240
+ The [agent trace contract](./instrumentation#agent-trace-contract) defines span
241
+ names, identities, and usage counters shared by the exporters and local viewers.
242
+
238
243
  ## What to read next
239
244
 
240
245
  - [Observability](./instrumentation): the default `instrumentation.ts` API and trace hierarchy
@@ -48,13 +48,15 @@ Use the `setup` callback to register your OTel provider (for example `registerOT
48
48
 
49
49
  Any OTel-compatible backend works (Braintrust, PostHog, Sentry, Raindrop, Arize, Honeycomb, Datadog, Jaeger). Install the exporter package you need and configure it in the callback. The [PostHog AI Observability integration](/integrations/posthog-instrumentation) provides a ready-to-install exporter and optional user identification. The [Sentry integration](/integrations/sentry-instrumentation) provides a ready-to-install OTLP exporter that sends traces to Sentry without a Sentry SDK.
50
50
 
51
- Three more fields control what the AI SDK records inside those spans (see the AI SDK's [telemetry reference](https://ai-sdk.dev/docs/ai-sdk-core/telemetry)):
51
+ Three more fields control what eve and the AI SDK record inside those spans (see the AI SDK's [telemetry reference](https://ai-sdk.dev/docs/ai-sdk-core/telemetry)):
52
52
 
53
- - `recordInputs` records full message history on each step span. It defaults to `false`; set it to `true` to include input content.
54
- - `recordOutputs` records model outputs on spans. It defaults to `false`; set it to `true` to include output content.
53
+ - `recordInputs` records full message history on each step span and recalled records on memory spans. It defaults to `false`; set it to `true` to include input content.
54
+ - `recordOutputs` records model outputs. It defaults to `false`; set it to `true` to include output content.
55
55
  - `functionId` overrides the function name on spans (defaults to the agent name).
56
56
 
57
- eve records metadata without model or tool inputs and outputs by default. Enable either content category only after reviewing the exporter and its data-retention path.
57
+ eve records metadata without model, tool, or memory-record content by default. Enable either content category only after reviewing the exporter and its data-retention path.
58
+
59
+ In the provider layout, eve stamps each span with `gen_ai.conversation.id`, which stays fixed across local and remote activations, including independent remote root workflows. Query this attribute to find the conversation's exported, retained traces; it does not grant access or control trace parenting. On Vercel, `vercel.session_id` additionally identifies the current Workflow run. See [Query exported traces](#query-exported-traces) for the cross-backend workflow.
58
60
 
59
61
  You are responsible for ensuring any observability or eval provider is approved for the data exported to it.
60
62
 
@@ -79,11 +81,9 @@ and outcome fields. Content providers additionally receive only eve's known
79
81
  message, context, input-response, and output-schema fields; adapter-specific
80
82
  payload fields are never projected.
81
83
 
82
- The built-in OpenTelemetry provider maps each pair to an
83
- `agent.channel.delivery` consumer span under the durable session window. When
84
- `traceChannelRequests: true` creates an inbound HTTP server span, the delivery
85
- span links to it with `eve.link.type=channel.request` rather than using the
86
- short-lived request span as its parent.
84
+ For a single delivery that starts a turn, the built-in OpenTelemetry provider records the channel kind, channel name, delivery ID, optional request ID, and captured input on that turn's `invoke_agent` activation. The activation remains a root in its own trace and links to the active upstream request or function span with `eve.link.type=channel.request`. Set `traceChannelRequests: true` to create an eve-owned HTTP server span as that link target; when the option is false, an already-active upstream span remains the target.
85
+
86
+ Deliveries that do not map one-to-one to an activation still produce instrumentation lifecycle events, but the built-in OpenTelemetry provider does not emit a separate delivery span.
87
87
 
88
88
  ## Callback delivery errors
89
89
 
@@ -103,19 +103,28 @@ not mark the active span as failed.
103
103
  The built-in OpenTelemetry provider preserves each span's OTel name and adds
104
104
  `operation.name` and `resource.name` for Datadog's operation/resource mapping:
105
105
 
106
- | OTel span name | `operation.name` | `resource.name` |
107
- | ------------------------------------------------------------------------------------------------------------------ | ----------------- | ---------------------- |
108
- | `invoke_agent weather` | `invoke_agent` | `invoke_agent weather` |
109
- | `execute_tool search` | `execute_tool` | `execute_tool search` |
110
- | `chat <model>` | `chat` | `chat <model>` |
111
- | `agent.session`, `agent.step`, `agent.action`, `agent.approval`, `agent.channel.delivery`, `agent.channel.request` | Same as span name | Same as span name |
106
+ | OTel span name | `operation.name` | `resource.name` |
107
+ | ----------------------------------------------------------------------- | ----------------- | ------------------------ |
108
+ | `invoke_agent weather` | `invoke_agent` | `invoke_agent weather` |
109
+ | `invoke_workflow deploy` | `invoke_workflow` | `invoke_workflow deploy` |
110
+ | `execute_tool search` | `execute_tool` | `execute_tool search` |
111
+ | `chat <model>` | `chat` | `chat <model>` |
112
+ | `search_memory`, `upsert_memory` | Same as span name | Same as span name |
113
+ | `agent.step`, `agent.action`, `agent.approval`, `agent.channel.request` | Same as span name | Same as span name |
112
114
 
113
- These attributes apply to eve-owned spans in local tracing and the
115
+ These rows apply to eve-owned spans in local tracing and the
114
116
  [instrumentation provider layout](./instrumentation-providers). They do not
115
117
  rename Workflow, AI SDK, or other third-party spans, or change trace IDs,
116
- parenting, sampling, or session grouping. Legacy `instrumentation.ts` setup
117
- still owns its exporter configuration and [authored trace
118
- hierarchy](#authored-trace-hierarchy).
118
+ parenting, or session grouping. Legacy `instrumentation.ts` setup still owns
119
+ its exporter configuration and [authored trace hierarchy](#authored-trace-hierarchy).
120
+
121
+ Workflow action spans enter the sampler as `agent.action`, with
122
+ `gen_ai.operation.name` and `gen_ai.workflow.name` already present. After
123
+ sampling, eve changes the exported span name to `invoke_workflow <tool>`.
124
+ Existing name-based samplers therefore keep their `agent.action` behavior;
125
+ attribute-based samplers can select GenAI workflow operations explicitly.
126
+ Review custom attribute rules when upgrading because the new workflow
127
+ attributes may change their decisions.
119
128
 
120
129
  In Datadog APM, `operation_name:invoke_agent resource_name:"invoke_agent weather"`
121
130
  selects named agent invocations. Operation-based dashboards and monitors may
@@ -137,6 +146,153 @@ that discard span events, including Sentry's [direct OTLP
137
146
  intake](https://docs.sentry.io/concepts/otlp/direct/traces/). These attributes
138
147
  remain available when model and tool content is redacted.
139
148
 
149
+ ## Memory spans
150
+
151
+ eve records [OpenTelemetry GenAI memory spans](https://opentelemetry.io/docs/specs/semconv/gen-ai/gen-ai-spans/#memory) for provider calls. Recalls at `turn.started` and `compaction.completed` use `search_memory`; capture handlers use `upsert_memory`. They are client spans, following the GenAI memory convention for a call to a memory system.
152
+
153
+ Every memory span includes `gen_ai.operation.name` and `gen_ai.memory.store.id`. The store ID is eve's opaque `memory.scope.key`, which identifies the resolved scope without exposing the namespace or scope values. Recall spans set `gen_ai.memory.record.count` to their result count.
154
+
155
+ `gen_ai.memory.records` contains recalled record content only when `recordInputs` is enabled. eve classifies recalled records as input content because they become part of the model context. eve does not set `gen_ai.memory.query.text` because a memory provider receives structured conversation messages, not a standalone search-query string. The `agent.memory.slot` and `agent.memory.phase` attributes identify the eve slot and lifecycle boundary without adding either to the span name.
156
+
157
+ ## Agent trace contract
158
+
159
+ The provider layout and zero-config local tracing emit the following spans.
160
+ The legacy `instrumentation.ts` layout still uses its authored OTel setup.
161
+
162
+ | Span | Meaning |
163
+ | ------------------------ | -------------------------------------------------------- |
164
+ | `invoke_agent <agent>` | One agent activation in its own trace |
165
+ | `agent.step` | One model attempt |
166
+ | `chat <model>` | One model call beneath its step |
167
+ | `invoke_workflow <tool>` | One workflow tool run that coordinated a nested agent |
168
+ | `agent.action` | Durable action lifecycle, including dispatch and waiting |
169
+ | `execute_tool <tool>` | In-process tool execution beneath its action |
170
+ | `agent.approval` | Approval waiting beneath its action |
171
+ | `search_memory` | Recall memory records before a turn or after compaction |
172
+ | `upsert_memory` | Automatic memory capture |
173
+ | `agent.channel.request` | Optional HTTP request span in the provider layout |
174
+
175
+ For background tools and subagents, the AI SDK's `execute_tool` span ends when
176
+ the model receives the task receipt. The enclosing `agent.action` span remains
177
+ open until the background task completes, fails, or is cancelled. When a
178
+ workflow tool coordinates a nested `ctx.agent()` call, eve exports that span as
179
+ `invoke_workflow` instead. Its duration, outcome, and usage describe the
180
+ background task rather than the receipt.
181
+ Background tool results follow the output-content policy. Recorded task failure
182
+ details become bounded exception and status messages; redacted spans retain only
183
+ the failure outcome, error status, and error type. The initiating turn can
184
+ finish or be cancelled while the action remains open. Ending the session closes
185
+ an action whose task never reported a terminal result.
186
+
187
+ Schema v4 removes the session-long `agent.session` root and duplicate agent session and lineage attributes. Every eve span carries `agent.trace.schema.version=4` and `gen_ai.conversation.id`; Vercel deployments additionally carry `vercel.session_id`.
188
+ Only activations use the `invoke_agent` operation. A workflow tool invocation
189
+ that coordinates at least one nested agent uses `invoke_workflow`, with its
190
+ path-derived tool name in `gen_ai.workflow.name`. Durable workflow tools without
191
+ agent operations, including `sleep`, remain `agent.action` spans. Dispatch
192
+ lifecycle spans use `agent.action` with
193
+ `agent.invocation.role=caller`; the built-in `agent` tool executes under
194
+ `execute_tool agent`. Turn IDs such as `turn_0` are local to a session, so
195
+ correlate turns by session ID and turn ID together.
196
+
197
+ A conversation remains durable state; `gen_ai.conversation.id` joins the activations that operate on it.
198
+
199
+ Each activation owns a fresh trace identity, including local and remote
200
+ subagents. The first child activation links to its caller with
201
+ `eve.link.type=agent.dispatch`; incoming `traceparent` provides that link, not
202
+ the child trace ID. Later turns do not reuse the original caller link.
203
+ Conversation baggage is independent of execution lineage and trace-policy
204
+ ceilings, which remain in force across the boundary.
205
+
206
+ Channel delivery does not allocate or replace the activation, and a later turn
207
+ receives a new trace. Samplers
208
+ see the activation name and attributes after its session coordinates are
209
+ available. Sampling must be deterministic for the same trace and operation
210
+ because durable reconstruction can evaluate it again.
211
+
212
+ Use `agent.turn.outcome` to distinguish completed, failed, and cancelled activations. A failed action can be handled by the agent without failing its activation; see [Exported span names and outcomes](#exported-span-names-and-outcomes).
213
+
214
+ Activation spans retain `gen_ai.usage.input_tokens` and
215
+ `gen_ai.usage.output_tokens` alongside `agent.usage.*` totals for that activation.
216
+ Model spans carry `gen_ai.usage.*`; step and dispatch spans report
217
+ `agent.usage.*`. Activation totals summarize that activation's own model calls, while caller spans can summarize delegated usage. Do not sum usage across these levels.
218
+
219
+ Nested dispatch spans are materialized when the child settles and handed to
220
+ span processors; successful materialization removes their completed records
221
+ from durable state. Settlement does not drain exporters or authored providers.
222
+ Materialization failures are logged without failing settlement, and exporter
223
+ draining follows the runtime's normal flush lifecycle.
224
+
225
+ Cancelled or abandoned dispatches retain
226
+ their outcome without error status. Error messages and stacks on eve spans count as
227
+ output content, including errors reconstructed after a worker replacement.
228
+ Metadata-only capture retains failure status without those details. Error logging
229
+ outside eve's instrumented execution retains its existing exception content.
230
+
231
+ Agent Runs activation metadata includes bounded principal summaries:
232
+
233
+ - `agent.principal.current.type` and `agent.principal.current.id` describe the current caller.
234
+ - `agent.principal.initiator.type` and `agent.principal.initiator.id` describe the authenticated principal that created the root session. The initiator remains fixed when later turns have a different caller.
235
+
236
+ Types are limited to `user`, `service`, `runtime`, `app`, `anonymous`, `local-dev`, `unknown`, `none`, and `other`. Types are emitted for every audience when a principal is present. An absent type means no authentication context was set; `none` means an explicitly null principal and has no ID. The auth layer's `unknown` type stays `unknown`; unrecognized authored types become `other`.
237
+
238
+ Principal IDs require a content-visible audience and a resolved trace decision that allows both `recordInputs` and `recordOutputs`. Public turns and unknown turns under `eve dev` can include IDs; private and hosted-unknown turns omit them. A user-configured trace policy or forwarded content ceiling that denies either direction omits both principal IDs before turn state is stored or sampled. Empty IDs and IDs larger than 1 KiB of UTF-8 data are omitted, not truncated; authentication records are unchanged. eve does not copy other authentication fields, such as claims, email attributes, issuers, or subjects, into these summaries.
239
+
240
+ ## Query exported traces
241
+
242
+ Use a trace to investigate one activation's work. Use session and conversation attributes to find the other activations. Exporting to an OpenTelemetry backend does not turn a conversation into one continuous waterfall.
243
+
244
+ This workflow applies to schema v4 from the [instrumentation provider layout](./instrumentation-providers). Configure third-party exporters through `otelIntegration()` so they receive the same framework spans as local tracing and Agent Runs. The legacy `instrumentation.ts` setup emits the [authored trace hierarchy](#authored-trace-hierarchy), not this contract.
245
+
246
+ ### Find an activation or conversation
247
+
248
+ | Investigation | Filter |
249
+ | ------------------------ | ----------------------------------------------------------------------- |
250
+ | Agent activations | `agent.trace.schema.version=4` and `gen_ai.operation.name=invoke_agent` |
251
+ | One logical conversation | `gen_ai.conversation.id=<conversation ID>` |
252
+ | One turn | Both `gen_ai.conversation.id` and `agent.turn.id` |
253
+ | One Vercel Workflow run | `vercel.session_id=<session ID>` |
254
+ | Delegated dispatches | `agent.invocation.role=caller` |
255
+
256
+ Start with an activation filter for latency, failure, or turn-count dashboards. Every activation is a trace root. Within a conversation, group by trace ID, order activations by `agent.turn.sequence` or start time, and open the selected trace ID. Child activations link to their caller with `eve.link.type=agent.dispatch`; remote workflows keep their own execution lineage, so use conversation IDs and caller links for cross-deployment correlation.
257
+
258
+ For example, the built-in `agent` tool dispatches research into a new workflow and trace, and the next user turn starts another trace:
259
+
260
+ ```text
261
+ Trace A
262
+ invoke_agent support session=S, turn=turn_0, conversation=S
263
+ agent.step
264
+ chat <model>
265
+ agent.action role=caller, action.call_id=C
266
+ execute_tool agent
267
+
268
+ Trace B
269
+ invoke_agent research session=R, turn=turn_0, conversation=S
270
+ link: agent.dispatch -> Trace A's caller action C
271
+ agent.step
272
+ chat <model>
273
+
274
+ Trace C
275
+ invoke_agent support session=S, turn=turn_1, conversation=S
276
+ agent.step
277
+ chat <model>
278
+ ```
279
+
280
+ The conversation filter finds all three retained traces. eve initializes the conversation ID once and carries it through the existing parent context for local dispatch and `eve.conversation.id` baggage for remote dispatch. Remote session creation does not carry execution lineage or add authorization requirements for tracing. Existing authentication, principal forwarding, and root-session limits remain unchanged.
281
+
282
+ `traceparent` carries the caller's trace and span IDs for the causal link; adopting it as the child's parent would instead keep both in the same trace. Resolved trace-policy decisions and trusted remote content ceilings continue across this boundary independently of correlation, and an unsampled caller cannot be widened into a sampled child. No synthetic session span is needed.
283
+
284
+ Activation duration is elapsed time for that activation, including waits inside it, not the lifetime of the conversation or CPU time. Idle time between ended activations is not part of their durations. For token totals, choose one level: filter to `chat` model spans and sum `gen_ai.usage.*`, or filter to activations and sum their `agent.usage.input_tokens` and `agent.usage.output_tokens`. Exclude caller summaries from the activation total. Query cache usage on model spans. Do not add model, step, activation, and caller counters together.
285
+
286
+ ### Search traces
287
+
288
+ Use your destination's span-search surface to filter by the attributes in the table, group activations by session or trace ID, and open one activation's trace waterfall. Use the OTel span name and `gen_ai.operation.name` to identify the operation. Preserve eve's ownership of the OTel provider; do not register a second provider merely to add a destination.
289
+
290
+ ### Sampling and completeness
291
+
292
+ A session can contain both retained and missing activation traces. Head sampling, backend retention, destination filtering, and exporter failures all affect what a conversation query returns. Preserve the schema and correlation attributes in Collector transforms and destination policies, and configure indexing and retention for the queries above.
293
+
294
+ Do not interpret a missing activation as a missing execution, or sampled trace counts and token sums as an exact session ledger. A backend may receive descendants before the activation span finishes and exports; a temporarily missing root is not necessarily a broken parent ID. After deployment, verify a two-turn conversation and a delegation in the actual destination, including names, conversation grouping across services, separate trace roots, caller links, and outcome attributes.
295
+
140
296
  ## Runtime context
141
297
 
142
298
  _Runtime context_ is an [AI SDK concept](https://ai-sdk.dev/docs/reference/ai-sdk-core/stream-text): a user-defined object that flows through a generation lifecycle. eve exposes it through `events["step.started"]`, a callback that runs once eve has assembled the model input for an attempt and returns `{ runtimeContext }`. Because eve registers the AI SDK's OpenTelemetry integration with runtime context enabled, those returned values ride onto the model-call span and its children. The field is named `runtimeContext`, not `metadata`, because AI SDK v7 carries per-call attributes on runtime context rather than a dedicated metadata field.
@@ -198,7 +354,7 @@ eve creates the `ai.eve.turn` parent span per turn and passes enriched telemetry
198
354
 
199
355
  This hierarchy applies when eve passes telemetry to the AI SDK. When the `otel()` provider layout is declared and eve owns the agent spans, eve names its invocation span `invoke_agent <agent>` and its model-attempt spans `agent.step`. Session, turn, step, and channel context is injected as the framework half of the runtime context (`eve.version`, `eve.session.id`, `eve.environment`, `eve.turn.id`, `eve.turn.sequence`, `eve.step.index`, `eve.channel.kind`) and rides onto the spans alongside any values your `events["step.started"]` callback returns under `runtimeContext`.
200
356
 
201
- Set `traceChannelRequests: true` on `defineInstrumentation` to also wrap each inbound channel HTTP request in a single OpenTelemetry `SERVER` span named for the registered route, which parents the turn tree above (and any `hook.resume` and outgoing HTTP spans):
357
+ Set `traceChannelRequests: true` on `defineInstrumentation` to also wrap each inbound channel HTTP request in a single OpenTelemetry `SERVER` span named for the registered route. In the authored hierarchy above, this span parents the turn tree and any `hook.resume` or outgoing HTTP spans. In the provider layout, `invoke_agent` remains a separate trace root and links to the request span.
202
358
 
203
359
  ```text
204
360
  POST /eve/v1/session/:sessionId
@@ -224,7 +380,7 @@ Structural tags describe each run's place in the tree:
224
380
  - `$eve.trigger`: the channel kind that started the run
225
381
  - `$eve.schedule`: the authored schedule that created the session, including sessions started through a target channel
226
382
  - `$eve.title`: truncated title derived from the first user message
227
- - `$eve.trace_id`: trace id of the sampled agent trace containing the run, written on session, subagent, and turn rows so a dashboard run can be joined to its OpenTelemetry trace. Present only when the trace is sampled; absence means no exported OTEL trace exists.
383
+ - `$eve.trace_id`: sampled trace seed available when tagging a session, subagent, or turn run. Use it as a trace link, not a conversation-wide trace identity. Later activations can use other trace IDs; query `gen_ai.conversation.id` for the history. The tag does not confirm that a destination retained the trace.
228
384
 
229
385
  Per-turn usage tags are written on each step of a turn, accumulating cumulative totals (last write wins):
230
386
 
@@ -238,12 +394,12 @@ These tags power the **Agent Runs** tab in the Vercel dashboard. When you deploy
238
394
 
239
395
  ## Local traces
240
396
 
241
- Without an `instrumentation.ts`, `eve dev` records spans to disk — one trace per session, with turns, model steps, and tool calls. Read them two ways:
397
+ Without an `instrumentation.ts`, `eve dev` records spans to disk with one bounded trace per turn, including its model steps and tool calls. Read them two ways:
242
398
 
243
399
  - [`/traces`](dev-tui#logs-and-traces) in the dev TUI: a live trace viewer that replays captured content as a conversation.
244
400
  - [`eve traces`](../reference/cli#eve-traces): a span tree in the terminal, `eve traces ls` to list. Works after `eve dev` exits.
245
401
 
246
- Local traces omit model and tool inputs and outputs by default. Set `EVE_TRACES_CONTENT=on` in `.env.local` to capture that content.
402
+ Local traces omit model, tool, and memory-record content by default. Set `EVE_TRACES_CONTENT=on` in `.env.local` to capture that content.
247
403
 
248
404
  Writing `instrumentation.ts` replaces this: your `setup` takes over and nothing is recorded locally. For span attributes, retention, and the `EVE_TRACES*` variables, see [`eve traces`](../reference/cli#eve-traces).
249
405