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.
- package/CHANGELOG.md +32 -0
- package/dist/src/channel/types.d.ts +2 -0
- package/dist/src/chunks/{use-eve-agent-BR8EpIOX.js → use-eve-agent-CxPlg0KL.js} +0 -1
- package/dist/src/chunks/{use-eve-agent-XnfjQt1Z.js → use-eve-agent-D-KQzzyW.js} +0 -1
- package/dist/src/cli/commands/trace-detail.js +1 -1
- package/dist/src/cli/commands/trace.d.ts +2 -2
- package/dist/src/cli/commands/trace.js +3 -3
- package/dist/src/cli/dev/tui/runner.js +1 -1
- package/dist/src/cli/dev/tui/tool-presentation.js +1 -1
- package/dist/src/cli/dev/tui/traces/trace-content.d.ts +1 -3
- package/dist/src/cli/dev/tui/traces/trace-content.js +2 -2
- package/dist/src/cli/dev/tui/traces/trace-conversation.d.ts +5 -5
- package/dist/src/cli/dev/tui/traces/trace-conversation.js +1 -1
- package/dist/src/cli/dev/tui/traces/trace-view.js +1 -1
- package/dist/src/cli/dev/tui/traces/trace-viewer-session.js +1 -1
- package/dist/src/client/agent-info-schema.d.ts +0 -1
- package/dist/src/client/agent-info-schema.js +1 -1
- package/dist/src/compiled/.vendor-stamp.json +1 -1
- package/dist/src/compiled/@opentelemetry/api/index.d.ts +1 -0
- package/dist/src/compiler/default-tool-policy.js +1 -1
- package/dist/src/compiler/extension-compatibility.d.ts +4 -4
- package/dist/src/compiler/extension-compatibility.js +1 -1
- package/dist/src/compiler/manifest.js +1 -1
- package/dist/src/context/dynamic-instruction-lifecycle.d.ts +2 -1
- package/dist/src/context/dynamic-instruction-lifecycle.js +1 -1
- package/dist/src/context/keys.d.ts +3 -1
- package/dist/src/context/keys.js +1 -1
- package/dist/src/context/memory-event-lifecycle.d.ts +2 -0
- package/dist/src/context/memory-event-lifecycle.js +1 -1
- package/dist/src/context/memory-lifecycle.d.ts +5 -0
- package/dist/src/context/memory-lifecycle.js +1 -1
- package/dist/src/eve-channel/index.js +1 -1
- package/dist/src/execution/cancelled-model-call-batch.js +1 -1
- package/dist/src/execution/cancelled-turn-message.js +1 -1
- package/dist/src/execution/compaction.d.ts +2 -2
- package/dist/src/execution/coordination-dispatch-shared.d.ts +0 -1
- package/dist/src/execution/coordination-dispatch-shared.js +1 -1
- package/dist/src/execution/coordination-dispatch-step.js +1 -1
- package/dist/src/execution/create-session-step.js +1 -1
- package/dist/src/execution/durable-session-store.d.ts +2 -2
- package/dist/src/execution/eve-workflow-attributes.d.ts +3 -3
- package/dist/src/execution/next-driver-action.d.ts +2 -0
- package/dist/src/execution/parked-delivery-wait.js +1 -1
- package/dist/src/execution/route-child-delivery.js +1 -1
- package/dist/src/execution/runtime-context.js +1 -1
- package/dist/src/execution/session.d.ts +0 -2
- package/dist/src/execution/session.js +2 -2
- package/dist/src/execution/tasks/parent/dispatch.d.ts +1 -12
- package/dist/src/execution/tasks/parent/dispatch.js +1 -1
- package/dist/src/execution/tasks/parent/hitl-proxy-steps.d.ts +5 -1
- package/dist/src/execution/tasks/parent/hitl-proxy-steps.js +1 -1
- package/dist/src/execution/tasks/parent/tool-execution.js +1 -1
- package/dist/src/execution/tools/sleep-workflow.js +1 -1
- package/dist/src/execution/tools/subagent/invoke-agent.d.ts +1 -2
- package/dist/src/execution/tools/subagent/invoke-agent.js +1 -1
- package/dist/src/execution/tools/subagent/invoke-step.d.ts +4 -0
- package/dist/src/execution/tools/subagent/invoke-step.js +1 -1
- package/dist/src/execution/tools/subagent/start.d.ts +2 -2
- package/dist/src/execution/tools/subagent/start.js +1 -1
- package/dist/src/execution/tools/subagent/task-agent-requests.js +1 -1
- package/dist/src/execution/tools/tasks.d.ts +1 -8
- package/dist/src/execution/tools/tasks.js +1 -1
- package/dist/src/execution/tools/todo.d.ts +2 -2
- package/dist/src/execution/tools/todo.js +2 -2
- package/dist/src/execution/turn-workflow.js +1 -1
- package/dist/src/execution/workflow-runtime.js +1 -1
- package/dist/src/execution/workflow-steps.js +1 -1
- package/dist/src/framework/sources/registry.js +1 -1
- package/dist/src/harness/compaction.js +1 -1
- package/dist/src/harness/coordination.js +1 -1
- package/dist/src/harness/current-messages.d.ts +7 -6
- package/dist/src/harness/current-messages.js +1 -1
- package/dist/src/harness/emission.js +1 -1
- package/dist/src/harness/execute-tool.d.ts +2 -4
- package/dist/src/harness/messages.d.ts +36 -0
- package/dist/src/harness/messages.js +1 -1
- package/dist/src/harness/model-call-error.d.ts +5 -0
- package/dist/src/harness/model-call-error.js +1 -1
- package/dist/src/harness/semantic-errors/rules/model-provider.js +1 -1
- package/dist/src/harness/session-limit-enforcement.d.ts +2 -15
- package/dist/src/harness/step-hooks.d.ts +2 -1
- package/dist/src/harness/step-hooks.js +1 -1
- package/dist/src/harness/tool-loop.js +2 -2
- package/dist/src/harness/types.d.ts +6 -4
- package/dist/src/instrumentation/ai-sdk-hook-bridge.js +1 -1
- package/dist/src/instrumentation/background-task-runtime.d.ts +18 -0
- package/dist/src/instrumentation/background-task-runtime.js +1 -0
- package/dist/src/instrumentation/channel-delivery.js +1 -1
- package/dist/src/instrumentation/content.js +1 -1
- package/dist/src/instrumentation/dispatch.js +1 -1
- package/dist/src/instrumentation/lifecycle.d.ts +19 -2
- package/dist/src/instrumentation/lifecycle.js +1 -1
- package/dist/src/instrumentation/memory.d.ts +72 -0
- package/dist/src/instrumentation/memory.js +1 -0
- package/dist/src/instrumentation/native-events.d.ts +7 -0
- package/dist/src/instrumentation/native-events.js +1 -1
- package/dist/src/instrumentation/parent-lineage.d.ts +2 -2
- package/dist/src/instrumentation/parent-lineage.js +1 -1
- package/dist/src/instrumentation/prepare-trace-context.d.ts +3 -11
- package/dist/src/instrumentation/prepare-trace-context.js +1 -1
- package/dist/src/instrumentation/principal-summary.d.ts +11 -0
- package/dist/src/instrumentation/principal-summary.js +1 -0
- package/dist/src/instrumentation/provider.d.ts +1 -0
- package/dist/src/instrumentation/runtime.d.ts +11 -7
- package/dist/src/instrumentation/runtime.js +1 -1
- package/dist/src/instrumentation/session-context.d.ts +22 -0
- package/dist/src/instrumentation/session-context.js +1 -0
- package/dist/src/instrumentation/state.d.ts +7 -2
- package/dist/src/instrumentation/state.js +1 -1
- package/dist/src/internal/application/package.js +1 -1
- package/dist/src/internal/logging.js +1 -1
- package/dist/src/internal/nitro/routes/channel-dispatch.js +1 -1
- package/dist/src/internal/nitro/routes/channel-request-instrumentation.d.ts +4 -5
- package/dist/src/internal/nitro/routes/channel-request-instrumentation.js +1 -1
- package/dist/src/protocol/baggage.d.ts +15 -2
- package/dist/src/protocol/baggage.js +1 -1
- package/dist/src/public/instrumentation/index.d.ts +5 -4
- package/dist/src/runtime/agent/bootstrap.d.ts +2 -2
- package/dist/src/runtime/agent/bootstrap.js +1 -1
- package/dist/src/self-modification/agent.js +1 -1
- package/dist/src/self-modification/extension/instructions.js +21 -20
- package/dist/src/self-modification/extension/tools/edit_file.js +1 -1
- package/dist/src/self-modification/extension/tools/search_registry.d.ts +1 -1
- package/dist/src/self-modification/extension/tools/search_registry.js +1 -1
- package/dist/src/setup/integrations/self-modification/setup.js +1 -1
- package/dist/src/setup/scaffold/create/project.js +1 -1
- package/dist/src/shared/action-types.d.ts +4 -0
- package/dist/src/shared/action-types.js +1 -1
- package/dist/src/shared/dispatch-action.d.ts +1 -1
- package/dist/src/shared/memory-state.js +1 -1
- package/dist/src/shared/serialized-observability-state.d.ts +12 -0
- package/dist/src/shared/serialized-observability-state.js +1 -0
- package/dist/src/subagents/callback-route.js +1 -1
- package/dist/src/subagents/callback-step.d.ts +0 -8
- package/dist/src/subagents/callback-step.js +1 -1
- package/dist/src/subagents/invocation.d.ts +9 -0
- package/dist/src/subagents/remote-dispatch.d.ts +3 -3
- package/dist/src/subagents/remote-dispatch.js +1 -1
- package/dist/src/subagents/start-local.d.ts +2 -6
- package/dist/src/subagents/start-local.js +1 -1
- package/dist/src/subagents/start-remote.d.ts +2 -8
- package/dist/src/subagents/start-remote.js +1 -1
- package/dist/src/subagents/tool.d.ts +3 -13
- package/dist/src/subagents/tool.js +1 -1
- package/dist/src/svelte/index.js +1 -1
- package/dist/src/svelte/use-eve-agent.js +1 -1
- package/dist/src/tasks/delivery-context.d.ts +12 -3
- package/dist/src/tasks/delivery-context.js +2 -2
- package/dist/src/tasks/session-index.d.ts +6 -3
- package/dist/src/tasks/session-index.js +1 -1
- package/dist/src/tasks/session-task-cohorts.d.ts +10 -2
- package/dist/src/tasks/session-task-cohorts.js +1 -1
- package/dist/src/tools/behavior.d.ts +1 -3
- package/dist/src/tools/framework/task-contract.d.ts +0 -4
- package/dist/src/tools/framework/task-contract.js +1 -1
- package/dist/src/tracing/agent-action-instrumentation.d.ts +3 -2
- package/dist/src/tracing/agent-action-instrumentation.js +1 -1
- package/dist/src/tracing/agent-approval-instrumentation.js +1 -1
- package/dist/src/tracing/agent-channel-delivery-instrumentation.d.ts +1 -6
- package/dist/src/tracing/agent-channel-delivery-instrumentation.js +1 -1
- package/dist/src/tracing/agent-invocation-coordinator.d.ts +28 -0
- package/dist/src/tracing/agent-invocation-coordinator.js +1 -0
- package/dist/src/tracing/agent-invocation-terminal.d.ts +18 -0
- package/dist/src/tracing/agent-invocation-terminal.js +1 -0
- package/dist/src/tracing/agent-memory-instrumentation.d.ts +13 -0
- package/dist/src/tracing/agent-memory-instrumentation.js +1 -0
- package/dist/src/tracing/agent-otel-attributes.d.ts +4 -0
- package/dist/src/tracing/agent-otel-attributes.js +1 -0
- package/dist/src/tracing/agent-otel-content.d.ts +4 -12
- package/dist/src/tracing/agent-otel-content.js +3 -3
- package/dist/src/tracing/agent-otel-provider.d.ts +4 -6
- package/dist/src/tracing/agent-otel-provider.js +2 -2
- package/dist/src/tracing/agent-otel-runtime-context.d.ts +9 -0
- package/dist/src/tracing/agent-otel-runtime-context.js +1 -1
- package/dist/src/tracing/agent-otel-session-context.d.ts +4 -3
- package/dist/src/tracing/agent-otel-session-context.js +1 -1
- package/dist/src/tracing/agent-otel-usage.d.ts +4 -10
- package/dist/src/tracing/agent-otel-usage.js +1 -1
- package/dist/src/tracing/agent-span-contract.d.ts +26 -0
- package/dist/src/tracing/agent-span-contract.js +1 -0
- package/dist/src/tracing/agent-span-error.d.ts +3 -0
- package/dist/src/tracing/agent-span-error.js +1 -0
- package/dist/src/tracing/agent-span-id-generator.d.ts +3 -0
- package/dist/src/tracing/agent-span-id-generator.js +1 -1
- package/dist/src/tracing/agent-tool-instrumentation.js +1 -1
- package/dist/src/tracing/agent-trace-context-codec.d.ts +12 -0
- package/dist/src/tracing/agent-trace-context-codec.js +1 -0
- package/dist/src/tracing/agent-trace-context-store.d.ts +35 -8
- package/dist/src/tracing/agent-trace-context-store.js +1 -1
- package/dist/src/tracing/agent-trace-span-processor.d.ts +5 -7
- package/dist/src/tracing/agent-trace-span-processor.js +1 -1
- package/dist/src/tracing/agent-trace-state.d.ts +43 -3
- package/dist/src/tracing/agent-trace-state.js +1 -1
- package/dist/src/tracing/bounded-error.d.ts +1 -0
- package/dist/src/tracing/bounded-error.js +1 -0
- package/dist/src/tracing/content-attributes.js +1 -1
- package/dist/src/tracing/content-span-processor.js +1 -1
- package/dist/src/tracing/conversation-context.d.ts +4 -0
- package/dist/src/tracing/conversation-context.js +1 -0
- package/dist/src/tracing/error-content-context.d.ts +3 -0
- package/dist/src/tracing/error-content-context.js +1 -0
- package/dist/src/tracing/install-instrumentation-runtime.js +1 -1
- package/dist/src/tracing/local-trace-reader.d.ts +6 -6
- package/dist/src/tracing/local-trace-reader.js +1 -1
- package/dist/src/tracing/local-traces.d.ts +6 -8
- package/dist/src/tracing/local-traces.js +1 -1
- package/dist/src/tracing/otel-declaration.d.ts +5 -3
- package/dist/src/tracing/otel-registration.d.ts +2 -1
- package/dist/src/tracing/otel-registration.js +1 -1
- package/dist/src/tracing/telemetry-budget.d.ts +4 -0
- package/dist/src/tracing/telemetry-budget.js +1 -0
- package/dist/src/vue/index.js +1 -1
- package/dist/src/vue/use-eve-agent.js +1 -1
- package/docs/concepts/built-in-tools.md +0 -20
- package/docs/concepts/sessions-runs-and-streaming.md +9 -1
- package/docs/guides/frontend/overview.mdx +1 -1
- package/docs/guides/instrumentation-providers.md +5 -0
- package/docs/guides/instrumentation.md +179 -23
- package/docs/guides/remote-agents.md +11 -0
- package/docs/reference/cli.md +16 -14
- package/docs/subagents/index.mdx +15 -10
- package/package.json +1 -6
- package/dist/src/execution/tasks/child/update-step.d.ts +0 -6
- package/dist/src/execution/tasks/child/update-step.js +0 -1
- package/dist/src/execution/tasks/child/update.d.ts +0 -8
- package/dist/src/execution/tasks/child/update.js +0 -1
- package/dist/src/public/tools/task-update.d.ts +0 -1
- package/dist/src/public/tools/task-update.js +0 -1
- package/dist/src/tools/framework/task-update.d.ts +0 -5
- package/dist/src/tools/framework/task-update.js +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
import{normalizeChannelAudience}from"#shared/channel-audience.js";import{
|
|
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 @@
|
|
|
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{
|
|
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
|
-
/**
|
|
35
|
-
readonly
|
|
34
|
+
/** Conversation that owns the trace, which is the one the list shows. */
|
|
35
|
+
readonly conversationId?: string;
|
|
36
36
|
/**
|
|
37
|
-
* Every
|
|
37
|
+
* Every conversation identifier recorded in the trace.
|
|
38
38
|
*
|
|
39
|
-
* A
|
|
40
|
-
*
|
|
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
|
|
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,`
|
|
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
|
|
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
|
-
|
|
13
|
+
releaseConversation(conversationId: string): Promise<boolean>;
|
|
16
14
|
}
|
|
17
15
|
/**
|
|
18
|
-
* Reports whether a processor tracks which
|
|
19
|
-
* tell it when that
|
|
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
|
|
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 `
|
|
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
|
|
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
|
|
32
|
-
* request
|
|
33
|
-
*
|
|
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
|
|
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};
|
package/dist/src/vue/index.js
CHANGED
|
@@ -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 `<eve-empty-delivery/>` 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;
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
83
|
-
|
|
84
|
-
|
|
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
|
|
107
|
-
|
|
|
108
|
-
| `invoke_agent weather`
|
|
109
|
-
| `
|
|
110
|
-
| `
|
|
111
|
-
| `
|
|
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
|
|
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,
|
|
117
|
-
|
|
118
|
-
|
|
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,
|
|
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`:
|
|
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
|
|
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
|
|
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
|
|