eve 0.54.5 → 0.55.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (175) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/dist/src/channel/adapter.d.ts +3 -2
  3. package/dist/src/channel/audience.d.ts +16 -0
  4. package/dist/src/channel/audience.js +1 -0
  5. package/dist/src/channel/conversation-context.d.ts +3 -0
  6. package/dist/src/channel/conversation-context.js +1 -0
  7. package/dist/src/channel/instrumentation.js +1 -1
  8. package/dist/src/channel/types.d.ts +9 -0
  9. package/dist/src/cli/commands/agent-prompt/scaffold.md +5 -4
  10. package/dist/src/cli/commands/init-target.js +2 -2
  11. package/dist/src/cli/commands/init.js +1 -1
  12. package/dist/src/cli/dev/environment.js +1 -1
  13. package/dist/src/cli/dev/tui/terminal-renderer.js +9 -9
  14. package/dist/src/compiled/.vendor-stamp.json +1 -1
  15. package/dist/src/compiler/extension-compatibility.d.ts +16 -16
  16. package/dist/src/compiler/extension-compatibility.js +1 -1
  17. package/dist/src/context/dynamic-resolve-context.js +1 -1
  18. package/dist/src/discover/filesystem.d.ts +3 -1
  19. package/dist/src/discover/filesystem.js +1 -1
  20. package/dist/src/discover/skills.js +1 -1
  21. package/dist/src/dynamic/definition.d.ts +6 -0
  22. package/dist/src/eve-channel/audience.d.ts +3 -0
  23. package/dist/src/eve-channel/audience.js +1 -0
  24. package/dist/src/eve-channel/index.js +1 -1
  25. package/dist/src/eve-channel/types.d.ts +14 -1
  26. package/dist/src/execution/activity-work.d.ts +2 -0
  27. package/dist/src/execution/activity-work.js +1 -1
  28. package/dist/src/execution/channel-context.js +1 -1
  29. package/dist/src/execution/coordination-dispatch-shared.d.ts +1 -0
  30. package/dist/src/execution/coordination-dispatch-shared.js +1 -1
  31. package/dist/src/execution/eve-workflow-attributes.js +1 -1
  32. package/dist/src/execution/runtime-context.js +1 -1
  33. package/dist/src/execution/scheduled-launch-delivery.d.ts +7 -0
  34. package/dist/src/execution/scheduled-launch-delivery.js +1 -0
  35. package/dist/src/execution/session-activity.js +1 -1
  36. package/dist/src/execution/tasks/child/steps.js +1 -1
  37. package/dist/src/execution/tasks/parent/delegate.d.ts +2 -0
  38. package/dist/src/execution/tasks/parent/tool-execution.js +1 -1
  39. package/dist/src/execution/tools/sleep-workflow.js +1 -1
  40. package/dist/src/execution/tools/subagent/invoke-step.d.ts +2 -0
  41. package/dist/src/execution/tools/subagent/invoke-step.js +1 -1
  42. package/dist/src/execution/tools/subagent/start.d.ts +5 -0
  43. package/dist/src/execution/tools/subagent/start.js +1 -1
  44. package/dist/src/execution/wire/session-inbox-contract.d.ts +2 -2
  45. package/dist/src/execution/wire/session-inbox-contract.js +1 -1
  46. package/dist/src/execution/wire/session-inbox-encoder.d.ts +6 -2
  47. package/dist/src/execution/wire/session-inbox-encoder.js +1 -1
  48. package/dist/src/execution/wire/session-inbox-resume.js +1 -1
  49. package/dist/src/execution/wire/session-inbox-wire.js +1 -1
  50. package/dist/src/execution/wire/session-inbox-wire.v7.d.ts +342 -0
  51. package/dist/src/execution/wire/session-inbox-wire.v7.js +1 -0
  52. package/dist/src/execution/workflow-steps.js +1 -1
  53. package/dist/src/harness/action-presentation.d.ts +5 -0
  54. package/dist/src/harness/action-presentation.js +1 -1
  55. package/dist/src/harness/background-tools.d.ts +3 -1
  56. package/dist/src/harness/emission.js +1 -1
  57. package/dist/src/harness/step-hooks.js +1 -1
  58. package/dist/src/harness/tool-loop.js +1 -1
  59. package/dist/src/harness/tools.js +1 -1
  60. package/dist/src/harness/workflow-lifecycle.js +1 -1
  61. package/dist/src/instrumentation/channel-delivery.js +1 -1
  62. package/dist/src/instrumentation/content-policy.d.ts +2 -2
  63. package/dist/src/instrumentation/principal-summary.d.ts +3 -3
  64. package/dist/src/instrumentation/runtime-global.d.ts +4 -0
  65. package/dist/src/instrumentation/runtime-global.js +1 -0
  66. package/dist/src/instrumentation/runtime.d.ts +5 -9
  67. package/dist/src/instrumentation/runtime.js +1 -1
  68. package/dist/src/instrumentation/session-context.d.ts +1 -0
  69. package/dist/src/instrumentation/session-context.js +1 -1
  70. package/dist/src/instrumentation/session-init.d.ts +5 -0
  71. package/dist/src/instrumentation/session-init.js +1 -0
  72. package/dist/src/instrumentation/setup-context.js +1 -1
  73. package/dist/src/internal/application/dev-environment.d.ts +3 -0
  74. package/dist/src/internal/application/dev-environment.js +1 -1
  75. package/dist/src/internal/application/output-publication-journal.js +1 -1
  76. package/dist/src/internal/application/output-publication-lock.js +1 -1
  77. package/dist/src/internal/application/package.js +1 -1
  78. package/dist/src/internal/authored-definition/connection.js +1 -1
  79. package/dist/src/internal/instrumentation.d.ts +1 -12
  80. package/dist/src/internal/instrumentation.js +1 -1
  81. package/dist/src/internal/logging.js +1 -1
  82. package/dist/src/internal/nitro/host/build-application.js +1 -1
  83. package/dist/src/protocol/activity.d.ts +1 -0
  84. package/dist/src/protocol/activity.js +1 -1
  85. package/dist/src/public/channels/chat-sdk/audience.d.ts +8 -0
  86. package/dist/src/public/channels/chat-sdk/audience.js +1 -1
  87. package/dist/src/public/channels/chat-sdk/chatSdkChannel.d.ts +0 -2
  88. package/dist/src/public/channels/chat-sdk/chatSdkChannel.js +1 -1
  89. package/dist/src/public/channels/discord/audience.js +1 -1
  90. package/dist/src/public/channels/discord/discordChannel.js +1 -1
  91. package/dist/src/public/channels/discord/index.d.ts +0 -1
  92. package/dist/src/public/channels/index.d.ts +2 -3
  93. package/dist/src/public/channels/slack/activity-plan.js +1 -1
  94. package/dist/src/public/channels/slack/defaults.d.ts +2 -2
  95. package/dist/src/public/channels/slack/index.d.ts +1 -1
  96. package/dist/src/public/channels/slack/slackChannel.d.ts +11 -3
  97. package/dist/src/public/channels/slack/slackChannel.js +1 -1
  98. package/dist/src/public/channels/teams/hitl.js +1 -1
  99. package/dist/src/public/channels/teams/index.d.ts +0 -1
  100. package/dist/src/public/channels/teams/teamsChannel.js +1 -1
  101. package/dist/src/public/channels/teams/verify.js +1 -1
  102. package/dist/src/public/channels/telegram/audience.d.ts +7 -0
  103. package/dist/src/public/channels/telegram/audience.js +1 -1
  104. package/dist/src/public/channels/telegram/index.d.ts +0 -1
  105. package/dist/src/public/channels/telegram/telegramChannel.js +1 -1
  106. package/dist/src/public/channels/twilio/twilioChannel.d.ts +0 -2
  107. package/dist/src/public/channels/twilio/twilioChannel.js +1 -1
  108. package/dist/src/public/definitions/channel.d.ts +2 -1
  109. package/dist/src/public/definitions/channel.js +1 -1
  110. package/dist/src/public/definitions/connections/mcp.d.ts +6 -0
  111. package/dist/src/public/definitions/workspace-agent.js +1 -1
  112. package/dist/src/public/models/openai/chatgpt/auth.js +1 -1
  113. package/dist/src/public/models/openai/chatgpt/codex-app-server.js +1 -1
  114. package/dist/src/public/models/openai/chatgpt/credential-store.js +1 -1
  115. package/dist/src/public/next/index.d.ts +6 -4
  116. package/dist/src/public/next/index.js +1 -1
  117. package/dist/src/public/next/server.js +1 -1
  118. package/dist/src/public/next/vercel-output-config.d.ts +1 -0
  119. package/dist/src/runtime/connections/mcp-client.js +1 -1
  120. package/dist/src/runtime/resolve-connection.js +1 -1
  121. package/dist/src/runtime/sessions/runtime-context-keys.js +1 -1
  122. package/dist/src/runtime/types.d.ts +1 -0
  123. package/dist/src/self-modification/agent.d.ts +7 -1
  124. package/dist/src/self-modification/agent.js +1 -1
  125. package/dist/src/setup/flows/chatgpt-auth.js +1 -1
  126. package/dist/src/setup/flows/registry.js +1 -1
  127. package/dist/src/setup/provider-settings.js +1 -1
  128. package/dist/src/setup/scaffold/create/project.js +1 -1
  129. package/dist/src/shared/channel-audience.d.ts +0 -3
  130. package/dist/src/shared/channel-definition.d.ts +13 -4
  131. package/dist/src/shared/conversation-context.d.ts +47 -0
  132. package/dist/src/shared/conversation-context.js +1 -0
  133. package/dist/src/shared/forwarded-trace-policy.d.ts +2 -1
  134. package/dist/src/shared/forwarded-trace-policy.js +1 -1
  135. package/dist/src/shared/instrumentation-channel-kind.d.ts +3 -0
  136. package/dist/src/shared/instrumentation-channel-kind.js +1 -0
  137. package/dist/src/shared/instrumentation-content.d.ts +9 -4
  138. package/dist/src/shared/instrumentation-content.js +1 -1
  139. package/dist/src/shared/trace-policy.d.ts +7 -6
  140. package/dist/src/shared/trace-policy.js +1 -1
  141. package/dist/src/subagents/handle-dispatch.d.ts +2 -1
  142. package/dist/src/subagents/handle-dispatch.js +1 -1
  143. package/dist/src/subagents/remote-dispatch.js +1 -1
  144. package/dist/src/subagents/start-local.d.ts +1 -0
  145. package/dist/src/subagents/start-local.js +1 -1
  146. package/dist/src/subagents/start-remote.d.ts +2 -0
  147. package/dist/src/subagents/start-remote.js +1 -1
  148. package/dist/src/subagents/tool.d.ts +3 -0
  149. package/dist/src/subagents/tool.js +1 -1
  150. package/dist/src/tasks/session-index.d.ts +2 -0
  151. package/dist/src/tasks/session-index.js +1 -1
  152. package/dist/src/tracing/agent-invocation-coordinator.d.ts +3 -2
  153. package/dist/src/tracing/agent-invocation-coordinator.js +1 -1
  154. package/dist/src/tracing/agent-memory-instrumentation.d.ts +3 -1
  155. package/dist/src/tracing/agent-memory-instrumentation.js +1 -1
  156. package/dist/src/tracing/agent-otel-provider.d.ts +2 -0
  157. package/dist/src/tracing/agent-otel-provider.js +2 -2
  158. package/dist/src/tracing/agent-otel-session-context.d.ts +2 -0
  159. package/dist/src/tracing/agent-otel-session-context.js +1 -1
  160. package/dist/src/tracing/agent-trace-context-store.js +1 -1
  161. package/dist/src/tracing/install-instrumentation-runtime.js +1 -1
  162. package/dist/src/tracing/local-instrumentation-runtime.d.ts +1 -1
  163. package/dist/src/tracing/local-instrumentation-runtime.js +1 -1
  164. package/docs/channels/custom.mdx +22 -2
  165. package/docs/channels/eve.mdx +39 -0
  166. package/docs/channels/slack.mdx +32 -0
  167. package/docs/connections/mcp.mdx +14 -0
  168. package/docs/guides/frontend/nextjs.mdx +12 -10
  169. package/docs/guides/instrumentation-providers.md +10 -8
  170. package/docs/guides/instrumentation.md +2 -2
  171. package/docs/guides/remote-agents.md +1 -1
  172. package/docs/install-integrations.mdx +1 -1
  173. package/docs/reference/cli.md +9 -8
  174. package/docs/subagents/index.mdx +3 -1
  175. package/package.json +1 -1
@@ -1 +1 @@
1
- import{z}from"#compiled/zod/index.js";import{SESSION_TASKS_STATE_KEY,SESSION_TASKS_STATE_KEY as SESSION_TASKS_STATE_KEY$1,SESSION_TASKS_STATE_VERSION,getTaskCohortId}from"#tasks/session-task-cohorts.js";import{sameTaskMetadata}from"#tasks/types.js";const taskMetadataSchema=z.looseObject({kind:z.string().min(1),name:z.string().min(1)}),taskViewBaseShape={executor:z.strictObject({binding:z.strictObject({data:z.record(z.string(),z.custom()),kind:z.string().min(1)}).optional()}).optional(),metadata:taskMetadataSchema,taskId:z.string().min(1),usage:z.strictObject({cacheReadTokens:z.number().nonnegative(),cacheWriteTokens:z.number().nonnegative(),inputTokens:z.number().nonnegative(),outputTokens:z.number().nonnegative()}).optional()},taskViewSchema=z.discriminatedUnion(`status`,[z.strictObject({...taskViewBaseShape,lastOutput:z.strictObject({data:z.custom(),type:z.literal(`result`)}),status:z.literal(`completed`)}),z.strictObject({...taskViewBaseShape,lastOutput:z.strictObject({data:z.custom(),type:z.literal(`error`)}),status:z.literal(`failed`)}),z.strictObject({...taskViewBaseShape,status:z.literal(`cancelled`)})]),sessionTaskIndexEntrySchema=z.strictObject({taskInboxToken:z.string().min(1),createdByStepIndex:z.number().int().nonnegative().optional(),createdByTurnId:z.string().min(1),cohortId:z.string().min(1).optional(),executor:z.strictObject({data:z.record(z.string(),z.custom()),kind:z.string().min(1)}).optional(),metadata:taskMetadataSchema,taskId:z.string().min(1),taskRunId:z.string().min(1),terminalView:taskViewSchema.optional()}),sessionTaskIndexSchema=z.strictObject({tasks:z.array(sessionTaskIndexEntrySchema),version:z.literal(SESSION_TASKS_STATE_VERSION)}).refine(e=>new Set(e.tasks.map(e=>e.taskId)).size===e.tasks.length,{message:`Task ids must be unique.`}).refine(e=>e.tasks.every(e=>e.terminalView===void 0||e.terminalView.taskId===e.taskId&&sameTaskMetadata(e.terminalView.metadata,e.metadata)),{message:`Cached terminal views must match their task index entry.`});function getSessionTaskIndex(e){let t=e?.[SESSION_TASKS_STATE_KEY$1];if(t===void 0)return[];let n=typeof t==`object`&&t?Reflect.get(t,`version`):void 0;if(n!==SESSION_TASKS_STATE_VERSION)throw Error(`Unsupported task index version ${JSON.stringify(n)} under session state key "${SESSION_TASKS_STATE_KEY$1}"; expected version ${SESSION_TASKS_STATE_VERSION}.`);let r=sessionTaskIndexSchema.safeParse(t);if(!r.success)throw Error(`Corrupt task index under session state key "${SESSION_TASKS_STATE_KEY$1}": ${r.error.message}`);return r.data.tasks}function cacheTerminalTaskView(e,t){if(!isValidTerminalView(t))throw Error(`Cannot cache invalid terminal task "${t.taskId}".`);let n=getSessionTaskIndex(e),r=n.findIndex(e=>e.taskId===t.taskId);if(r<0)return e;if(!sameTaskMetadata(n[r].metadata,t.metadata))throw Error(`Task view metadata does not match index entry "${t.taskId}".`);let i=[...n];return i[r]={...i[r],terminalView:t},{...e,[SESSION_TASKS_STATE_KEY$1]:{tasks:i,version:SESSION_TASKS_STATE_VERSION}}}function isValidTerminalView(e){if(e.inputRequests!==void 0)return!1;switch(e.status){case`completed`:return e.lastOutput?.type===`result`;case`failed`:return e.lastOutput?.type===`error`;case`cancelled`:return e.lastOutput===void 0;case`working`:return!1}}function findSessionTaskEntry(e,t){return getSessionTaskIndex(e).find(e=>e.taskId===t)}function recordSessionTask(e,t){let n=[...getSessionTaskIndex(e.state)],r=n.findIndex(e=>e.taskId===t.taskId),i=n[r];if(i!==void 0)n[r]={...t,cohortId:i.cohortId,createdByStepIndex:i.createdByStepIndex,createdByTurnId:i.createdByTurnId,terminalView:i.terminalView??t.terminalView};else{let e=n.find(e=>e.terminalView===void 0);n.push({...t,cohortId:e===void 0?void 0:getTaskCohortId(e)})}return{...e,state:{...e.state,[SESSION_TASKS_STATE_KEY$1]:{tasks:n,version:SESSION_TASKS_STATE_VERSION}}}}export{SESSION_TASKS_STATE_KEY,cacheTerminalTaskView,findSessionTaskEntry,getSessionTaskIndex,recordSessionTask};
1
+ import{z}from"#compiled/zod/index.js";import{parseActivityWorkIdentityV1}from"#protocol/activity.js";import{SESSION_TASKS_STATE_KEY,SESSION_TASKS_STATE_KEY as SESSION_TASKS_STATE_KEY$1,SESSION_TASKS_STATE_VERSION,getTaskCohortId}from"#tasks/session-task-cohorts.js";import{sameTaskMetadata}from"#tasks/types.js";const taskMetadataSchema=z.looseObject({kind:z.string().min(1),name:z.string().min(1)}),taskViewBaseShape={executor:z.strictObject({binding:z.strictObject({data:z.record(z.string(),z.custom()),kind:z.string().min(1)}).optional()}).optional(),metadata:taskMetadataSchema,taskId:z.string().min(1),usage:z.strictObject({cacheReadTokens:z.number().nonnegative(),cacheWriteTokens:z.number().nonnegative(),inputTokens:z.number().nonnegative(),outputTokens:z.number().nonnegative()}).optional()},taskViewSchema=z.discriminatedUnion(`status`,[z.strictObject({...taskViewBaseShape,lastOutput:z.strictObject({data:z.custom(),type:z.literal(`result`)}),status:z.literal(`completed`)}),z.strictObject({...taskViewBaseShape,lastOutput:z.strictObject({data:z.custom(),type:z.literal(`error`)}),status:z.literal(`failed`)}),z.strictObject({...taskViewBaseShape,status:z.literal(`cancelled`)})]),sessionTaskIndexEntrySchema=z.strictObject({activityWorkIdentity:z.custom(e=>parseActivityWorkIdentityV1(e)!==void 0).optional(),taskInboxToken:z.string().min(1),createdByStepIndex:z.number().int().nonnegative().optional(),createdByTurnId:z.string().min(1),cohortId:z.string().min(1).optional(),executor:z.strictObject({data:z.record(z.string(),z.custom()),kind:z.string().min(1)}).optional(),metadata:taskMetadataSchema,taskId:z.string().min(1),taskRunId:z.string().min(1),terminalView:taskViewSchema.optional()}),sessionTaskIndexSchema=z.strictObject({tasks:z.array(sessionTaskIndexEntrySchema),version:z.literal(SESSION_TASKS_STATE_VERSION)}).refine(e=>new Set(e.tasks.map(e=>e.taskId)).size===e.tasks.length,{message:`Task ids must be unique.`}).refine(e=>e.tasks.every(e=>e.terminalView===void 0||e.terminalView.taskId===e.taskId&&sameTaskMetadata(e.terminalView.metadata,e.metadata)),{message:`Cached terminal views must match their task index entry.`});function getSessionTaskIndex(e){let t=e?.[SESSION_TASKS_STATE_KEY$1];if(t===void 0)return[];let n=typeof t==`object`&&t?Reflect.get(t,`version`):void 0;if(n!==SESSION_TASKS_STATE_VERSION)throw Error(`Unsupported task index version ${JSON.stringify(n)} under session state key "${SESSION_TASKS_STATE_KEY$1}"; expected version ${SESSION_TASKS_STATE_VERSION}.`);let r=sessionTaskIndexSchema.safeParse(t);if(!r.success)throw Error(`Corrupt task index under session state key "${SESSION_TASKS_STATE_KEY$1}": ${r.error.message}`);return r.data.tasks}function cacheTerminalTaskView(e,t){if(!isValidTerminalView(t))throw Error(`Cannot cache invalid terminal task "${t.taskId}".`);let n=getSessionTaskIndex(e),r=n.findIndex(e=>e.taskId===t.taskId);if(r<0)return e;if(!sameTaskMetadata(n[r].metadata,t.metadata))throw Error(`Task view metadata does not match index entry "${t.taskId}".`);let i=[...n];return i[r]={...i[r],terminalView:t},{...e,[SESSION_TASKS_STATE_KEY$1]:{tasks:i,version:SESSION_TASKS_STATE_VERSION}}}function isValidTerminalView(e){if(e.inputRequests!==void 0)return!1;switch(e.status){case`completed`:return e.lastOutput?.type===`result`;case`failed`:return e.lastOutput?.type===`error`;case`cancelled`:return e.lastOutput===void 0;case`working`:return!1}}function findSessionTaskEntry(e,t){return getSessionTaskIndex(e).find(e=>e.taskId===t)}function recordSessionTask(e,t){let n=[...getSessionTaskIndex(e.state)],r=n.findIndex(e=>e.taskId===t.taskId),i=n[r];if(i!==void 0)n[r]={...t,cohortId:i.cohortId,createdByStepIndex:i.createdByStepIndex,createdByTurnId:i.createdByTurnId,terminalView:i.terminalView??t.terminalView};else{let e=n.find(e=>e.terminalView===void 0);n.push({...t,cohortId:e===void 0?void 0:getTaskCohortId(e)})}return{...e,state:{...e.state,[SESSION_TASKS_STATE_KEY$1]:{tasks:n,version:SESSION_TASKS_STATE_VERSION}}}}export{SESSION_TASKS_STATE_KEY,cacheTerminalTaskView,findSessionTaskEntry,getSessionTaskIndex,recordSessionTask};
@@ -1,14 +1,15 @@
1
- import type { ChannelInstrumentationProjection, SessionTraceContext } from "#channel/types.js";
1
+ import type { SessionTraceContext } from "#channel/types.js";
2
2
  import type { RuntimeSubagentResult } from "#shared/action-types.js";
3
3
  import type { SessionStateMap } from "#harness/types.js";
4
4
  import { type ChannelAudience } from "#shared/channel-audience.js";
5
+ import type { ConversationContext } from "#shared/conversation-context.js";
5
6
  export interface AgentChildTraceDispatch {
6
7
  readonly conversationId?: string;
7
8
  readonly originAudience: ChannelAudience;
8
9
  readonly parentTraceContext?: SessionTraceContext;
9
10
  }
10
11
  export declare function prepareAgentInvocationTrace(input: {
11
- readonly channelMetadata?: ChannelInstrumentationProjection;
12
+ readonly conversation?: ConversationContext;
12
13
  readonly invocation: {
13
14
  readonly callId: string;
14
15
  readonly kind: "remote-agent-call" | "subagent-call";
@@ -1 +1 @@
1
- import{normalizeChannelAudience}from"#shared/channel-audience.js";import{ConversationIdKey}from"#context/keys.js";import{readConversationId}from"#tracing/conversation-context.js";import{applyLiveDeliveryAudienceCeiling,readForwardedTraceAssertion}from"#shared/forwarded-trace-policy.js";import{getWorkflowToolRuns}from"#harness/workflow-tool-runs.js";import{readActionTraceContext,readTaskActionTrace,readTurnTraceContext,recordActionInvocationKind,recordNestedAgentInvocation}from"#tracing/agent-trace-context-store.js";import{invocationError,recordNestedAgentInvocationTerminal}from"#tracing/agent-invocation-terminal.js";import{deriveAgentActionSpanId}from"#tracing/agent-span-id-generator.js";function prepareAgentInvocationTrace(e){let t=readConversationId(e.serializedContext[ConversationIdKey.name]),n=e.taskId===void 0?void 0:readTaskActionTrace(e.serializedContext,e.sessionId,e.taskId),r=e.taskId===void 0?getWorkflowToolRuns(e.sessionState).find(t=>t.runId===e.ownerId)?.callId:n?.callId,i=n?.turnId??e.turnId,a=readTurnTraceContext(e.serializedContext,e.sessionId,i),o=normalizeChannelAudience(e.channelMetadata?.metadata.audience),s=(r===void 0?void 0:readActionTraceContext(e.serializedContext,e.sessionId,i,r))??a,c=s?.decision===void 0?void 0:applyLiveDeliveryAudienceCeiling(s.decision,o,s.forwardedTracePolicy),l=r===void 0?e.serializedContext:r===e.invocation.callId?recordActionInvocationKind({callId:e.invocation.callId,kind:e.invocation.kind,serializedContext:e.serializedContext,sessionId:e.sessionId,turnId:i}):recordNestedAgentInvocation({callId:e.invocation.callId,kind:e.invocation.kind,name:e.invocation.name,outerCallId:r,recordOutputs:c?.action===`record`&&c.recordOutputs,serializedContext:e.serializedContext,sessionId:e.sessionId,spanId:deriveAgentActionSpanId(e.sessionId,i,e.invocation.callId),startTimeMs:e.startTimeMs,turnId:i}),u=readActionTraceContext(l,e.sessionId,i,e.invocation.callId)??s,d=readForwardedTraceAssertion(u?.forwardedTracePolicy),f=u?.decision===void 0?u:{...u,decision:applyLiveDeliveryAudienceCeiling(u.decision,o,d)};return{dispatch:{conversationId:t,originAudience:d?.originAudience??o,parentTraceContext:f},fail:t=>recordNestedAgentInvocationTerminal({callId:e.invocation.callId,serializedContext:l,sessionId:e.sessionId,terminal:{acceptedAtMs:Date.now(),error:invocationError(t.output),outcome:`failed`},turnId:i}),serializedContext:l}}export{prepareAgentInvocationTrace};
1
+ import"#shared/channel-audience.js";import{applyLiveDeliveryAudienceCeiling,readForwardedTraceAssertion}from"#shared/forwarded-trace-policy.js";import{ConversationIdKey}from"#context/keys.js";import{readConversationId}from"#tracing/conversation-context.js";import{getWorkflowToolRuns}from"#harness/workflow-tool-runs.js";import{readActionTraceContext,readTaskActionTrace,readTurnTraceContext,recordActionInvocationKind,recordNestedAgentInvocation}from"#tracing/agent-trace-context-store.js";import{invocationError,recordNestedAgentInvocationTerminal}from"#tracing/agent-invocation-terminal.js";import{deriveAgentActionSpanId}from"#tracing/agent-span-id-generator.js";function prepareAgentInvocationTrace(e){let t=readConversationId(e.serializedContext[ConversationIdKey.name]),n=e.taskId===void 0?void 0:readTaskActionTrace(e.serializedContext,e.sessionId,e.taskId),r=e.taskId===void 0?getWorkflowToolRuns(e.sessionState).find(t=>t.runId===e.ownerId)?.callId:n?.callId,i=n?.turnId??e.turnId,a=readTurnTraceContext(e.serializedContext,e.sessionId,i),o=e.conversation,s=o?.audience??`unknown`,c=o?.environment??`production`,l=(r===void 0?void 0:readActionTraceContext(e.serializedContext,e.sessionId,i,r))??a,u=l?.decision===void 0?void 0:applyLiveDeliveryAudienceCeiling(l.decision,s,l.forwardedTracePolicy,c),d=r===void 0?e.serializedContext:r===e.invocation.callId?recordActionInvocationKind({callId:e.invocation.callId,kind:e.invocation.kind,serializedContext:e.serializedContext,sessionId:e.sessionId,turnId:i}):recordNestedAgentInvocation({callId:e.invocation.callId,kind:e.invocation.kind,name:e.invocation.name,outerCallId:r,recordOutputs:u?.action===`record`&&u.recordOutputs,serializedContext:e.serializedContext,sessionId:e.sessionId,spanId:deriveAgentActionSpanId(e.sessionId,i,e.invocation.callId),startTimeMs:e.startTimeMs,turnId:i}),f=readActionTraceContext(d,e.sessionId,i,e.invocation.callId)??l,p=readForwardedTraceAssertion(f?.forwardedTracePolicy),m=f?.decision===void 0?f:{...f,decision:applyLiveDeliveryAudienceCeiling(f.decision,s,p,c)};return{dispatch:{conversationId:t,originAudience:p?.originAudience??s,parentTraceContext:m},fail:t=>recordNestedAgentInvocationTerminal({callId:e.invocation.callId,serializedContext:d,sessionId:e.sessionId,terminal:{acceptedAtMs:Date.now(),error:invocationError(t.output),outcome:`failed`},turnId:i}),serializedContext:d}}export{prepareAgentInvocationTrace};
@@ -2,12 +2,14 @@ import { type Tracer } from "#compiled/@opentelemetry/api/index.js";
2
2
  import type { InstrumentationProviderDefinition } from "#instrumentation/lifecycle.js";
3
3
  import type { InstrumentationMemoryExecutionOperation } from "#instrumentation/memory.js";
4
4
  import type { AgentTraceStateStore } from "#tracing/agent-trace-state.js";
5
+ import type { ConversationEnvironment } from "#shared/conversation-context.js";
5
6
  export interface AgentMemoryInstrumentation {
6
7
  readonly events: Pick<NonNullable<InstrumentationProviderDefinition["events"]>, "memory.operation.completed" | "memory.operation.failed" | "memory.operation.started">;
7
8
  runInContext<T>(operation: InstrumentationMemoryExecutionOperation, execute: () => PromiseLike<T>): Promise<T>;
8
9
  }
9
10
  export declare function createAgentMemoryInstrumentation(input: {
10
- readonly recordOutputs: boolean;
11
+ readonly environment: ConversationEnvironment;
12
+ readonly recordOutputs?: boolean;
11
13
  readonly stateStore: AgentTraceStateStore;
12
14
  readonly tracer: Tracer;
13
15
  }): AgentMemoryInstrumentation;
@@ -1 +1 @@
1
- import{normalizeChannelAudience}from"#shared/channel-audience.js";import{contextStorage}from"#context/container.js";import{SessionTraceSeedKey}from"#context/keys.js";import{applyLiveDeliveryAudienceCeiling,resolveForwardedTraceSeed}from"#shared/forwarded-trace-policy.js";import{isSampledTrace}from"#tracing/sampled-trace.js";import{ROOT_CONTEXT,SpanKind,context,trace}from"#compiled/@opentelemetry/api/index.js";import{isAgentTraceContext,markAgentTraceContext}from"#tracing/agent-trace-context.js";import{withErrorContent}from"#tracing/error-content-context.js";import{agentSpanNamingAttributes}from"#tracing/agent-span-naming.js";import{agentTraceIdentityAttributes}from"#tracing/agent-otel-attributes.js";import{genAiMemoryRecordsAttribute}from"#tracing/agent-otel-content.js";import{withChannelAudience}from"#tracing/channel-audience-context.js";import{recordAgentSpanError}from"#tracing/agent-span-error.js";import{suppressTracing}from"#tracing/suppress-tracing.js";function createAgentMemoryInstrumentation(e){let t=new Map,parentContext=async t=>{let n=context.active();if(isAgentTraceContext(n))return n;let r=await e.stateStore.getSession(t.sessionId);if(t.turnId!==void 0){let n=await e.stateStore.getTurn(t.sessionId,t.turnId);if(n!==void 0)return withChannelAudience(contextFromSpanContext(n.context),r?.channelAudience)}return r===void 0?void 0:withChannelAudience(contextFromSpanContext(r.context),r.channelAudience)},onStarted=async n=>{if(t.has(n.idempotencyKey))return;let r=await parentContext(n),i=r===void 0?void 0:trace.getSpan(r)?.spanContext();if(r===void 0||i===void 0||!isSampledTrace(i))return;let a=e.tracer.startSpan(n.operationName,{attributes:memorySpanAttributes(n),kind:SpanKind.CLIENT},r);t.set(n.idempotencyKey,{context:trace.setSpan(r,a),span:a})},onTerminal=e=>{let n=t.get(e.idempotencyKey);n!==void 0&&(t.delete(e.idempotencyKey),updateMemorySpan(n.span,e),n.span.end())};return{events:{"memory.operation.completed":onTerminal,"memory.operation.failed":onTerminal,"memory.operation.started":onStarted},async runInContext(n,r){let i=await e.stateStore.getSession(n.sessionId),a=t.get(n.idempotencyKey)?.context;if(a===void 0&&n.turnId!==void 0){let t=await e.stateStore.getTurn(n.sessionId,n.turnId);t!==void 0&&(a=withChannelAudience(contextFromSpanContext(t.context),i?.channelAudience),isSampledTrace(t.context)||(a=suppressTracing(a)))}a===void 0&&i!==void 0&&(a=withChannelAudience(contextFromSpanContext(i.context),i.channelAudience),isSampledTrace(i.context)||(a=suppressTracing(a)));let o=resolveForwardedTraceSeed(contextStorage.getStore()?.get(SessionTraceSeedKey)),s=o?.decision??i?.decision,c=s===void 0?void 0:applyLiveDeliveryAudienceCeiling(s,normalizeChannelAudience(i?.channelAudience),o?.forwardedTracePolicy);return a===void 0?await r():await context.with(markAgentTraceContext(withErrorContent(a,e.recordOutputs&&c?.action===`record`&&c.recordOutputs)),r)}}}function memorySpanAttributes(e){let t={"agent.memory.phase":e.phase,"agent.memory.slot":e.slot,"gen_ai.memory.store.id":e.storeId,"gen_ai.operation.name":e.operationName,...agentSpanNamingAttributes(e.operationName,e.operationName),...agentTraceIdentityAttributes({rootSessionId:e.rootSessionId,sessionId:e.sessionId})};return e.turnId!==void 0&&(t[`agent.turn.id`]=e.turnId),t}function updateMemorySpan(e,t){if(t.type===`memory.operation.failed`)recordAgentSpanError(e,t.error);else{t.recordCount!==void 0&&e.setAttribute(`gen_ai.memory.record.count`,t.recordCount);let n=genAiMemoryRecordsAttribute(t.outputRecords??[]);n!==void 0&&t.outputRecords!==void 0&&e.setAttribute(`gen_ai.memory.records`,n)}}function contextFromSpanContext(e){return trace.setSpan(ROOT_CONTEXT,trace.wrapSpanContext(e))}export{createAgentMemoryInstrumentation};
1
+ import{normalizeChannelAudience}from"#shared/channel-audience.js";import{applyLiveDeliveryAudienceCeiling,resolveForwardedTraceSeed}from"#shared/forwarded-trace-policy.js";import{contextStorage}from"#context/container.js";import{SessionTraceSeedKey}from"#context/keys.js";import{isSampledTrace}from"#tracing/sampled-trace.js";import{ROOT_CONTEXT,SpanKind,context,trace}from"#compiled/@opentelemetry/api/index.js";import{isAgentTraceContext,markAgentTraceContext}from"#tracing/agent-trace-context.js";import{withErrorContent}from"#tracing/error-content-context.js";import{agentSpanNamingAttributes}from"#tracing/agent-span-naming.js";import{agentTraceIdentityAttributes}from"#tracing/agent-otel-attributes.js";import{genAiMemoryRecordsAttribute}from"#tracing/agent-otel-content.js";import{withChannelAudience}from"#tracing/channel-audience-context.js";import{recordAgentSpanError}from"#tracing/agent-span-error.js";import{suppressTracing}from"#tracing/suppress-tracing.js";function createAgentMemoryInstrumentation(e){let t=e.recordOutputs??!1,n=new Map,parentContext=async t=>{let n=context.active();if(isAgentTraceContext(n))return n;let r=await e.stateStore.getSession(t.sessionId);if(t.turnId!==void 0){let n=await e.stateStore.getTurn(t.sessionId,t.turnId);if(n!==void 0)return withChannelAudience(contextFromSpanContext(n.context),r?.channelAudience)}return r===void 0?void 0:withChannelAudience(contextFromSpanContext(r.context),r.channelAudience)},onStarted=async t=>{if(n.has(t.idempotencyKey))return;let r=await parentContext(t),i=r===void 0?void 0:trace.getSpan(r)?.spanContext();if(r===void 0||i===void 0||!isSampledTrace(i))return;let a=e.tracer.startSpan(t.operationName,{attributes:memorySpanAttributes(t),kind:SpanKind.CLIENT},r);n.set(t.idempotencyKey,{context:trace.setSpan(r,a),span:a})},onTerminal=e=>{let t=n.get(e.idempotencyKey);t!==void 0&&(n.delete(e.idempotencyKey),updateMemorySpan(t.span,e),t.span.end())};return{events:{"memory.operation.completed":onTerminal,"memory.operation.failed":onTerminal,"memory.operation.started":onStarted},async runInContext(r,i){let a=await e.stateStore.getSession(r.sessionId),o=n.get(r.idempotencyKey)?.context;if(o===void 0&&r.turnId!==void 0){let t=await e.stateStore.getTurn(r.sessionId,r.turnId);t!==void 0&&(o=withChannelAudience(contextFromSpanContext(t.context),a?.channelAudience),isSampledTrace(t.context)||(o=suppressTracing(o)))}o===void 0&&a!==void 0&&(o=withChannelAudience(contextFromSpanContext(a.context),a.channelAudience),isSampledTrace(a.context)||(o=suppressTracing(o)));let s=resolveForwardedTraceSeed(contextStorage.getStore()?.get(SessionTraceSeedKey)),c=s?.decision??a?.decision,l=c===void 0?void 0:applyLiveDeliveryAudienceCeiling(c,normalizeChannelAudience(a?.channelAudience),s?.forwardedTracePolicy,e.environment);return o===void 0?await i():await context.with(markAgentTraceContext(withErrorContent(o,t&&l?.action===`record`&&l.recordOutputs)),i)}}}function memorySpanAttributes(e){let t={"agent.memory.phase":e.phase,"agent.memory.slot":e.slot,"gen_ai.memory.store.id":e.storeId,"gen_ai.operation.name":e.operationName,...agentSpanNamingAttributes(e.operationName,e.operationName),...agentTraceIdentityAttributes({rootSessionId:e.rootSessionId,sessionId:e.sessionId})};return e.turnId!==void 0&&(t[`agent.turn.id`]=e.turnId),t}function updateMemorySpan(e,t){if(t.type===`memory.operation.failed`)recordAgentSpanError(e,t.error);else{t.recordCount!==void 0&&e.setAttribute(`gen_ai.memory.record.count`,t.recordCount);let n=genAiMemoryRecordsAttribute(t.outputRecords??[]);n!==void 0&&t.outputRecords!==void 0&&e.setAttribute(`gen_ai.memory.records`,n)}}function contextFromSpanContext(e){return trace.setSpan(ROOT_CONTEXT,trace.wrapSpanContext(e))}export{createAgentMemoryInstrumentation};
@@ -4,7 +4,9 @@ import type { AgentSpanIdGenerator } from "#tracing/agent-span-id-generator.js";
4
4
  import type { TraceCapturePolicy } from "#tracing/otel-declaration.js";
5
5
  import type { InstrumentationContextRunner, InstrumentationProviderDefinition, InstrumentationSessionStartedEvent, InstrumentationTraceSeed, InstrumentationTurnStartedEvent } from "#instrumentation/lifecycle.js";
6
6
  import { type AgentSamplingOperation } from "#tracing/agent-span-contract.js";
7
+ import type { ConversationEnvironment } from "#shared/conversation-context.js";
7
8
  export interface AgentOtelInstrumentationInput {
9
+ readonly environment?: ConversationEnvironment;
8
10
  /** Whether any destination records model and tool inputs. */
9
11
  readonly recordInputs?: boolean;
10
12
  /** Whether any destination records model and tool outputs. */
@@ -1,2 +1,2 @@
1
- import{normalizeChannelAudience}from"#shared/channel-audience.js";import{contextStorage}from"#context/container.js";import{SessionTraceSeedKey}from"#context/keys.js";import{AGENT_SPAN_NAMES,agentInvocationSpanName}from"#tracing/agent-span-contract.js";import{applyLiveDeliveryAudienceCeiling,resolveForwardedTraceSeed}from"#shared/forwarded-trace-policy.js";import{isSampledTrace,resolveTracePolicyDecision}from"#tracing/sampled-trace.js";import{ROOT_CONTEXT,SpanKind,context,trace}from"#compiled/@opentelemetry/api/index.js";import{markAgentTraceContext}from"#tracing/agent-trace-context.js";import{attemptIdempotencyKey}from"#instrumentation/lifecycle.js";import{withoutInstrumentationContent}from"#instrumentation/content.js";import{withErrorContent}from"#tracing/error-content-context.js";import{readInstrumentationDecision}from"#shared/instrumentation-decision.js";import{agentSpanNamingAttributes}from"#tracing/agent-span-naming.js";import{agentTraceIdentityAttributes}from"#tracing/agent-otel-attributes.js";import{contentAttribute,genAiInputMessagesAttribute,genAiOutputMessagesAttribute,genAiSystemInstructionsAttribute,systemPromptAttribute,textContentAttribute,toolResultsContentAttribute}from"#tracing/agent-otel-content.js";import{readGatewayCost,setAgentInvocationUsage,setAgentUsage,setGenAiUsage}from"#tracing/agent-otel-usage.js";import{withChannelAudience}from"#tracing/channel-audience-context.js";import{recordAgentSpanError}from"#tracing/agent-span-error.js";import{suppressTracing}from"#tracing/suppress-tracing.js";import{instrumentationEventForTraceDecision}from"#instrumentation/content-policy.js";import{createAgentActionInstrumentation}from"#tracing/agent-action-instrumentation.js";import{createAgentApprovalInstrumentation}from"#tracing/agent-approval-instrumentation.js";import{createAgentChannelDeliveryInstrumentation}from"#tracing/agent-channel-delivery-instrumentation.js";import{createAgentToolInstrumentation}from"#tracing/agent-tool-instrumentation.js";import*as runtimeAttributes from"#tracing/agent-otel-runtime-context.js";import{createAgentMemoryInstrumentation}from"#tracing/agent-memory-instrumentation.js";import{createAgentOtelSessionContext}from"#tracing/agent-otel-session-context.js";function createAgentOtelInstrumentation(e){let t=e.recordInputs??!1,n=e.recordOutputs??!1,r=new WeakMap,i=new Map,a=new WeakMap,o=new WeakMap,s=createAgentActionInstrumentation({frameworkVersion:e.frameworkVersion,idGenerator:e.idGenerator,recordInputs:t,recordOutputs:n,resolveTraceContext:async t=>(await e.stateStore.getTurn(t.scope.sessionId,t.scope.turnId))?.context,stateStore:e.stateStore,tracer:e.tracer}),c=createAgentApprovalInstrumentation({actionContextFor:s.contextFor,frameworkVersion:e.frameworkVersion,idGenerator:e.idGenerator,tracer:e.tracer}),l=createAgentToolInstrumentation({actionContextFor:s.contextFor,idGenerator:e.idGenerator,recordInputs:t,recordOutputs:n,resolveFallback:e=>{let t=i.get(e.scope.attemptId)??e.scope,n=a.get(t);return n===void 0?void 0:{context:n.context,spanContext:n.span.spanContext()}},tracer:e.tracer}),u=createAgentMemoryInstrumentation({recordOutputs:n,stateStore:e.stateStore,tracer:e.tracer}),{ensureSessionContext:d,prepareSessionTrace:f,prepareTurnTrace:p}=createAgentOtelSessionContext(e),projectEvent=async r=>{let i=await e.stateStore.getSession(sessionIdForEvent(r)),a=audienceForEvent(r,i?.channelAudience),o=`traceSeed`in r?r.traceSeed:void 0,s=contextStorage.getStore()?.get(SessionTraceSeedKey),c=resolveForwardedTraceSeed(s),l=resolveForwardedTraceSeed(o,c?.forwardedTracePolicy),u=l?.decision??c?.decision??readInstrumentationDecision(i?.decision)??(o===void 0?s===void 0?i===void 0?void 0:resolveTracePolicyDecision(isSampledTrace(i.context),a):resolveTracePolicyDecision(isSampledTrace(s),a):resolveTracePolicyDecision(isSampledTrace(o),a));if(u===void 0)return withoutInstrumentationContent(r);let d=l===void 0||!(`traceSeed`in r)||r.traceSeed===void 0?r:{...r,traceSeed:{...r.traceSeed,decision:l.decision,traceFlags:l.traceFlags}};return instrumentationEventForTraceDecision(d,applyLiveDeliveryAudienceCeiling(u.action===`drop`?u:{action:`record`,recordInputs:t&&u.recordInputs,recordOutputs:n&&u.recordOutputs},a,l?.forwardedTracePolicy??c?.forwardedTracePolicy),a,{applyAudienceCeiling:!1})},onSessionStarted=async e=>{await f(e)},onTurnStarted=async e=>{await p(e)},onStepStarted=async t=>{let n=await e.stateStore.getTurn(t.scope.sessionId,t.scope.turnId);if(n===void 0||!isSampledTrace(n.context))return;let r=withChannelAudience(contextFromSpanContext(n.context),t.scope.channelAudience),o=trace.getSpan(context.active())?.spanContext(),s=e.idGenerator.withSpanId(e.idGenerator.deriveSpanId(attemptIdempotencyKey(t.scope)),()=>e.tracer.startSpan(AGENT_SPAN_NAMES.step,{attributes:{"agent.framework.name":`eve`,"agent.framework.version":e.frameworkVersion,"agent.step.attempt":t.scope.attemptIndex,"agent.step.index":t.scope.stepIndex,"agent.turn.id":t.scope.turnId,"agent.name":t.scope.functionId,...agentSpanNamingAttributes(`agent.step`),...agentTraceIdentityAttributes({rootSessionId:t.scope.rootSessionId??t.scope.sessionId,sessionId:t.scope.sessionId}),...runtimeAttributes.runtimeContextAttributes(t.runtimeContext)},links:o===void 0||o.traceId===n.context.traceId?void 0:[{attributes:{"eve.link.type":`workflow.delivery`},context:o}]},r));s.addEvent(`step.started`);let c=trace.setSpan(r,s);a.set(t.scope,{context:c,span:s}),i.set(t.scope.attemptId,t.scope)},onStepTerminal=async e=>{let t=i.get(e.scope.attemptId)??e.scope;r.delete(t),drainOpenSpans({...e,scope:t}),l.drain(e.scope.attemptId,e.type===`step.attempt.failed`?{error:e.error}:void 0),e.type===`step.attempt.failed`&&await s.failForAttempt(t,e.error),i.delete(e.scope.attemptId);let n=a.get(t);n!==void 0&&(n.span.addEvent(e.type===`step.attempt.completed`?`step.completed`:`step.failed`),e.type===`step.attempt.failed`&&recordAgentSpanError(n.span,e.error),n.span.end(),a.delete(t))},onTurnTerminal=async t=>{await e.stateStore.updateTurn(t.sessionId,t.turnId,e=>({...e,terminal:t.type===`turn.failed`?{error:t.error,type:t.type}:{type:t.type}}))},onSessionTransition=async t=>{if(await s.flushForSessionTransition(t),t.type===`session.failed`&&t.turnId!==void 0&&await e.stateStore.updateTurn(t.sessionId,t.turnId,e=>({...e,terminal:e.terminal??{error:t.error,type:`turn.failed`}})),t.turnId!==void 0){let n=await e.stateStore.getTurn(t.sessionId,t.turnId);if(n!==void 0){let r=await e.stateStore.getSession(t.sessionId);if(isSampledTrace(n.context)){let i=r?.agentName??n.subagentName,a=withChannelAudience(ROOT_CONTEXT,r?.channelAudience),startSpan=()=>e.tracer.startSpan(agentInvocationSpanName(i),{attributes:runtimeAttributes.agentActivationAttributes({agentName:i,frameworkVersion:e.frameworkVersion,sessionId:t.sessionId,turnId:t.turnId,turn:n}),kind:SpanKind.INTERNAL,links:agentActivationLinks(n),root:!0,startTime:n.startTimeMs},a),o=e.idGenerator.withSpanId(n.context.spanId,()=>e.idGenerator.withTraceId(n.context.traceId,startSpan));setAgentInvocationUsage(o,n.modelUsage),o.addEvent(`turn.started`,void 0,n.startTimeMs),n.terminal!==void 0&&(o.setAttribute(`agent.turn.outcome`,n.terminal.type===`turn.completed`?`completed`:n.terminal.type===`turn.cancelled`?`cancelled`:`failed`),o.addEvent(n.terminal.type),n.terminal.type===`turn.failed`&&recordAgentSpanError(o,n.terminal.error)),o.end()}await e.stateStore.deleteTurn(t.sessionId,t.turnId)}}(t.type===`session.completed`||t.type===`session.failed`)&&(await s.deleteForSession(t.sessionId),await e.stateStore.deleteSession(t.sessionId))},onModelCallStarted=n=>{let r=a.get(n.scope);if(r===void 0)return;r.span.setAttribute(`agent.model.id`,n.model.modelId),r.span.setAttribute(`agent.model.provider`,n.model.provider);let i=e.tracer.startSpan(modelSpanName(n.model.modelId),{attributes:{"gen_ai.agent.name":n.scope.functionId,"gen_ai.operation.name":`chat`,"gen_ai.provider.name":n.model.provider,"gen_ai.request.model":n.model.modelId,...agentSpanNamingAttributes(modelSpanName(n.model.modelId),`chat`),...agentTraceIdentityAttributes({rootSessionId:n.scope.rootSessionId??n.scope.sessionId,sessionId:n.scope.sessionId}),...runtimeAttributes.runtimeContextAttributes(n.runtimeContext)},kind:SpanKind.CLIENT},r.context);if(t&&n.input!==void 0){let e=genAiInputMessagesAttribute(n.input.messages);e!==void 0&&i.setAttribute(`gen_ai.input.messages`,e);let t=systemPromptAttribute(n.input.instructions);t!==void 0&&i.setAttribute(`ai.prompt.system`,t);let r=genAiSystemInstructionsAttribute(n.input.instructions);r!==void 0&&i.setAttribute(`gen_ai.system_instructions`,r)}let s={context:trace.setSpan(r.context,i),span:i};getExecutionContexts(n.scope).set(n.idempotencyKey,s.context),getSpanStates(o,n.scope).set(n.idempotencyKey,s)},onModelCallTerminal=async e=>{r.get(e.scope)?.delete(e.idempotencyKey);let t=takeSpanState(o,e.scope,e.idempotencyKey);if(t!==void 0){if(e.type===`model.call.failed`)recordAgentSpanError(t.span,e.error);else{await recordTurnUsage(e),setGenAiUsage(t.span,e.usage),e.responseId!==void 0&&t.span.setAttribute(`gen_ai.response.id`,e.responseId),t.span.setAttribute(`gen_ai.response.finish_reasons`,[e.finishReason]);let r=a.get(e.scope);if(r!==void 0&&setAgentUsage(r.span,e.usage),n){t.span.setAttribute(`ai.response.finish_reason`,e.finishReason);let n=e.content;if(n===void 0){t.span.end();return}let r=genAiOutputMessagesAttribute(n,e.finishReason);r!==void 0&&t.span.setAttribute(`gen_ai.output.messages`,r);let i=textContentAttribute(n.filter(e=>e.type===`reasoning`).map(e=>e.text).filter(e=>e.trim().length>0).join(`
2
- `));i!==void 0&&t.span.setAttribute(`ai.response.reasoning`,i);let a=textContentAttribute(n.filter(e=>e.type===`text`).map(e=>e.text).join(``));a!==void 0&&t.span.setAttribute(`ai.response.text`,a);let o=n.filter(e=>e.type===`tool-call`).map(e=>({callId:e.callId,input:e.input,toolName:e.toolName}));if(o.length>0){let e=contentAttribute(o);e!==void 0&&t.span.setAttribute(`ai.response.tool_calls`,e)}let s=n.filter(e=>e.type===`tool-result`||e.type===`tool-error`).map(e=>e.type===`tool-result`?{callId:e.callId,input:e.input,output:e.output,toolName:e.toolName}:{callId:e.callId,error:errorText(e.error),input:e.input,toolName:e.toolName});if(s.length>0){let e=toolResultsContentAttribute(s);e!==void 0&&t.span.setAttribute(`ai.response.tool_results`,e)}}}t.span.end()}},recordTurnUsage=async t=>{(t.usage.inputTokens!==void 0||t.usage.outputTokens!==void 0)&&await e.stateStore.updateTurn(t.scope.sessionId,t.scope.turnId,e=>({...e,modelUsage:{inputTokens:t.usage.inputTokens===void 0?e.modelUsage?.inputTokens:(e.modelUsage?.inputTokens??0)+t.usage.inputTokens,outputTokens:t.usage.outputTokens===void 0?e.modelUsage?.outputTokens:(e.modelUsage?.outputTokens??0)+t.usage.outputTokens}}))},m=createAgentChannelDeliveryInstrumentation({ensureSessionContext:d,recordInputs:t,stateStore:e.stateStore}),onStepMetadata=e=>{let t=a.get(e.scope);if(t===void 0)return;let n=readGatewayCost(e.providerMetadata);if(n!==void 0)for(let[e,r]of Object.entries(n))t.span.setAttribute(e,r)};return{hook:{flush:s.flushSettledInvocations,events:{...m,"action.completed":s.events[`action.completed`],"action.failed":s.events[`action.failed`],async"action.started"(e,t){await s.events[`action.started`](e,t),await l.actionStarted(e)},...c,...u.events,"step.attempt.completed":onStepTerminal,"step.attempt.failed":onStepTerminal,"step.attempt.metadata":onStepMetadata,"step.attempt.started":onStepStarted,"model.call.completed":onModelCallTerminal,"model.call.failed":onModelCallTerminal,"model.call.started":onModelCallStarted,"session.completed":onSessionTransition,"session.failed":onSessionTransition,"session.started":onSessionStarted,"session.waiting":onSessionTransition,...l.events,"turn.cancelled":onTurnTerminal,"turn.completed":onTurnTerminal,"turn.failed":onTurnTerminal,"turn.started":onTurnStarted},name:`eve.otel`,projectEvent,tracePolicy:()=>({emit:!0,recordInputs:t,recordOutputs:n})},prepareSessionTrace:f,prepareTurnTrace:p,async runInContext(t,a){if(t.type===`memory.operation`)return u.runInContext(t,a);let o=i.get(t.scope.attemptId)??t.scope,s=r.get(o),c=t.type===`model.call`?s?.get(t.idempotencyKey):l.contextFor(t.scope.attemptId,t.idempotencyKey);if(c===void 0){let n=await e.stateStore.getTurn(t.scope.sessionId,t.scope.turnId);n!==void 0&&(c=withChannelAudience(contextFromSpanContext(n.context),t.scope.channelAudience),isSampledTrace(n.context)||(c=suppressTracing(c)))}let d=await e.stateStore.getSession(t.scope.sessionId),f=resolveForwardedTraceSeed(contextStorage.getStore()?.get(SessionTraceSeedKey)),p=f?.decision??d?.decision,m=p===void 0?void 0:applyLiveDeliveryAudienceCeiling(p,normalizeChannelAudience(t.scope.channelAudience),f?.forwardedTracePolicy);return c===void 0?a():context.with(markAgentTraceContext(withErrorContent(c,n&&m?.action===`record`&&m.recordOutputs)),a)}};function getExecutionContexts(e){let t=r.get(e);return t===void 0&&(t=new Map,r.set(e,t)),t}function drainOpenSpans(e){for(let t of o.get(e.scope)?.values()??[])e.type===`step.attempt.failed`&&recordAgentSpanError(t.span,e.error),t.span.end();o.delete(e.scope)}}function agentActivationLinks(e){let t=[];return e.caller!==void 0&&t.push({context:e.caller,attributes:{"eve.link.type":`agent.dispatch`}}),e.channelDelivery?.requestTraceContext!==void 0&&t.push({context:e.channelDelivery.requestTraceContext,attributes:{"eve.link.type":`channel.request`}}),t.length===0?void 0:t}function sessionIdForEvent(e){return`scope`in e?e.scope.sessionId:e.sessionId}function audienceForEvent(e,t){return`delivery`in e?normalizeChannelAudience(e.delivery.channelAudience):`scope`in e&&e.scope.channelAudience!==void 0?normalizeChannelAudience(e.scope.channelAudience):e.type===`session.started`?normalizeChannelAudience(e.channelAudience):normalizeChannelAudience(t)}function getSpanStates(e,t){let n=e.get(t);return n===void 0&&(n=new Map,e.set(t,n)),n}function takeSpanState(e,t,n){let r=e.get(t),i=r?.get(n);if(r!==void 0)return r.delete(n),r.size===0&&e.delete(t),i}function contextFromSpanContext(e){return trace.setSpan(ROOT_CONTEXT,trace.wrapSpanContext(e))}function modelSpanName(e){return`chat ${e}`}function errorText(e){return e instanceof Error?e.message:e}export{createAgentOtelInstrumentation};
1
+ import{normalizeChannelAudience}from"#shared/channel-audience.js";import{applyLiveDeliveryAudienceCeiling,resolveForwardedTraceSeed}from"#shared/forwarded-trace-policy.js";import{contextStorage}from"#context/container.js";import{SessionTraceSeedKey}from"#context/keys.js";import{AGENT_SPAN_NAMES,agentInvocationSpanName}from"#tracing/agent-span-contract.js";import{resolveInstrumentationEnvironment}from"#internal/application/dev-environment.js";import{isSampledTrace,resolveTracePolicyDecision}from"#tracing/sampled-trace.js";import{ROOT_CONTEXT,SpanKind,context,trace}from"#compiled/@opentelemetry/api/index.js";import{markAgentTraceContext}from"#tracing/agent-trace-context.js";import{attemptIdempotencyKey}from"#instrumentation/lifecycle.js";import{withoutInstrumentationContent}from"#instrumentation/content.js";import{withErrorContent}from"#tracing/error-content-context.js";import{readInstrumentationDecision}from"#shared/instrumentation-decision.js";import{agentSpanNamingAttributes}from"#tracing/agent-span-naming.js";import{agentTraceIdentityAttributes}from"#tracing/agent-otel-attributes.js";import{contentAttribute,genAiInputMessagesAttribute,genAiOutputMessagesAttribute,genAiSystemInstructionsAttribute,systemPromptAttribute,textContentAttribute,toolResultsContentAttribute}from"#tracing/agent-otel-content.js";import{readGatewayCost,setAgentInvocationUsage,setAgentUsage,setGenAiUsage}from"#tracing/agent-otel-usage.js";import{withChannelAudience}from"#tracing/channel-audience-context.js";import{recordAgentSpanError}from"#tracing/agent-span-error.js";import{suppressTracing}from"#tracing/suppress-tracing.js";import{instrumentationEventForTraceDecision}from"#instrumentation/content-policy.js";import{createAgentActionInstrumentation}from"#tracing/agent-action-instrumentation.js";import{createAgentApprovalInstrumentation}from"#tracing/agent-approval-instrumentation.js";import{createAgentChannelDeliveryInstrumentation}from"#tracing/agent-channel-delivery-instrumentation.js";import{createAgentToolInstrumentation}from"#tracing/agent-tool-instrumentation.js";import*as runtimeAttributes from"#tracing/agent-otel-runtime-context.js";import{createAgentMemoryInstrumentation}from"#tracing/agent-memory-instrumentation.js";import{createAgentOtelSessionContext}from"#tracing/agent-otel-session-context.js";function createAgentOtelInstrumentation(e){let t=e.environment??resolveInstrumentationEnvironment(),n=e.recordInputs??!1,r=e.recordOutputs??!1,i=new WeakMap,a=new Map,o=new WeakMap,s=new WeakMap,c=createAgentActionInstrumentation({frameworkVersion:e.frameworkVersion,idGenerator:e.idGenerator,recordInputs:n,recordOutputs:r,resolveTraceContext:async t=>(await e.stateStore.getTurn(t.scope.sessionId,t.scope.turnId))?.context,stateStore:e.stateStore,tracer:e.tracer}),l=createAgentApprovalInstrumentation({actionContextFor:c.contextFor,frameworkVersion:e.frameworkVersion,idGenerator:e.idGenerator,tracer:e.tracer}),u=createAgentToolInstrumentation({actionContextFor:c.contextFor,idGenerator:e.idGenerator,recordInputs:n,recordOutputs:r,resolveFallback:e=>{let t=a.get(e.scope.attemptId)??e.scope,n=o.get(t);return n===void 0?void 0:{context:n.context,spanContext:n.span.spanContext()}},tracer:e.tracer}),d=createAgentMemoryInstrumentation({...e,environment:t}),{ensureSessionContext:f,prepareSessionTrace:p,prepareTurnTrace:m}=createAgentOtelSessionContext({...e,environment:t}),projectEvent=async i=>{let a=await e.stateStore.getSession(sessionIdForEvent(i)),o=audienceForEvent(i,a?.channelAudience),s=`traceSeed`in i?i.traceSeed:void 0,c=contextStorage.getStore()?.get(SessionTraceSeedKey),l=resolveForwardedTraceSeed(c),u=resolveForwardedTraceSeed(s,l?.forwardedTracePolicy),decisionForTrace=e=>e===void 0?void 0:resolveTracePolicyDecision(isSampledTrace(e),{audience:o,environment:t}),d=u?.decision??l?.decision??readInstrumentationDecision(a?.decision)??decisionForTrace(s)??decisionForTrace(c)??decisionForTrace(a?.context);if(d===void 0)return withoutInstrumentationContent(i);let f=u===void 0||!(`traceSeed`in i)||i.traceSeed===void 0?i:{...i,traceSeed:{...i.traceSeed,decision:u.decision,traceFlags:u.traceFlags}};return instrumentationEventForTraceDecision(f,applyLiveDeliveryAudienceCeiling(d.action===`drop`?d:{action:`record`,recordInputs:n&&d.recordInputs,recordOutputs:r&&d.recordOutputs},o,u?.forwardedTracePolicy??l?.forwardedTracePolicy,t),{audience:o,environment:t},{applyAudienceCeiling:!1})},onSessionStarted=async e=>{await p(e)},onTurnStarted=async e=>{await m(e)},onStepStarted=async t=>{let n=await e.stateStore.getTurn(t.scope.sessionId,t.scope.turnId);if(n===void 0||!isSampledTrace(n.context))return;let r=withChannelAudience(contextFromSpanContext(n.context),t.scope.channelAudience),i=trace.getSpan(context.active())?.spanContext(),s=e.idGenerator.withSpanId(e.idGenerator.deriveSpanId(attemptIdempotencyKey(t.scope)),()=>e.tracer.startSpan(AGENT_SPAN_NAMES.step,{attributes:{"agent.framework.name":`eve`,"agent.framework.version":e.frameworkVersion,"agent.step.attempt":t.scope.attemptIndex,"agent.step.index":t.scope.stepIndex,"agent.turn.id":t.scope.turnId,"agent.name":t.scope.functionId,...agentSpanNamingAttributes(`agent.step`),...agentTraceIdentityAttributes({rootSessionId:t.scope.rootSessionId??t.scope.sessionId,sessionId:t.scope.sessionId}),...runtimeAttributes.runtimeContextAttributes(t.runtimeContext)},links:i===void 0||i.traceId===n.context.traceId?void 0:[{attributes:{"eve.link.type":`workflow.delivery`},context:i}]},r));s.addEvent(`step.started`);let c=trace.setSpan(r,s);o.set(t.scope,{context:c,span:s}),a.set(t.scope.attemptId,t.scope)},onStepTerminal=async e=>{let t=a.get(e.scope.attemptId)??e.scope;i.delete(t),drainOpenSpans({...e,scope:t}),u.drain(e.scope.attemptId,e.type===`step.attempt.failed`?{error:e.error}:void 0),e.type===`step.attempt.failed`&&await c.failForAttempt(t,e.error),a.delete(e.scope.attemptId);let n=o.get(t);n!==void 0&&(n.span.addEvent(e.type===`step.attempt.completed`?`step.completed`:`step.failed`),e.type===`step.attempt.failed`&&recordAgentSpanError(n.span,e.error),n.span.end(),o.delete(t))},onTurnTerminal=async t=>{await e.stateStore.updateTurn(t.sessionId,t.turnId,e=>({...e,terminal:t.type===`turn.failed`?{error:t.error,type:t.type}:{type:t.type}}))},onSessionTransition=async t=>{if(await c.flushForSessionTransition(t),t.type===`session.failed`&&t.turnId!==void 0&&await e.stateStore.updateTurn(t.sessionId,t.turnId,e=>({...e,terminal:e.terminal??{error:t.error,type:`turn.failed`}})),t.turnId!==void 0){let n=await e.stateStore.getTurn(t.sessionId,t.turnId);if(n!==void 0){let r=await e.stateStore.getSession(t.sessionId);if(isSampledTrace(n.context)){let i=r?.agentName??n.subagentName,a=withChannelAudience(ROOT_CONTEXT,r?.channelAudience),startSpan=()=>e.tracer.startSpan(agentInvocationSpanName(i),{attributes:runtimeAttributes.agentActivationAttributes({agentName:i,frameworkVersion:e.frameworkVersion,sessionId:t.sessionId,turnId:t.turnId,turn:n}),kind:SpanKind.INTERNAL,links:agentActivationLinks(n),root:!0,startTime:n.startTimeMs},a),o=e.idGenerator.withSpanId(n.context.spanId,()=>e.idGenerator.withTraceId(n.context.traceId,startSpan));setAgentInvocationUsage(o,n.modelUsage),o.addEvent(`turn.started`,void 0,n.startTimeMs),n.terminal!==void 0&&(o.setAttribute(`agent.turn.outcome`,n.terminal.type===`turn.completed`?`completed`:n.terminal.type===`turn.cancelled`?`cancelled`:`failed`),o.addEvent(n.terminal.type),n.terminal.type===`turn.failed`&&recordAgentSpanError(o,n.terminal.error)),o.end()}await e.stateStore.deleteTurn(t.sessionId,t.turnId)}}(t.type===`session.completed`||t.type===`session.failed`)&&(await c.deleteForSession(t.sessionId),await e.stateStore.deleteSession(t.sessionId))},onModelCallStarted=t=>{let r=o.get(t.scope);if(r===void 0)return;r.span.setAttribute(`agent.model.id`,t.model.modelId),r.span.setAttribute(`agent.model.provider`,t.model.provider);let i=e.tracer.startSpan(modelSpanName(t.model.modelId),{attributes:{"gen_ai.agent.name":t.scope.functionId,"gen_ai.operation.name":`chat`,"gen_ai.provider.name":t.model.provider,"gen_ai.request.model":t.model.modelId,...agentSpanNamingAttributes(modelSpanName(t.model.modelId),`chat`),...agentTraceIdentityAttributes({rootSessionId:t.scope.rootSessionId??t.scope.sessionId,sessionId:t.scope.sessionId}),...runtimeAttributes.runtimeContextAttributes(t.runtimeContext)},kind:SpanKind.CLIENT},r.context);if(n&&t.input!==void 0){let e=genAiInputMessagesAttribute(t.input.messages);e!==void 0&&i.setAttribute(`gen_ai.input.messages`,e);let n=systemPromptAttribute(t.input.instructions);n!==void 0&&i.setAttribute(`ai.prompt.system`,n);let r=genAiSystemInstructionsAttribute(t.input.instructions);r!==void 0&&i.setAttribute(`gen_ai.system_instructions`,r)}let a={context:trace.setSpan(r.context,i),span:i};getExecutionContexts(t.scope).set(t.idempotencyKey,a.context),getSpanStates(s,t.scope).set(t.idempotencyKey,a)},onModelCallTerminal=async e=>{i.get(e.scope)?.delete(e.idempotencyKey);let t=takeSpanState(s,e.scope,e.idempotencyKey);if(t!==void 0){if(e.type===`model.call.failed`)recordAgentSpanError(t.span,e.error);else{await recordTurnUsage(e),setGenAiUsage(t.span,e.usage),e.responseId!==void 0&&t.span.setAttribute(`gen_ai.response.id`,e.responseId),t.span.setAttribute(`gen_ai.response.finish_reasons`,[e.finishReason]);let n=o.get(e.scope);if(n!==void 0&&setAgentUsage(n.span,e.usage),r){t.span.setAttribute(`ai.response.finish_reason`,e.finishReason);let n=e.content;if(n===void 0){t.span.end();return}let r=genAiOutputMessagesAttribute(n,e.finishReason);r!==void 0&&t.span.setAttribute(`gen_ai.output.messages`,r);let i=textContentAttribute(n.filter(e=>e.type===`reasoning`).map(e=>e.text).filter(e=>e.trim().length>0).join(`
2
+ `));i!==void 0&&t.span.setAttribute(`ai.response.reasoning`,i);let a=textContentAttribute(n.filter(e=>e.type===`text`).map(e=>e.text).join(``));a!==void 0&&t.span.setAttribute(`ai.response.text`,a);let o=n.filter(e=>e.type===`tool-call`).map(e=>({callId:e.callId,input:e.input,toolName:e.toolName}));if(o.length>0){let e=contentAttribute(o);e!==void 0&&t.span.setAttribute(`ai.response.tool_calls`,e)}let s=n.filter(e=>e.type===`tool-result`||e.type===`tool-error`).map(e=>e.type===`tool-result`?{callId:e.callId,input:e.input,output:e.output,toolName:e.toolName}:{callId:e.callId,error:errorText(e.error),input:e.input,toolName:e.toolName});if(s.length>0){let e=toolResultsContentAttribute(s);e!==void 0&&t.span.setAttribute(`ai.response.tool_results`,e)}}}t.span.end()}},recordTurnUsage=async t=>{(t.usage.inputTokens!==void 0||t.usage.outputTokens!==void 0)&&await e.stateStore.updateTurn(t.scope.sessionId,t.scope.turnId,e=>({...e,modelUsage:{inputTokens:t.usage.inputTokens===void 0?e.modelUsage?.inputTokens:(e.modelUsage?.inputTokens??0)+t.usage.inputTokens,outputTokens:t.usage.outputTokens===void 0?e.modelUsage?.outputTokens:(e.modelUsage?.outputTokens??0)+t.usage.outputTokens}}))},h=createAgentChannelDeliveryInstrumentation({ensureSessionContext:f,recordInputs:n,stateStore:e.stateStore}),onStepMetadata=e=>{let t=o.get(e.scope);if(t===void 0)return;let n=readGatewayCost(e.providerMetadata);if(n!==void 0)for(let[e,r]of Object.entries(n))t.span.setAttribute(e,r)};return{hook:{flush:c.flushSettledInvocations,events:{...h,"action.completed":c.events[`action.completed`],"action.failed":c.events[`action.failed`],async"action.started"(e,t){await c.events[`action.started`](e,t),await u.actionStarted(e)},...l,...d.events,"step.attempt.completed":onStepTerminal,"step.attempt.failed":onStepTerminal,"step.attempt.metadata":onStepMetadata,"step.attempt.started":onStepStarted,"model.call.completed":onModelCallTerminal,"model.call.failed":onModelCallTerminal,"model.call.started":onModelCallStarted,"session.completed":onSessionTransition,"session.failed":onSessionTransition,"session.started":onSessionStarted,"session.waiting":onSessionTransition,...u.events,"turn.cancelled":onTurnTerminal,"turn.completed":onTurnTerminal,"turn.failed":onTurnTerminal,"turn.started":onTurnStarted},name:`eve.otel`,projectEvent,tracePolicy:()=>({emit:!0,recordInputs:n,recordOutputs:r})},prepareSessionTrace:p,prepareTurnTrace:m,async runInContext(n,o){if(n.type===`memory.operation`)return d.runInContext(n,o);let s=a.get(n.scope.attemptId)??n.scope,c=i.get(s),l=n.type===`model.call`?c?.get(n.idempotencyKey):u.contextFor(n.scope.attemptId,n.idempotencyKey);if(l===void 0){let t=await e.stateStore.getTurn(n.scope.sessionId,n.scope.turnId);t!==void 0&&(l=withChannelAudience(contextFromSpanContext(t.context),n.scope.channelAudience),isSampledTrace(t.context)||(l=suppressTracing(l)))}let f=await e.stateStore.getSession(n.scope.sessionId),p=resolveForwardedTraceSeed(contextStorage.getStore()?.get(SessionTraceSeedKey)),m=p?.decision??f?.decision,h=m===void 0?void 0:applyLiveDeliveryAudienceCeiling(m,normalizeChannelAudience(n.scope.channelAudience),p?.forwardedTracePolicy,t);return l===void 0?o():context.with(markAgentTraceContext(withErrorContent(l,r&&h?.action===`record`&&h.recordOutputs)),o)}};function getExecutionContexts(e){let t=i.get(e);return t===void 0&&(t=new Map,i.set(e,t)),t}function drainOpenSpans(e){for(let t of s.get(e.scope)?.values()??[])e.type===`step.attempt.failed`&&recordAgentSpanError(t.span,e.error),t.span.end();s.delete(e.scope)}}function agentActivationLinks(e){let t=[];return e.caller!==void 0&&t.push({context:e.caller,attributes:{"eve.link.type":`agent.dispatch`}}),e.channelDelivery?.requestTraceContext!==void 0&&t.push({context:e.channelDelivery.requestTraceContext,attributes:{"eve.link.type":`channel.request`}}),t.length===0?void 0:t}function sessionIdForEvent(e){return`scope`in e?e.scope.sessionId:e.sessionId}function audienceForEvent(e,t){return`delivery`in e?normalizeChannelAudience(e.delivery.channelAudience):`scope`in e&&e.scope.channelAudience!==void 0?normalizeChannelAudience(e.scope.channelAudience):e.type===`session.started`?normalizeChannelAudience(e.channelAudience):normalizeChannelAudience(t)}function getSpanStates(e,t){let n=e.get(t);return n===void 0&&(n=new Map,e.set(t,n)),n}function takeSpanState(e,t,n){let r=e.get(t),i=r?.get(n);if(r!==void 0)return r.delete(n),r.size===0&&e.delete(t),i}function contextFromSpanContext(e){return trace.setSpan(ROOT_CONTEXT,trace.wrapSpanContext(e))}function modelSpanName(e){return`chat ${e}`}function errorText(e){return e instanceof Error?e.message:e}export{createAgentOtelInstrumentation};
@@ -3,7 +3,9 @@ import type { AgentSpanIdGenerator } from "#tracing/agent-span-id-generator.js";
3
3
  import type { TraceCapturePolicy } from "#tracing/otel-declaration.js";
4
4
  import type { AgentSessionTraceState, AgentTraceStateStore } from "#tracing/agent-trace-state.js";
5
5
  import { type AgentSamplingOperation } from "#tracing/agent-span-contract.js";
6
+ import type { ConversationEnvironment } from "#shared/conversation-context.js";
6
7
  interface AgentOtelSessionContextInput {
8
+ readonly environment: ConversationEnvironment;
7
9
  readonly frameworkVersion: string;
8
10
  readonly idGenerator: AgentSpanIdGenerator;
9
11
  readonly samplesTrace?: (traceId: string, operation?: AgentSamplingOperation) => boolean;
@@ -1 +1 @@
1
- import{normalizeChannelAudience}from"#shared/channel-audience.js";import{agentInvocationSpanName}from"#tracing/agent-span-contract.js";import{isSampledTrace,resolveTracePolicy,resolveTracePolicyDecision}from"#tracing/sampled-trace.js";import"#instrumentation/lifecycle.js";import{readInstrumentationDecision}from"#shared/instrumentation-decision.js";import{applyPrincipalTraceDecision}from"#instrumentation/principal-summary.js";import{agentActivationAttributes}from"#tracing/agent-otel-runtime-context.js";function createAgentOtelSessionContext(e){let ensureSessionContext=async t=>{let n=await e.stateStore.getSession(t.sessionId);if(n===void 0){let r=normalizeChannelAudience(t.channelAudience),i=resolveSessionTraceDecision(t,r,e.tracePolicy);n={agentName:t.agentName,channelAudience:r,channelKind:t.channelKind,decision:i,context:initialSessionContext(e,t,i),rootSessionId:t.rootSessionId,parentLineage:t.parentLineage},await e.stateStore.setSession(t.sessionId,n)}return n};return{ensureSessionContext,prepareSessionTrace:async e=>{let t=await ensureSessionContext(e);return portableSpanContext(t.context,t.decision)},prepareTurnTrace:async t=>{let n=await e.stateStore.getTurn(t.sessionId,t.turnId);if(n!==void 0){let r=await e.stateStore.getSession(t.sessionId);return portableSpanContext(n.context,r?.decision)}let r=await ensureSessionContext(t),i=t.sequence===0,a=i?t.parentTraceContext:void 0,o=i?{...r.context,isRemote:!1}:freshTurnContext(e,t.idempotencyKey,r.decision),s={caller:a===void 0?void 0:adoptedSpanContext(a),context:o,currentPrincipal:applyPrincipalTraceDecision(t.currentPrincipal,r.decision),initiatorPrincipal:applyPrincipalTraceDecision(t.initiatorPrincipal,r.decision),parentLineage:t.parentLineage??r.parentLineage,rootSessionId:t.rootSessionId,sequence:t.sequence,startTimeMs:Date.now(),subagentName:(t.parentLineage??r.parentLineage)?.subagentName};if(isSampledTrace(s.context)){let n=r.agentName??s.subagentName,i=e.samplesTrace?.(s.context.traceId,{name:agentInvocationSpanName(n),attributes:agentActivationAttributes({agentName:n,frameworkVersion:e.frameworkVersion,sessionId:t.sessionId,turnId:t.turnId,turn:s})})??!0;o={...o,traceFlags:+!!i}}return await e.stateStore.setTurn(t.sessionId,t.turnId,{...s,context:o}),portableSpanContext(o,r.decision)}}}function portableSpanContext(e,t){return{decision:t,spanId:e.spanId,traceFlags:e.traceFlags,traceId:e.traceId}}function adoptedSpanContext(e){return{isRemote:`isRemote`in e&&e.isRemote===!0,spanId:e.spanId,traceFlags:e.traceFlags,traceId:e.traceId}}function initialSessionContext(e,t,n){let r=t.traceSeed;if(r!==void 0)return{...adoptedSpanContext(r),traceFlags:n.action===`drop`?0:r.traceFlags};let i=e.idGenerator.deriveTraceId(`session:${t.sessionId}`),a=n.action===`record`;return{isRemote:!1,spanId:e.idGenerator.deriveSpanId(`session:${t.sessionId}`),traceFlags:+!!a,traceId:i}}function freshTurnContext(e,t,n){let r=e.idGenerator.deriveTraceId(`turn:${t}`),i=n?.action===`record`;return{isRemote:!1,spanId:e.idGenerator.deriveSpanId(`turn:${t}`),traceFlags:+!!i,traceId:r}}function resolveSessionTraceDecision(e,t,n){return e.parentTraceContext!==void 0&&!isSampledTrace(e.parentTraceContext)?{action:`drop`}:e.traceSeed?.decision===void 0?e.traceSeed===void 0?e.parentTraceContext===void 0?e.agentName===void 0?n===void 0?resolveTracePolicyDecision(!0,t):{action:`drop`}:resolveTracePolicy(n,{agentName:e.agentName,audience:t,channelType:e.channelType}):resolveTracePolicyDecision(isSampledTrace(e.parentTraceContext),t):resolveTracePolicyDecision(isSampledTrace(e.traceSeed),t):readInstrumentationDecision(e.traceSeed.decision)??{action:`drop`}}export{createAgentOtelSessionContext};
1
+ import{normalizeChannelAudience}from"#shared/channel-audience.js";import{normalizeInstrumentationChannelKind}from"#internal/instrumentation.js";import{agentInvocationSpanName}from"#tracing/agent-span-contract.js";import{isSampledTrace,resolveTracePolicy,resolveTracePolicyDecision}from"#tracing/sampled-trace.js";import"#instrumentation/lifecycle.js";import{readInstrumentationDecision}from"#shared/instrumentation-decision.js";import{applyPrincipalTraceDecision}from"#instrumentation/principal-summary.js";import{agentActivationAttributes}from"#tracing/agent-otel-runtime-context.js";function createAgentOtelSessionContext(e){let ensureSessionContext=async t=>{let n=await e.stateStore.getSession(t.sessionId);if(n===void 0){let r=normalizeChannelAudience(t.channelAudience),i=resolveSessionTraceDecision(t,r,e.environment,e.tracePolicy);n={agentName:t.agentName,channelAudience:r,channelKind:t.channelKind,decision:i,context:initialSessionContext(e,t,i),rootSessionId:t.rootSessionId,parentLineage:t.parentLineage},await e.stateStore.setSession(t.sessionId,n)}return n};return{ensureSessionContext,prepareSessionTrace:async e=>{let t=await ensureSessionContext(e);return portableSpanContext(t.context,t.decision)},prepareTurnTrace:async t=>{let n=await e.stateStore.getTurn(t.sessionId,t.turnId);if(n!==void 0){let r=await e.stateStore.getSession(t.sessionId);return portableSpanContext(n.context,r?.decision)}let r=await ensureSessionContext(t),i=t.sequence===0,a=i?t.parentTraceContext:void 0,o=i?{...r.context,isRemote:!1}:freshTurnContext(e,t.idempotencyKey,r.decision),s={caller:a===void 0?void 0:adoptedSpanContext(a),context:o,currentPrincipal:applyPrincipalTraceDecision(t.currentPrincipal,r.decision),initiatorPrincipal:applyPrincipalTraceDecision(t.initiatorPrincipal,r.decision),parentLineage:t.parentLineage??r.parentLineage,rootSessionId:t.rootSessionId,sequence:t.sequence,startTimeMs:Date.now(),subagentName:(t.parentLineage??r.parentLineage)?.subagentName};if(isSampledTrace(s.context)){let n=r.agentName??s.subagentName,i=e.samplesTrace?.(s.context.traceId,{name:agentInvocationSpanName(n),attributes:agentActivationAttributes({agentName:n,frameworkVersion:e.frameworkVersion,sessionId:t.sessionId,turnId:t.turnId,turn:s})})??!0;o={...o,traceFlags:+!!i}}return await e.stateStore.setTurn(t.sessionId,t.turnId,{...s,context:o}),portableSpanContext(o,r.decision)}}}function portableSpanContext(e,t){return{decision:t,spanId:e.spanId,traceFlags:e.traceFlags,traceId:e.traceId}}function adoptedSpanContext(e){return{isRemote:`isRemote`in e&&e.isRemote===!0,spanId:e.spanId,traceFlags:e.traceFlags,traceId:e.traceId}}function initialSessionContext(e,t,n){let r=t.traceSeed;if(r!==void 0)return{...adoptedSpanContext(r),traceFlags:n.action===`drop`?0:r.traceFlags};let i=e.idGenerator.deriveTraceId(`session:${t.sessionId}`),a=n.action===`record`;return{isRemote:!1,spanId:e.idGenerator.deriveSpanId(`session:${t.sessionId}`),traceFlags:+!!a,traceId:i}}function freshTurnContext(e,t,n){let r=e.idGenerator.deriveTraceId(`turn:${t}`),i=n?.action===`record`;return{isRemote:!1,spanId:e.idGenerator.deriveSpanId(`turn:${t}`),traceFlags:+!!i,traceId:r}}function resolveSessionTraceDecision(e,t,n,r){let i={audience:t,environment:n};return e.parentTraceContext!==void 0&&!isSampledTrace(e.parentTraceContext)?{action:`drop`}:e.traceSeed?.decision===void 0?e.traceSeed===void 0?e.parentTraceContext===void 0?e.agentName===void 0?r===void 0?resolveTracePolicyDecision(!0,i):{action:`drop`}:resolveTracePolicy(r,{agentName:e.agentName,audience:t,channel:{kind:normalizeInstrumentationChannelKind(e.channelKind??e.channelType)},environment:n,mode:`conversation`,principalType:`unknown`}):resolveTracePolicyDecision(isSampledTrace(e.parentTraceContext),i):resolveTracePolicyDecision(isSampledTrace(e.traceSeed),i):readInstrumentationDecision(e.traceSeed.decision)??{action:`drop`}}export{createAgentOtelSessionContext};
@@ -1 +1 @@
1
- import{createLogger}from"#internal/logging.js";import{contextStorage,loadContext}from"#context/container.js";import{SessionTraceSeedKey}from"#context/keys.js";import{ContextKey}from"#context/key.js";import{decisionToTraceContentCeiling,resolveForwardedTraceSeed}from"#shared/forwarded-trace-policy.js";import{getWorkflowToolRuns}from"#harness/workflow-tool-runs.js";import{getSessionTaskIndex}from"#tasks/session-index.js";import{deriveTaskId}from"#tasks/task-id.js";import{actionIdempotencyKey}from"#instrumentation/lifecycle.js";import{AGENT_TRACE_CONTEXT_KEY,deserializeAgentTraceContextState,emptyAgentTraceContextState,serializeAgentTraceContextState}from"#tracing/agent-trace-context-codec.js";const AgentTraceContextKey=new ContextKey(AGENT_TRACE_CONTEXT_KEY,{codec:{deserialize:deserializeAgentTraceContextState,serialize:serializeAgentTraceContextState}});function pruneAgentTraceState(e,t,n){try{pruneTraceOwnership(e,t,n)}catch(e){createLogger(`tracing.retention`).warn(`could not reconcile trace ownership; preserving trace state`,{error:e})}}function pruneTraceOwnership(e,t,n){let r=e.get(AgentTraceContextKey);if(r===void 0)return;let i=new Set(getWorkflowToolRuns(n).map(e=>e.callId)),a=new Set(getSessionTaskIndex(n).filter(e=>e.terminalView===void 0).map(e=>e.taskId)),o=Object.fromEntries(Object.entries(r.actionAnchors).filter(([e,n])=>n.sessionId!==t||r.actions[e]!==void 0||i.has(n.callId)||a.has(deriveTaskId({callId:n.callId,parentSessionId:t,parentTurnId:n.turnId})))),s=new Set(Object.values(o).filter(e=>e.sessionId===t).map(e=>e.callId)),c=Object.fromEntries(Object.entries(r.invocations).filter(([,e])=>e.sessionId!==t||e.terminal!==void 0||s.has(e.parentActionCallId)));e.set(AgentTraceContextKey,{...r,actionAnchors:o,invocations:c})}function readCurrentSessionTraceDecision(e){let t=contextStorage.getStore();return t===void 0?void 0:readSessionTraceDecision(t,e)}function readSessionTraceDecision(e,t){return e.get(AgentTraceContextKey)?.sessions[t]?.decision}function preserveSerializedAgentTraceState(e,t){let n=t[AgentTraceContextKey.name];return n===void 0?e:{...e,[AgentTraceContextKey.name]:n}}function readTurnTraceContext(e,t,n){let r=e[AgentTraceContextKey.name];if(r===void 0)return;let i=deserializeAgentTraceContextState(r),a=i.turns[turnKey(t,n)];return a===void 0?void 0:withTraceDecision(e,a.context,i.sessions[t]?.decision)}function readActionTraceContext(e,t,n,r){let i=e[AgentTraceContextKey.name];if(i===void 0)return;let a=deserializeAgentTraceContextState(i),o=actionIdempotencyKey(t,n,r),s=a.invocations[o]??a.actions[o]??a.actionAnchors[o];if(s!==void 0)return withTraceDecision(e,{isRemote:!1,spanId:s.spanId,traceFlags:s.parent.traceFlags,traceId:s.parent.traceId},a.sessions[s.sessionId]?.decision)}function readTaskActionTrace(e,t,n){let r=deserializeAgentTraceContextState(e[AgentTraceContextKey.name]);return Object.values(r.actionAnchors).find(e=>e.sessionId===t&&deriveTaskId({callId:e.callId,parentSessionId:t,parentTurnId:e.turnId})===n)}function recordNestedAgentInvocation(e){let t=e.serializedContext[AgentTraceContextKey.name];if(t===void 0)return e.serializedContext;let n=deserializeAgentTraceContextState(t),r=actionIdempotencyKey(e.sessionId,e.turnId,e.outerCallId),i=n.actions[r]??n.actionAnchors[r];if(i===void 0)return e.serializedContext;let a=actionIdempotencyKey(e.sessionId,e.turnId,e.callId),promote=e=>e.isWorkflowTool===!0&&e.kind===`tool-call`?{...e,workflowName:e.name}:e,o=n.actions[r]===void 0?n.actions:{...n.actions,[r]:promote(n.actions[r])},s=n.actionAnchors[r]===void 0?n.actionAnchors:{...n.actionAnchors,[r]:promote(n.actionAnchors[r])};if(n.invocations[a]!==void 0)return{...e.serializedContext,[AgentTraceContextKey.name]:serializeAgentTraceContextState({...n,actionAnchors:s,actions:o})};let c={attemptIndex:i.attemptIndex,callId:e.callId,channelAudience:i.channelAudience,kind:e.kind,name:e.name,parent:{spanId:i.spanId,traceFlags:i.parent.traceFlags,traceId:i.parent.traceId},parentActionCallId:e.outerCallId,recordOutputs:e.recordOutputs===!0,rootSessionId:i.rootSessionId,sessionId:i.sessionId,spanId:e.spanId,startTimeMs:e.startTimeMs,stepIndex:i.stepIndex,turnId:i.turnId};return{...e.serializedContext,[AgentTraceContextKey.name]:serializeAgentTraceContextState({...n,actionAnchors:s,actions:o,invocations:{...n.invocations,[a]:c}})}}function recordActionInvocationKind(e){let t=e.serializedContext[AgentTraceContextKey.name];if(t===void 0)return e.serializedContext;let n=deserializeAgentTraceContextState(t),update=t=>t.sessionId===e.sessionId&&t.turnId===e.turnId&&t.callId===e.callId?{...t,isWorkflowTool:void 0,kind:e.kind,workflowName:void 0}:t;return{...e.serializedContext,[AgentTraceContextKey.name]:serializeAgentTraceContextState({...n,actionAnchors:Object.fromEntries(Object.entries(n.actionAnchors).map(([e,t])=>[e,update(t)])),actions:Object.fromEntries(Object.entries(n.actions).map(([e,t])=>[e,update(t)]))})}}function withTraceDecision(e,t,n){let r=e[SessionTraceSeedKey.name],i=resolveForwardedTraceSeed({decision:n??r?.decision,forwardedTracePolicy:r?.forwardedTracePolicy,traceFlags:t.traceFlags}),a=i.decision,o=i.forwardedTracePolicy,s=decisionToTraceContentCeiling(a),c={...t,traceFlags:i.traceFlags};if(o===void 0)return a===void 0?c:{...c,decision:a};let l=s===void 0?o:{...o,ceiling:s};return a===void 0?{...c,forwardedTracePolicy:l}:{...c,decision:a,forwardedTracePolicy:l}}var ContextAgentTraceStateStore=class{deleteAction(e){updateState(t=>{let n={...t.actions};return delete n[e],{...t,actions:n}})}deleteActionAnchors(e){updateState(t=>({...t,actionAnchors:Object.fromEntries(Object.entries(t.actionAnchors).filter(([,t])=>t.sessionId!==e))}))}deleteActions(e,t){updateState(n=>{let r={...n.actions};for(let[n,i]of Object.entries(r))i.sessionId===e&&(t===void 0||i.turnId===t)&&delete r[n];return{...n,actions:r}})}deleteInvocation(e){updateState(t=>{let n={...t.invocations};return delete n[e],{...t,invocations:n}})}deleteInvocations(e,t){updateState(n=>({...n,invocations:Object.fromEntries(Object.entries(n.invocations).filter(([,n])=>n.sessionId!==e||t!==void 0&&n.turnId!==t))}))}deleteSession(e){updateState(t=>{let n={...t.sessions};return delete n[e],{...t,sessions:n}})}deleteTurn(e,t){updateState(n=>{let r={...n.turns};return delete r[turnKey(e,t)],{...n,turns:r}})}findAction(e,t){return Object.values(contextStorage.getStore()?.get(AgentTraceContextKey)?.actions??{}).find(n=>n.sessionId===e&&n.callId===t)}findActionAnchor(e,t,n){return Object.values(contextStorage.getStore()?.get(AgentTraceContextKey)?.actionAnchors??{}).find(r=>r.sessionId===e&&r.turnId===t&&r.callId===n)}findInvocations(e,t,n){return Object.values(contextStorage.getStore()?.get(AgentTraceContextKey)?.invocations??{}).filter(r=>(e===void 0||r.sessionId===e)&&(t===void 0||r.turnId===t)&&(n===void 0||r.parentActionCallId===n))}getAction(e){return contextStorage.getStore()?.get(AgentTraceContextKey)?.actions[e]}getSession(e){return contextStorage.getStore()?.get(AgentTraceContextKey)?.sessions[e]}getTurn(e,t){return contextStorage.getStore()?.get(AgentTraceContextKey)?.turns[turnKey(e,t)]}setAction(e,t){updateState(n=>({...n,actions:{...n.actions,[e]:t}}))}setActionAnchor(e,t){updateState(n=>({...n,actionAnchors:{...n.actionAnchors,[e]:t}}))}setInvocation(e,t){updateState(n=>({...n,invocations:{...n.invocations,[e]:t}}))}setSession(e,t){updateState(n=>({...n,sessions:{...n.sessions,[e]:t}}))}setTurn(e,t,n){updateState(r=>({...r,turns:{...r.turns,[turnKey(e,t)]:n}}))}updateTurn(e,t,n){updateState(r=>{let i=turnKey(e,t),a=r.turns[i];return a===void 0?r:{...r,turns:{...r.turns,[i]:n(a)}}})}};function updateState(e){loadContext().set(AgentTraceContextKey,t=>e(t??emptyAgentTraceContextState()))}function turnKey(e,t){return`${e}\0${t}`}export{ContextAgentTraceStateStore,preserveSerializedAgentTraceState,pruneAgentTraceState,readActionTraceContext,readCurrentSessionTraceDecision,readSessionTraceDecision,readTaskActionTrace,readTurnTraceContext,recordActionInvocationKind,recordNestedAgentInvocation};
1
+ import{createLogger}from"#internal/logging.js";import{decisionToTraceContentCeiling,resolveForwardedTraceSeed}from"#shared/forwarded-trace-policy.js";import{contextStorage,loadContext}from"#context/container.js";import{SessionTraceSeedKey}from"#context/keys.js";import{ContextKey}from"#context/key.js";import{getWorkflowToolRuns}from"#harness/workflow-tool-runs.js";import{getSessionTaskIndex}from"#tasks/session-index.js";import{deriveTaskId}from"#tasks/task-id.js";import{actionIdempotencyKey}from"#instrumentation/lifecycle.js";import{AGENT_TRACE_CONTEXT_KEY,deserializeAgentTraceContextState,emptyAgentTraceContextState,serializeAgentTraceContextState}from"#tracing/agent-trace-context-codec.js";const AgentTraceContextKey=new ContextKey(AGENT_TRACE_CONTEXT_KEY,{codec:{deserialize:deserializeAgentTraceContextState,serialize:serializeAgentTraceContextState}});function pruneAgentTraceState(e,t,n){try{pruneTraceOwnership(e,t,n)}catch(e){createLogger(`tracing.retention`).warn(`could not reconcile trace ownership; preserving trace state`,{error:e})}}function pruneTraceOwnership(e,t,n){let r=e.get(AgentTraceContextKey);if(r===void 0)return;let i=new Set(getWorkflowToolRuns(n).map(e=>e.callId)),a=new Set(getSessionTaskIndex(n).filter(e=>e.terminalView===void 0).map(e=>e.taskId)),o=Object.fromEntries(Object.entries(r.actionAnchors).filter(([e,n])=>n.sessionId!==t||r.actions[e]!==void 0||i.has(n.callId)||a.has(deriveTaskId({callId:n.callId,parentSessionId:t,parentTurnId:n.turnId})))),s=new Set(Object.values(o).filter(e=>e.sessionId===t).map(e=>e.callId)),c=Object.fromEntries(Object.entries(r.invocations).filter(([,e])=>e.sessionId!==t||e.terminal!==void 0||s.has(e.parentActionCallId)));e.set(AgentTraceContextKey,{...r,actionAnchors:o,invocations:c})}function readCurrentSessionTraceDecision(e){let t=contextStorage.getStore();return t===void 0?void 0:readSessionTraceDecision(t,e)}function readSessionTraceDecision(e,t){return e.get(AgentTraceContextKey)?.sessions[t]?.decision}function preserveSerializedAgentTraceState(e,t){let n=t[AgentTraceContextKey.name];return n===void 0?e:{...e,[AgentTraceContextKey.name]:n}}function readTurnTraceContext(e,t,n){let r=e[AgentTraceContextKey.name];if(r===void 0)return;let i=deserializeAgentTraceContextState(r),a=i.turns[turnKey(t,n)];return a===void 0?void 0:withTraceDecision(e,a.context,i.sessions[t]?.decision)}function readActionTraceContext(e,t,n,r){let i=e[AgentTraceContextKey.name];if(i===void 0)return;let a=deserializeAgentTraceContextState(i),o=actionIdempotencyKey(t,n,r),s=a.invocations[o]??a.actions[o]??a.actionAnchors[o];if(s!==void 0)return withTraceDecision(e,{isRemote:!1,spanId:s.spanId,traceFlags:s.parent.traceFlags,traceId:s.parent.traceId},a.sessions[s.sessionId]?.decision)}function readTaskActionTrace(e,t,n){let r=deserializeAgentTraceContextState(e[AgentTraceContextKey.name]);return Object.values(r.actionAnchors).find(e=>e.sessionId===t&&deriveTaskId({callId:e.callId,parentSessionId:t,parentTurnId:e.turnId})===n)}function recordNestedAgentInvocation(e){let t=e.serializedContext[AgentTraceContextKey.name];if(t===void 0)return e.serializedContext;let n=deserializeAgentTraceContextState(t),r=actionIdempotencyKey(e.sessionId,e.turnId,e.outerCallId),i=n.actions[r]??n.actionAnchors[r];if(i===void 0)return e.serializedContext;let a=actionIdempotencyKey(e.sessionId,e.turnId,e.callId),promote=e=>e.isWorkflowTool===!0&&e.kind===`tool-call`?{...e,workflowName:e.name}:e,o=n.actions[r]===void 0?n.actions:{...n.actions,[r]:promote(n.actions[r])},s=n.actionAnchors[r]===void 0?n.actionAnchors:{...n.actionAnchors,[r]:promote(n.actionAnchors[r])};if(n.invocations[a]!==void 0)return{...e.serializedContext,[AgentTraceContextKey.name]:serializeAgentTraceContextState({...n,actionAnchors:s,actions:o})};let c={attemptIndex:i.attemptIndex,callId:e.callId,channelAudience:i.channelAudience,kind:e.kind,name:e.name,parent:{spanId:i.spanId,traceFlags:i.parent.traceFlags,traceId:i.parent.traceId},parentActionCallId:e.outerCallId,recordOutputs:e.recordOutputs===!0,rootSessionId:i.rootSessionId,sessionId:i.sessionId,spanId:e.spanId,startTimeMs:e.startTimeMs,stepIndex:i.stepIndex,turnId:i.turnId};return{...e.serializedContext,[AgentTraceContextKey.name]:serializeAgentTraceContextState({...n,actionAnchors:s,actions:o,invocations:{...n.invocations,[a]:c}})}}function recordActionInvocationKind(e){let t=e.serializedContext[AgentTraceContextKey.name];if(t===void 0)return e.serializedContext;let n=deserializeAgentTraceContextState(t),update=t=>t.sessionId===e.sessionId&&t.turnId===e.turnId&&t.callId===e.callId?{...t,isWorkflowTool:void 0,kind:e.kind,workflowName:void 0}:t;return{...e.serializedContext,[AgentTraceContextKey.name]:serializeAgentTraceContextState({...n,actionAnchors:Object.fromEntries(Object.entries(n.actionAnchors).map(([e,t])=>[e,update(t)])),actions:Object.fromEntries(Object.entries(n.actions).map(([e,t])=>[e,update(t)]))})}}function withTraceDecision(e,t,n){let r=e[SessionTraceSeedKey.name],i=resolveForwardedTraceSeed({decision:n??r?.decision,forwardedTracePolicy:r?.forwardedTracePolicy,traceFlags:t.traceFlags}),a=i.decision,o=i.forwardedTracePolicy,s=decisionToTraceContentCeiling(a),c={...t,traceFlags:i.traceFlags};if(o===void 0)return a===void 0?c:{...c,decision:a};let l=s===void 0?o:{...o,ceiling:s};return a===void 0?{...c,forwardedTracePolicy:l}:{...c,decision:a,forwardedTracePolicy:l}}var ContextAgentTraceStateStore=class{deleteAction(e){updateState(t=>{let n={...t.actions};return delete n[e],{...t,actions:n}})}deleteActionAnchors(e){updateState(t=>({...t,actionAnchors:Object.fromEntries(Object.entries(t.actionAnchors).filter(([,t])=>t.sessionId!==e))}))}deleteActions(e,t){updateState(n=>{let r={...n.actions};for(let[n,i]of Object.entries(r))i.sessionId===e&&(t===void 0||i.turnId===t)&&delete r[n];return{...n,actions:r}})}deleteInvocation(e){updateState(t=>{let n={...t.invocations};return delete n[e],{...t,invocations:n}})}deleteInvocations(e,t){updateState(n=>({...n,invocations:Object.fromEntries(Object.entries(n.invocations).filter(([,n])=>n.sessionId!==e||t!==void 0&&n.turnId!==t))}))}deleteSession(e){updateState(t=>{let n={...t.sessions};return delete n[e],{...t,sessions:n}})}deleteTurn(e,t){updateState(n=>{let r={...n.turns};return delete r[turnKey(e,t)],{...n,turns:r}})}findAction(e,t){return Object.values(contextStorage.getStore()?.get(AgentTraceContextKey)?.actions??{}).find(n=>n.sessionId===e&&n.callId===t)}findActionAnchor(e,t,n){return Object.values(contextStorage.getStore()?.get(AgentTraceContextKey)?.actionAnchors??{}).find(r=>r.sessionId===e&&r.turnId===t&&r.callId===n)}findInvocations(e,t,n){return Object.values(contextStorage.getStore()?.get(AgentTraceContextKey)?.invocations??{}).filter(r=>(e===void 0||r.sessionId===e)&&(t===void 0||r.turnId===t)&&(n===void 0||r.parentActionCallId===n))}getAction(e){return contextStorage.getStore()?.get(AgentTraceContextKey)?.actions[e]}getSession(e){return contextStorage.getStore()?.get(AgentTraceContextKey)?.sessions[e]}getTurn(e,t){return contextStorage.getStore()?.get(AgentTraceContextKey)?.turns[turnKey(e,t)]}setAction(e,t){updateState(n=>({...n,actions:{...n.actions,[e]:t}}))}setActionAnchor(e,t){updateState(n=>({...n,actionAnchors:{...n.actionAnchors,[e]:t}}))}setInvocation(e,t){updateState(n=>({...n,invocations:{...n.invocations,[e]:t}}))}setSession(e,t){updateState(n=>({...n,sessions:{...n.sessions,[e]:t}}))}setTurn(e,t,n){updateState(r=>({...r,turns:{...r.turns,[turnKey(e,t)]:n}}))}updateTurn(e,t,n){updateState(r=>{let i=turnKey(e,t),a=r.turns[i];return a===void 0?r:{...r,turns:{...r.turns,[i]:n(a)}}})}};function updateState(e){loadContext().set(AgentTraceContextKey,t=>e(t??emptyAgentTraceContextState()))}function turnKey(e,t){return`${e}\0${t}`}export{ContextAgentTraceStateStore,preserveSerializedAgentTraceState,pruneAgentTraceState,readActionTraceContext,readCurrentSessionTraceDecision,readSessionTraceDecision,readTaskActionTrace,readTurnTraceContext,recordActionInvocationKind,recordNestedAgentInvocation};
@@ -1 +1 @@
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};
1
+ import{createLogger,formatError}from"#internal/logging.js";import{contextStorage}from"#context/container.js";import{ConversationIdKey}from"#context/keys.js";import{resolveInstrumentationEnvironment}from"#internal/application/dev-environment.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({environment:resolveInstrumentationEnvironment(),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};
@@ -1,6 +1,6 @@
1
1
  import { type InstrumentationRuntime } from "#instrumentation/runtime.js";
2
2
  import { type TraceCapturePolicy } from "#tracing/otel-declaration.js";
3
- /** Zero-config local tracing keeps unclassified HTTP/TUI sessions observable. @internal */
3
+ /** Zero-config local tracing keeps public and unclassified sessions observable. @internal */
4
4
  export declare const localTracePolicy: TraceCapturePolicy;
5
5
  /** Installs the zero-config local OTel runtime once in an `eve dev` worker. */
6
6
  export declare function installLocalInstrumentationRuntime(input: {
@@ -1 +1 @@
1
- import{getInstrumentationRuntime}from"#instrumentation/runtime.js";import{installInstrumentationRuntime}from"#tracing/install-instrumentation-runtime.js";import{collectOtelPipeline,managedOtelIntegration,otel}from"#tracing/otel-declaration.js";import{createLocalTracesProcessor,resolveLocalTracesContent}from"#tracing/local-traces.js";const localTracePolicy=({audience:e})=>e===`public`||e===`unknown`;function installLocalInstrumentationRuntime(e){let t=getInstrumentationRuntime();if(t!==void 0)return t;let n=createLocalTracesProcessor({appRoot:e.appRoot});return installInstrumentationRuntime({collected:collectOtelPipeline([otel({tracePolicy:localTracePolicy}),managedOtelIntegration({...resolveLocalTracesContent(),spanProcessors:[n]})]),frameworkVersion:e.frameworkVersion,providers:[],serviceName:e.serviceName})}export{installLocalInstrumentationRuntime,localTracePolicy};
1
+ import{getInstrumentationRuntime}from"#instrumentation/runtime.js";import{installInstrumentationRuntime}from"#tracing/install-instrumentation-runtime.js";import{collectOtelPipeline,managedOtelIntegration,otel}from"#tracing/otel-declaration.js";import{createLocalTracesProcessor,resolveLocalTracesContent}from"#tracing/local-traces.js";const localTracePolicy=({audience:e})=>e!==`private`;function installLocalInstrumentationRuntime(e){let t=getInstrumentationRuntime();if(t!==void 0)return t;let n=createLocalTracesProcessor({appRoot:e.appRoot});return installInstrumentationRuntime({collected:collectOtelPipeline([otel({tracePolicy:localTracePolicy}),managedOtelIntegration({...resolveLocalTracesContent(),spanProcessors:[n]})]),frameworkVersion:e.frameworkVersion,providers:[],serviceName:e.serviceName})}export{installLocalInstrumentationRuntime,localTracePolicy};
@@ -310,9 +310,29 @@ export default defineChannel({
310
310
 
311
311
  The projection is re-evaluated whenever adapter state changes after channel event handlers run. Dynamic tool resolvers read it via `ctx.channel.metadata` and narrow it with `isChannel`. See [Dynamic capabilities](../guides/dynamic-capabilities) for the full consumption pattern.
312
312
 
313
- Metadata may include an `audience` classification: `public`, `private`, or `unknown`. Omit it when the channel cannot classify the conversation confidently; eve normalizes missing and invalid values to `unknown`. Consumers must treat `unknown` as non-public.
313
+ ### Conversation audience
314
314
 
315
- When a parent agent dispatches a subagent, the framework forwards the parent's channel metadata projection to the child. The same `metadata(state)` projector also serves instrumentation metadata resolvers.
315
+ Use `audience(input)` to classify who can observe the conversation. The hook runs after route authentication and before the session is created:
316
+
317
+ ```ts
318
+ import { defineChannel, POST } from "eve/channels";
319
+
320
+ export default defineChannel({
321
+ state: { visibility: "workspace" as "workspace" | "private" | "unknown" },
322
+ audience({ state, auth }) {
323
+ if (state.visibility === "workspace") return "public";
324
+ if (auth?.principalType === "user") return "private";
325
+ return "unknown";
326
+ },
327
+ routes: [POST("/webhook", async () => new Response("ok"))],
328
+ });
329
+ ```
330
+
331
+ The input contains the channel's `state`, authenticated `auth` principal, `channel`, `mode`, and `environment`. Return `"public"`, `"private"`, or `"unknown"`. Return `"unknown"` when the channel does not have enough evidence to classify confidently; consumers treat it as non-public. A missing, throwing, asynchronous, or malformed classifier also fails closed to `"unknown"`.
332
+
333
+ Classification is fixed when the session is created. Continuation turns from a different caller do not reclassify an existing session. When a parent dispatches a local subagent, the child inherits the parent's audience while the framework forwards the parent's custom channel metadata separately.
334
+
335
+ `metadata(state)` remains a channel-owned projection of custom observability fields. It no longer carries a reserved `audience` key. Channel extensions built before channel epoch 20 can still use that key; eve accepts it as a deprecated fallback and warns once, then authors should move classification to `audience(input)`.
316
336
 
317
337
  ## Continuation tokens
318
338
 
@@ -157,6 +157,45 @@ Neither admits browser users or external clients in production. For a public app
157
157
 
158
158
  For the full auth model and helper list, see [Auth & route protection](../guides/auth-and-route-protection).
159
159
 
160
+ ## Audience
161
+
162
+ The eve channel classifies who can observe a session when that session is created:
163
+
164
+ | Session creator | Default audience |
165
+ | ----------------------------------------- | ---------------- |
166
+ | Anonymous caller | `public` |
167
+ | `user`, `service`, or `runtime` principal | `private` |
168
+ | Any other principal type | `unknown` |
169
+
170
+ Anonymous HTTP surfaces are public because anyone who can reach the surface can read it. Authenticated `user`, `service`, and `runtime` sessions are private because they belong to one identified party. Other authenticated principal types remain `unknown`: trace consumers record metadata but omit content by default in preview and production.
171
+
172
+ Pass a constant or a function to override the default:
173
+
174
+ ```ts title="agent/channels/eve.ts"
175
+ import { none, vercelOidc } from "eve/channels/auth";
176
+ import { eveChannel } from "eve/channels/eve";
177
+
178
+ export default eveChannel({
179
+ auth: [vercelOidc()],
180
+ audience: "private",
181
+ });
182
+ ```
183
+
184
+ ```ts title="agent/channels/eve.ts"
185
+ import { vercelOidc } from "eve/channels/auth";
186
+ import { eveChannel } from "eve/channels/eve";
187
+
188
+ export default eveChannel({
189
+ auth: [vercelOidc(), none()],
190
+ audience({ auth, environment }) {
191
+ if (auth === null) return environment === "development" ? "public" : "unknown";
192
+ return "private";
193
+ },
194
+ });
195
+ ```
196
+
197
+ The function receives the authenticated principal, channel, run mode, and deployment environment. Classification is fixed at session creation; a continuation turn from a different caller does not reclassify the session. When another eve deployment forwards a request without an accepted forwarded trace assertion, the calling deployment's principal is used for classification, so the session remains `private`. A custom [trace policy](../guides/instrumentation-providers#control-inputs-and-outputs) can still admit or deny content independently.
198
+
160
199
  ## Customization
161
200
 
162
201
  Use `onMessage` to add request-specific context before the agent sees the user message, and `events` to observe stream events from sessions this channel created:
@@ -453,6 +453,38 @@ export default slackChannel({
453
453
 
454
454
  The callback receives the `InputRequest` and current `SessionContext`, so it can switch on `kind`, `action`, or presentation properties. Omit it to keep every request in the thread, or return `"direct-message"` unconditionally to make every request private. If eve cannot resolve the triggering Slack user for a direct message, it logs the undelivered request and posts no fallback, so private delivery fails closed. The existing `onInputResponse` or tool approval response policy still decides whether the person who clicks may respond.
455
455
 
456
+ An authored `input.requested` handler can extend delivery and then hand the requests back to eve through `defaultDeliver()`. For example, an application can add non-sensitive context to the Slack thread before eve renders the actionable controls. The configured `approvalChannel` still sends sensitive reviews to a DM and keeps ordinary requests in the thread:
457
+
458
+ ```ts title="agent/channels/slack.ts"
459
+ import { slackChannel } from "eve/channels/slack";
460
+ import { isPrivate } from "../lib/review-policy";
461
+
462
+ export default slackChannel({
463
+ approvalChannel(request) {
464
+ return isPrivate(request) ? "direct-message" : "thread";
465
+ },
466
+ events: {
467
+ async "input.requested"(event, channel, _ctx, defaultDeliver) {
468
+ await channel.thread.post({
469
+ blocks: [
470
+ {
471
+ type: "context",
472
+ elements: [
473
+ {
474
+ type: "mrkdwn",
475
+ text: "A review is needed before this work can continue.",
476
+ },
477
+ ],
478
+ },
479
+ ],
480
+ text: "A review is needed before this work can continue.",
481
+ });
482
+ await defaultDeliver(event);
483
+ },
484
+ },
485
+ });
486
+ ```
487
+
456
488
  Authorization prompts split public status from private credentials. A sign-in challenge (OAuth URL, device code) is a credential. Anyone who completes it binds their identity to the session's connection. The default `authorization.required` handler posts a public, link-free status in the thread, delivers the actual challenge ephemerally to the triggering user, device code included, and then updates that public status when `authorization.completed` fires. The handler receives a private-delivery context with `postEphemeral`, `postDirectMessage` (needs the `im:write` scope), and `state`. There is, intentionally, no public `post` and no raw API access.
457
489
 
458
490
  ```ts
@@ -24,6 +24,20 @@ export default defineMcpClientConnection({
24
24
 
25
25
  The `url` must speak Streamable HTTP or SSE. Write the `description` for the model, not for yourself: it is the main signal `connection_search` uses when deciding which connection to query.
26
26
 
27
+ ## Configure protocol discovery
28
+
29
+ eve discovers the server's MCP protocol by default. If a server requires the older `initialize` handshake, disable discovery for that connection:
30
+
31
+ ```ts
32
+ export default defineMcpClientConnection({
33
+ url: "https://mcp.example.com/mcp",
34
+ description: "Search support cases",
35
+ protocolVersionDiscovery: false,
36
+ });
37
+ ```
38
+
39
+ With `protocolVersionDiscovery: false`, the client skips `server/discover` and starts with `initialize`, proposing `2025-11-25` and negotiating a supported handshake-based version. This is a per-connection setting; omitting it or setting it to `true` keeps discovery enabled. Remove the override when the server supports discovery. The setting also applies to connections returned by dynamic resolvers.
40
+
27
41
  ## Use Vercel Connect for OAuth
28
42
 
29
43
  For OAuth-backed MCP servers, use the shared [Vercel Connect flow](../connections#interactive-oauth-via-vercel-connect), then pass the returned connector UID to `connect()`. Keep the MCP runtime URL and Connect service identifier distinct. For example, Linear uses `https://mcp.linear.app/mcp` as the MCP endpoint and `mcp.linear.app` when creating the connector.
@@ -22,7 +22,9 @@ const nextConfig: NextConfig = {};
22
22
  export default withEve(nextConfig);
23
23
  ```
24
24
 
25
- By default `withEve()` looks for an `agent/` folder inside your Next.js project root. If the agent lives somewhere else, point at it with `eveRoot`:
25
+ By default `withEve()` looks for an `agent/` folder inside your Next.js project root. When the project root is an eve workspace with `agents/<name>/` members, it discovers every member and mounts each at `/eve/agents/<name>/eve/v1/*` instead.
26
+
27
+ If one agent lives somewhere else, point at it with `eveRoot`:
26
28
 
27
29
  ```ts
28
30
  export default withEve(nextConfig, {
@@ -30,7 +32,7 @@ export default withEve(nextConfig, {
30
32
  });
31
33
  ```
32
34
 
33
- For multiple agents, use `agents`. String values are agent roots; object values can override the build command or private production service prefix for that agent:
35
+ To mount agents that are not members of the project-level `agents/` workspace, use `agents`. String values are agent roots; object values can override the build command or private production service prefix for that agent:
34
36
 
35
37
  ```ts
36
38
  export default withEve(nextConfig, {
@@ -60,13 +62,13 @@ Generated agent services build with `EVE_PUBLIC_ROUTE_PREFIX` set to the agent's
60
62
 
61
63
  All fields are optional.
62
64
 
63
- | Option | Type | Default | Purpose |
64
- | -------------------- | --------------------- | ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
65
- | `eveRoot` | `string` | Next.js app root | Path to one unnamed eve app root, relative to `process.cwd()` unless absolute. Do not combine with `agents`. |
66
- | `agents` | `Record<string, ...>` | unset | Named eve agents to mount under `/eve/agents/<name>/eve/v1/*`. Each value is a root string or `{ root, buildCommand?, servicePrefix? }`. |
67
- | `eveBuildCommand` | `string` | generated | Build command for generated eve Vercel services. In multi-agent mode this is the default for agents without their own `buildCommand`. |
68
- | `servicePrefix` | `string` | `"/_eve_internal/eve"` | Private route namespace for legacy manual Vercel service configs and non-Vercel production proxying. Named agents derive unique defaults from this prefix. |
69
- | `devServerTimeoutMs` | `number` | `180000` | Maximum time to wait for each eve development server to become available. |
65
+ | Option | Type | Default | Purpose |
66
+ | -------------------- | --------------------- | ------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
67
+ | `eveRoot` | `string` | Next.js app root | Path to one unnamed eve app root, relative to `process.cwd()` unless absolute. Do not combine with `agents`. |
68
+ | `agents` | `Record<string, ...>` | inferred for a workspace | Named eve agents to mount under `/eve/agents/<name>/eve/v1/*`. `withEve()` discovers project-level `agents/<name>/` members when neither `agents` nor `eveRoot` is set; otherwise each value is a root string or `{ root, buildCommand?, servicePrefix? }`. |
69
+ | `eveBuildCommand` | `string` | generated | Build command for generated eve Vercel services. In multi-agent mode this is the default for agents without their own `buildCommand`. |
70
+ | `servicePrefix` | `string` | `"/_eve_internal/eve"` | Private route namespace for legacy manual Vercel service configs and non-Vercel production proxying. Named agents derive unique defaults from this prefix. |
71
+ | `devServerTimeoutMs` | `number` | `180000` | Maximum time to wait for each eve development server to become available. |
70
72
 
71
73
  For slow cold starts, increase the development timeout:
72
74
 
@@ -124,7 +126,7 @@ See [Resumable sessions](./overview#resumable-sessions) for persistence and repl
124
126
  });
125
127
  ```
126
128
 
127
- - **Local production build.** `next build && next start` serves the eve runtime from its built `.output/server/index.mjs` on a stable local port (`4274`) and proxies the eve routes to it. Run `eve build` first so that output exists. Change the port with `EVE_NEXT_PRODUCTION_PORT`:
129
+ - **Local production build.** `next build && next start` serves the eve runtime from its built `.output/server/index.mjs` on a stable local port (`4274`) and proxies the eve routes to it. Run `eve build` first so that output exists. In an `agents/` workspace, build every member from its `agents/<name>/` directory before starting Next.js. Change the port with `EVE_NEXT_PRODUCTION_PORT`:
128
130
 
129
131
  ```bash
130
132
  EVE_NEXT_PRODUCTION_PORT=5000 npm run build && npm start
@@ -65,10 +65,10 @@ Each provider has an independent `tracePolicy`. It decides whether the provider
65
65
  import { defineInstrumentation } from "eve/instrumentation";
66
66
 
67
67
  export default defineInstrumentation({
68
- tracePolicy: ({ audience }) => ({
68
+ tracePolicy: ({ audience, environment }) => ({
69
69
  emit: true,
70
- recordInputs: audience === "public",
71
- recordOutputs: audience === "public",
70
+ recordInputs: audience === "public" || environment === "development",
71
+ recordOutputs: audience === "public" || environment === "development",
72
72
  }),
73
73
  events: {
74
74
  "model.call.started": (event) => {
@@ -81,9 +81,11 @@ export default defineInstrumentation({
81
81
  });
82
82
  ```
83
83
 
84
- The policy receives `agentName`, `audience`, and, when available, `channelType`. `audience` is `"public"`, `"private"`, or `"unknown"`.
84
+ The policy receives `agentName`, `channel`, `audience`, `mode`, `environment`, and `principalType`. `audience` is `"public"`, `"private"`, or `"unknown"`. `environment` is `"development"`, `"preview"`, or `"production"`.
85
85
 
86
- The default policy emits metadata for every audience and includes inputs and outputs only for `public` conversations. Return an explicit decision to change that behavior:
86
+ `principalType` is the principal used for classification. Normal channels report their route or session principal; forwarded eve sessions report the calling deployment's principal. Sessions that predate the durable conversation key report their session initiator.
87
+
88
+ The default policy emits metadata for every audience and includes inputs and outputs for `public` conversations and for any audience in a development environment. Preview behaves like production: an `unknown` conversation records metadata only. Return an explicit decision to change that behavior:
87
89
 
88
90
  | Decision | Result |
89
91
  | --------------------------------------------- | ------------------------------------------------------------ |
@@ -162,10 +164,10 @@ import { otel } from "eve/instrumentation/otel";
162
164
 
163
165
  export default otel({
164
166
  resource: { "deployment.environment": process.env.VERCEL_ENV ?? "development" },
165
- tracePolicy: ({ audience }) => ({
167
+ tracePolicy: ({ audience, environment }) => ({
166
168
  emit: true,
167
- recordInputs: audience === "public",
168
- recordOutputs: audience === "public",
169
+ recordInputs: audience === "public" || environment === "development",
170
+ recordOutputs: audience === "public" || environment === "development",
169
171
  }),
170
172
  });
171
173
  ```
@@ -62,7 +62,7 @@ You are responsible for ensuring any observability or eval provider is approved
62
62
 
63
63
  The third configurable surface, [runtime context events](#runtime-context), attaches per-model-call values to these spans.
64
64
 
65
- Built-in messaging channels classify their instrumentation metadata with an `audience`: `public`, `private`, or `unknown`. Slack public channels and Chat SDK workspace-visible threads are public; direct and private conversations are private; platform surfaces without enough visibility evidence remain unknown. Proactive Slack `receive` / `ctx.send` handoffs stay `unknown` unless the caller passes `audience` on the target, for example when a webhook or schedule already knows the destination channel is public.
65
+ Channels classify their conversation with an `audience`: `public`, `private`, or `unknown`. The eve channel classifies anonymous callers as public and authenticated `user`, `service`, or `runtime` callers as private. Slack public-channel handoffs and Chat SDK workspace-visible threads are public; direct and private conversations are private; platform surfaces without enough visibility evidence remain unknown. Inbound Slack webhooks remain `unknown`; proactive Slack `receive` / `ctx.send` handoffs also stay `unknown` unless the caller passes `audience` on the target, for example when a webhook or schedule already knows the destination channel is public.
66
66
 
67
67
  ## Channel delivery traces
68
68
 
@@ -253,7 +253,7 @@ Agent Runs activation metadata includes bounded principal summaries:
253
253
 
254
254
  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`.
255
255
 
256
- 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.
256
+ Principal IDs require content-visible capture and a resolved trace decision that allows both `recordInputs` and `recordOutputs`. Public turns and every audience in a development environment can include IDs; private and unknown turns omit them in preview and production. 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.
257
257
 
258
258
  ## Query exported traces
259
259
 
@@ -173,7 +173,7 @@ export default eveChannel({
173
173
 
174
174
  The request must also include a callback and a valid sampled `traceparent`. Those fields identify a remote call, but they do not establish trust. `trustedForwarders` is the authorization boundary.
175
175
 
176
- The receiver combines the incoming ceiling with its own trace policy. Each hop may narrow the result, but it cannot restore inputs or outputs removed earlier. The original audience stays the same across remote and local subagent hops. Public origins may include content by default; private and unknown origins stay metadata-only unless both deployments explicitly allow them.
176
+ The receiver combines the incoming ceiling with its own trace policy. Each hop may narrow the result, but it cannot restore inputs or outputs removed earlier. The original audience stays the same across remote and local subagent hops. Public origins may include content by default. Private and unknown origins stay metadata-only in preview and production unless both deployments explicitly allow them; a receiver running in development still applies the development content default.
177
177
 
178
178
  The live delivery audience still matters. An unknown callback delivery, or one matching the origin, uses the session decision. A different explicit audience applies its own hard ceiling, so a private delivery stays redacted even when the trace began in public.
179
179
 
@@ -19,7 +19,7 @@ eve add memory/file
19
19
 
20
20
  If an item is not found, `eve add` searches the available catalogs and prints close matches without installing anything.
21
21
 
22
- Web Chat installs a project-level Next.js application and cannot currently be added to a top-level `agents/` workspace. For that topology, create a root Next.js application and configure [`withEve({ agents })`](./guides/frontend/nextjs) instead. eve rejects `eve add channel/web` before writing files when the selected agent belongs to such a workspace.
22
+ Web Chat installs a project-level Next.js application and cannot currently be added to a top-level `agents/` workspace. For that topology, create a root Next.js application and wrap its config with [`withEve()`](./guides/frontend/nextjs); eve discovers the workspace agents automatically. eve rejects `eve add channel/web` before writing files when the selected agent belongs to such a workspace.
23
23
 
24
24
  If you do not know an item name yet, run `eve add` without an argument. Its help output shows how to search the registry with `eve registry search <query>`.
25
25