eve 0.33.2 → 0.34.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 (228) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/dist/src/channel/channel-address.d.ts +3 -6
  3. package/dist/src/channel/channel-address.js +1 -1
  4. package/dist/src/channel/channel-operations.d.ts +2 -3
  5. package/dist/src/channel/delivery-metadata.d.ts +9 -0
  6. package/dist/src/channel/delivery-metadata.js +1 -0
  7. package/dist/src/channel/routes.d.ts +1 -0
  8. package/dist/src/channel/session.d.ts +3 -4
  9. package/dist/src/channel/session.js +1 -1
  10. package/dist/src/channel/types.d.ts +20 -3
  11. package/dist/src/chunks/{use-eve-agent-B-Hky2f4.js → use-eve-agent-BNdcle_M.js} +33 -0
  12. package/dist/src/chunks/{use-eve-agent-3oBnxzhV.js → use-eve-agent-FJkEMXYk.js} +33 -0
  13. package/dist/src/cli/dev/tui/traces/trace-conversation.js +1 -1
  14. package/dist/src/client/message-reducer.js +1 -1
  15. package/dist/src/compiled/.vendor-stamp.json +1 -1
  16. package/dist/src/compiled/@opentelemetry/api/index.d.ts +32 -3
  17. package/dist/src/compiled/@vercel/otel/index.d.ts +45 -2
  18. package/dist/src/compiler/extension-compatibility.d.ts +12 -12
  19. package/dist/src/compiler/extension-compatibility.js +1 -1
  20. package/dist/src/compiler/manifest.js +1 -1
  21. package/dist/src/compiler/normalize-agent-config.js +1 -1
  22. package/dist/src/context/build-dynamic-tools.d.ts +7 -0
  23. package/dist/src/context/build-dynamic-tools.js +1 -1
  24. package/dist/src/context/dynamic-tool-lifecycle.d.ts +7 -0
  25. package/dist/src/context/dynamic-tool-lifecycle.js +1 -1
  26. package/dist/src/context/keys.d.ts +13 -1
  27. package/dist/src/context/keys.js +1 -1
  28. package/dist/src/discover/filesystem.d.ts +1 -1
  29. package/dist/src/discover/filesystem.js +1 -1
  30. package/dist/src/evals/cli/eval.js +2 -2
  31. package/dist/src/evals/runner/derive-run-facts.js +1 -1
  32. package/dist/src/execution/dispatch-runtime-actions-step.d.ts +1 -5
  33. package/dist/src/execution/dispatch-runtime-actions-step.js +1 -1
  34. package/dist/src/execution/dispatch-turn-step.d.ts +5 -0
  35. package/dist/src/execution/dispatch-turn-step.js +1 -0
  36. package/dist/src/execution/durable-session-migrations/turn-workflow.d.ts +1 -0
  37. package/dist/src/execution/node-step.js +1 -1
  38. package/dist/src/execution/parked-delivery-wait.d.ts +1 -1
  39. package/dist/src/execution/parked-delivery-wait.js +1 -1
  40. package/dist/src/execution/remote-agent-dispatch.d.ts +2 -1
  41. package/dist/src/execution/remote-agent-dispatch.js +1 -1
  42. package/dist/src/execution/route-child-delivery.d.ts +3 -4
  43. package/dist/src/execution/route-child-delivery.js +1 -1
  44. package/dist/src/execution/route-proxied-deliver-step.d.ts +34 -0
  45. package/dist/src/execution/route-proxied-deliver-step.js +1 -0
  46. package/dist/src/execution/runtime-context.js +1 -1
  47. package/dist/src/execution/session-command-inbox.d.ts +2 -2
  48. package/dist/src/execution/session-command-wire.js +1 -1
  49. package/dist/src/execution/settle-cancelled-turn-step.js +1 -1
  50. package/dist/src/execution/subagent-adapter.js +1 -1
  51. package/dist/src/execution/subagent-event-proxy-step.js +1 -1
  52. package/dist/src/execution/tool-auth.d.ts +9 -0
  53. package/dist/src/execution/tool-auth.js +1 -1
  54. package/dist/src/execution/turn-control-receiver.js +1 -1
  55. package/dist/src/execution/turn-dispatch.js +1 -1
  56. package/dist/src/execution/turn-workflow.js +1 -1
  57. package/dist/src/execution/workflow-entry.js +1 -1
  58. package/dist/src/execution/workflow-runtime.js +1 -1
  59. package/dist/src/execution/workflow-steps.d.ts +1 -27
  60. package/dist/src/execution/workflow-steps.js +1 -1
  61. package/dist/src/harness/ai-sdk-hook-bridge.js +1 -1
  62. package/dist/src/harness/ai-sdk-telemetry.d.ts +19 -0
  63. package/dist/src/harness/ai-sdk-telemetry.js +1 -0
  64. package/dist/src/harness/approval-candidates.d.ts +109 -0
  65. package/dist/src/harness/approval-candidates.js +1 -0
  66. package/dist/src/harness/approval-delivery-coordinator.d.ts +39 -0
  67. package/dist/src/harness/approval-delivery-coordinator.js +1 -0
  68. package/dist/src/harness/authorization.d.ts +1 -0
  69. package/dist/src/harness/authorization.js +1 -1
  70. package/dist/src/harness/channel-delivery-instrumentation.d.ts +25 -0
  71. package/dist/src/harness/channel-delivery-instrumentation.js +1 -0
  72. package/dist/src/harness/execute-tool.d.ts +1 -0
  73. package/dist/src/harness/hitl/approval-input-requests.js +1 -1
  74. package/dist/src/harness/hitl/pending-input-resolution.d.ts +3 -0
  75. package/dist/src/harness/hitl/pending-input-resolution.js +1 -1
  76. package/dist/src/harness/hitl/question-input-requests.js +1 -1
  77. package/dist/src/harness/hitl/session-limit-input-requests.js +1 -1
  78. package/dist/src/harness/input-extraction.js +1 -1
  79. package/dist/src/harness/input-request-resolution.d.ts +22 -0
  80. package/dist/src/harness/input-request-resolution.js +1 -0
  81. package/dist/src/harness/input-requests.d.ts +1 -0
  82. package/dist/src/harness/input-requests.js +1 -1
  83. package/dist/src/harness/instrumentation-config.d.ts +9 -4
  84. package/dist/src/harness/instrumentation-config.js +1 -1
  85. package/dist/src/harness/instrumentation-content.d.ts +5 -0
  86. package/dist/src/harness/instrumentation-content.js +1 -0
  87. package/dist/src/harness/instrumentation-dispatch.d.ts +2 -0
  88. package/dist/src/harness/instrumentation-dispatch.js +1 -0
  89. package/dist/src/harness/instrumentation-lifecycle.d.ts +388 -65
  90. package/dist/src/harness/instrumentation-lifecycle.js +1 -1
  91. package/dist/src/harness/instrumentation-native-events.d.ts +10 -1
  92. package/dist/src/harness/instrumentation-native-events.js +1 -1
  93. package/dist/src/harness/instrumentation-providers.d.ts +50 -0
  94. package/dist/src/harness/instrumentation-providers.js +1 -0
  95. package/dist/src/harness/instrumentation-runtime.d.ts +3 -0
  96. package/dist/src/harness/instrumentation-runtime.js +1 -1
  97. package/dist/src/harness/instrumentation-setup-context.d.ts +12 -0
  98. package/dist/src/harness/instrumentation-setup-context.js +1 -0
  99. package/dist/src/harness/instrumentation-state.d.ts +59 -0
  100. package/dist/src/harness/instrumentation-state.js +1 -0
  101. package/dist/src/harness/messages.d.ts +2 -1
  102. package/dist/src/harness/messages.js +1 -1
  103. package/dist/src/harness/pending-input-batches.d.ts +2 -0
  104. package/dist/src/harness/pending-input-batches.js +1 -1
  105. package/dist/src/harness/runtime-action-settlement-state.d.ts +3 -0
  106. package/dist/src/harness/runtime-action-settlement-state.js +1 -0
  107. package/dist/src/harness/runtime-actions.js +1 -1
  108. package/dist/src/harness/stale-input-responses.js +1 -1
  109. package/dist/src/harness/tool-call-action.d.ts +9 -0
  110. package/dist/src/harness/tool-call-action.js +1 -0
  111. package/dist/src/harness/tool-loop.js +2 -2
  112. package/dist/src/harness/tools.js +1 -1
  113. package/dist/src/harness/types.d.ts +15 -1
  114. package/dist/src/internal/application/compiled-artifacts.d.ts +13 -4
  115. package/dist/src/internal/application/compiled-artifacts.js +5 -4
  116. package/dist/src/internal/application/dev-environment.d.ts +12 -0
  117. package/dist/src/internal/application/dev-environment.js +1 -1
  118. package/dist/src/internal/application/package.js +1 -1
  119. package/dist/src/internal/authored-definition/approval.d.ts +3 -0
  120. package/dist/src/internal/authored-definition/approval.js +1 -0
  121. package/dist/src/internal/authored-definition/connection.js +1 -1
  122. package/dist/src/internal/authored-definition/core.js +1 -1
  123. package/dist/src/internal/authored-definition/schema-backed.js +1 -1
  124. package/dist/src/internal/instrumentation-layout.d.ts +28 -0
  125. package/dist/src/internal/instrumentation-layout.js +1 -0
  126. package/dist/src/internal/materialized-authored-modules.d.ts +13 -2
  127. package/dist/src/internal/materialized-authored-modules.js +1 -1
  128. package/dist/src/internal/nitro/host/create-application-nitro.js +1 -1
  129. package/dist/src/internal/nitro/host/dev-host-fingerprint.js +1 -1
  130. package/dist/src/internal/nitro/host/local-tracing-runtime-plugin.d.ts +5 -1
  131. package/dist/src/internal/nitro/host/local-tracing-runtime-plugin.js +1 -1
  132. package/dist/src/internal/nitro/routes/channel-dispatch.js +1 -1
  133. package/dist/src/internal/nitro/routes/channel-request-instrumentation.d.ts +2 -3
  134. package/dist/src/internal/nitro/routes/channel-request-instrumentation.js +1 -1
  135. package/dist/src/packages/eve-catalog/src/index.js +1 -1
  136. package/dist/src/protocol/message.d.ts +36 -1
  137. package/dist/src/protocol/message.js +1 -1
  138. package/dist/src/protocol/traceparent.d.ts +10 -0
  139. package/dist/src/protocol/traceparent.js +1 -0
  140. package/dist/src/public/channels/eve.js +1 -1
  141. package/dist/src/public/channels/github/defaults.d.ts +1 -0
  142. package/dist/src/public/channels/github/defaults.js +5 -2
  143. package/dist/src/public/channels/github/dispatch.js +1 -1
  144. package/dist/src/public/channels/github/githubChannel.d.ts +3 -3
  145. package/dist/src/public/channels/github/githubChannel.js +1 -1
  146. package/dist/src/public/channels/github/inbound.d.ts +0 -3
  147. package/dist/src/public/channels/github/inbound.js +1 -1
  148. package/dist/src/public/channels/slack/defaults.js +3 -3
  149. package/dist/src/public/channels/slack/interactions.js +1 -1
  150. package/dist/src/public/channels/slack/slackChannel.d.ts +11 -3
  151. package/dist/src/public/channels/slack/slackChannel.js +1 -1
  152. package/dist/src/public/definitions/approval.d.ts +57 -16
  153. package/dist/src/public/definitions/approval.js +1 -1
  154. package/dist/src/public/definitions/channel.d.ts +2 -2
  155. package/dist/src/public/definitions/channel.js +1 -1
  156. package/dist/src/public/definitions/hook.d.ts +4 -2
  157. package/dist/src/public/instrumentation/index.d.ts +32 -17
  158. package/dist/src/public/instrumentation/index.js +1 -1
  159. package/dist/src/public/instrumentation/otel.d.ts +31 -0
  160. package/dist/src/public/instrumentation/otel.js +1 -0
  161. package/dist/src/public/instrumentation/provider.d.ts +117 -0
  162. package/dist/src/public/instrumentation/provider.js +1 -0
  163. package/dist/src/public/tools/approval/approval-helpers.d.ts +4 -4
  164. package/dist/src/public/tools/index.d.ts +1 -1
  165. package/dist/src/runtime/actions/results.d.ts +3 -3
  166. package/dist/src/runtime/attributes/emit.js +1 -1
  167. package/dist/src/runtime/connections/principal.d.ts +3 -0
  168. package/dist/src/runtime/connections/principal.js +1 -1
  169. package/dist/src/runtime/connections/scoped-authorization.d.ts +3 -5
  170. package/dist/src/runtime/connections/scoped-authorization.js +1 -1
  171. package/dist/src/runtime/connections/types.d.ts +5 -0
  172. package/dist/src/runtime/resolve-agent.js +1 -1
  173. package/dist/src/runtime/resolve-tool.js +1 -1
  174. package/dist/src/setup/index.d.ts +1 -0
  175. package/dist/src/setup/index.js +1 -1
  176. package/dist/src/setup/scaffold/create/project.js +1 -1
  177. package/dist/src/setup/scaffold/version-tokens.js +1 -1
  178. package/dist/src/setup/verified-remote-agent.d.ts +30 -0
  179. package/dist/src/setup/verified-remote-agent.js +1 -0
  180. package/dist/src/shared/agent-definition.d.ts +9 -0
  181. package/dist/src/shared/channel-definition.d.ts +3 -1
  182. package/dist/src/svelte/index.js +1 -1
  183. package/dist/src/svelte/use-eve-agent.js +1 -1
  184. package/dist/src/tracing/agent-action-instrumentation.d.ts +31 -0
  185. package/dist/src/tracing/agent-action-instrumentation.js +1 -0
  186. package/dist/src/tracing/agent-approval-instrumentation.d.ts +13 -0
  187. package/dist/src/tracing/agent-approval-instrumentation.js +1 -0
  188. package/dist/src/tracing/agent-channel-delivery-instrumentation.d.ts +13 -0
  189. package/dist/src/tracing/agent-channel-delivery-instrumentation.js +1 -0
  190. package/dist/src/tracing/agent-otel-content.d.ts +6 -0
  191. package/dist/src/tracing/agent-otel-content.js +2 -2
  192. package/dist/src/tracing/agent-otel-provider.d.ts +7 -7
  193. package/dist/src/tracing/agent-otel-provider.js +2 -2
  194. package/dist/src/tracing/agent-otel-usage.d.ts +4 -0
  195. package/dist/src/tracing/agent-otel-usage.js +1 -0
  196. package/dist/src/tracing/agent-span-id-generator.d.ts +2 -0
  197. package/dist/src/tracing/agent-span-id-generator.js +1 -1
  198. package/dist/src/tracing/agent-tool-instrumentation.d.ts +28 -0
  199. package/dist/src/tracing/agent-tool-instrumentation.js +1 -0
  200. package/dist/src/tracing/agent-trace-context-store.d.ts +8 -1
  201. package/dist/src/tracing/agent-trace-context-store.js +1 -1
  202. package/dist/src/tracing/agent-trace-span-processor.d.ts +0 -1
  203. package/dist/src/tracing/agent-trace-span-processor.js +1 -1
  204. package/dist/src/tracing/agent-trace-state.d.ts +33 -3
  205. package/dist/src/tracing/agent-trace-state.js +1 -1
  206. package/dist/src/tracing/batch-span-processor.d.ts +20 -0
  207. package/dist/src/tracing/batch-span-processor.js +1 -0
  208. package/dist/src/tracing/content-attributes.d.ts +28 -0
  209. package/dist/src/tracing/content-attributes.js +1 -0
  210. package/dist/src/tracing/content-span-processor.d.ts +19 -0
  211. package/dist/src/tracing/content-span-processor.js +1 -0
  212. package/dist/src/tracing/install-instrumentation-runtime.d.ts +19 -0
  213. package/dist/src/tracing/install-instrumentation-runtime.js +1 -0
  214. package/dist/src/tracing/local-instrumentation-runtime.js +1 -1
  215. package/dist/src/tracing/local-traces.d.ts +56 -0
  216. package/dist/src/tracing/local-traces.js +1 -0
  217. package/dist/src/tracing/otel-declaration.d.ts +150 -0
  218. package/dist/src/tracing/otel-declaration.js +1 -0
  219. package/dist/src/tracing/otel-registration.d.ts +21 -0
  220. package/dist/src/tracing/otel-registration.js +1 -0
  221. package/dist/src/tracing/vercel-runtime-span-exporter.d.ts +5 -0
  222. package/dist/src/tracing/vercel-runtime-span-exporter.js +1 -0
  223. package/dist/src/vue/index.js +1 -1
  224. package/dist/src/vue/use-eve-agent.js +1 -1
  225. package/docs/guides/instrumentation.md +22 -0
  226. package/package.json +7 -1
  227. package/dist/src/harness/otel-integration.d.ts +0 -12
  228. package/dist/src/harness/otel-integration.js +0 -1
@@ -1,4 +1,4 @@
1
- import{pinnedNodeEngineMajor}from"../../node-engine.js";import{SUPPORTED_AUTHORED_MODULE_FILE_EXTENSIONS}from"../update/module-files.js";import{pathExists,writeTextFile}from"../files.js";import{blockingCreateInPlaceEntries}from"../create-in-place.js";import{resolveVersionToken}from"../version-tokens.js";import{applyPackageManagerWorkspaceConfiguration,isPackageManagerWorkspaceMember,patchWorkspaceRootPackageJson}from"../workspace-root.js";import{WEB_APP_TEMPLATE_FILES}from"./web-template.js";import{mkdir,readdir,stat}from"node:fs/promises";import{basename,join,resolve}from"node:path";const CURRENT_DIRECTORY_PROJECT_NAME=`.`,DEFAULT_AI_PACKAGE_VERSION=`^7.0.58`,DEFAULT_CONNECT_PACKAGE_VERSION=`0.4.3`,DEFAULT_ZOD_PACKAGE_VERSION=`4.4.3`,DEFAULT_EVE_PACKAGE_CONTRACT={version:`0.33.2`,nodeEngine:`>=24`};function resolveEvePackageContract(e=DEFAULT_EVE_PACKAGE_CONTRACT){return{version:resolveVersionToken(`evePackage.version`,e.version),nodeEngine:resolveVersionToken(`evePackage.nodeEngine`,e.nodeEngine)}}function modelProviderSlug(e){let t=(e.split(`/`)[0]??``).replaceAll(/[^A-Za-z0-9._-]/gu,``);return t.length>0?t:`anthropic`}function byokProviderEnvVar(e){let t=modelProviderSlug(e).toUpperCase().replaceAll(/[^A-Z0-9]/gu,`_`);return`${/^[0-9]/.test(t)?`_`:``}${t}_API_KEY`}function agentTemplateFiles(e,t){return{"agent/agent.ts":BASE_AGENT_TEMPLATE.replaceAll(`__EVE_INIT_MODEL__`,e).replaceAll(`__EVE_INIT_REASONING__`,reasoningTemplateLine(t)),"agent/channels/eve.ts":WEB_APP_TEMPLATE_FILES[`agent/channels/eve.ts`],"agent/instructions.md":AGENT_INSTRUCTIONS_TEMPLATE}}function reasoningTemplateLine(e){return e===void 0||e===`provider-default`?``:` reasoning: "${e}",\n`}function renderTemplate(e,t){return e.replaceAll(`__EVE_INIT_APP_NAME__`,t.appName).replaceAll(`__EVE_INIT_MODEL__`,t.model).replaceAll(`__EVE_INIT_REASONING__`,reasoningTemplateLine(t.reasoning)).replaceAll(`__EVE_INIT_BYOK_PROVIDER__`,modelProviderSlug(t.model)).replaceAll(`__EVE_INIT_BYOK_ENV_VAR__`,byokProviderEnvVar(t.model)).replaceAll(`__EVE_INIT_PACKAGE_VERSION__`,formatEveDependencySpecifier(t.eveVersion)).replaceAll(`__EVE_INIT_AI_SDK_VERSION__`,t.aiPackageVersion).replaceAll(`__EVE_INIT_CONNECT_VERSION__`,t.connectPackageVersion).replaceAll(`__EVE_INIT_ZOD_VERSION__`,t.zodPackageVersion).replaceAll(`__EVE_INIT_TYPESCRIPT_VERSION__`,t.typescriptPackageVersion).replaceAll(`__EVE_INIT_TYPES_NODE_VERSION__`,t.nodeTypesVersion).replaceAll(`__EVE_INIT_NODE_ENGINE__`,t.nodeEngine)}function formatEveDependencySpecifier(e){return/^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z-.]+)?$/.test(e)?`^${e}`:e}const BASE_AGENT_TEMPLATE=`import { defineAgent } from "eve";
1
+ import{pinnedNodeEngineMajor}from"../../node-engine.js";import{SUPPORTED_AUTHORED_MODULE_FILE_EXTENSIONS}from"../update/module-files.js";import{pathExists,writeTextFile}from"../files.js";import{blockingCreateInPlaceEntries}from"../create-in-place.js";import{resolveVersionToken}from"../version-tokens.js";import{applyPackageManagerWorkspaceConfiguration,isPackageManagerWorkspaceMember,patchWorkspaceRootPackageJson}from"../workspace-root.js";import{WEB_APP_TEMPLATE_FILES}from"./web-template.js";import{mkdir,readdir,stat}from"node:fs/promises";import{basename,join,resolve}from"node:path";const CURRENT_DIRECTORY_PROJECT_NAME=`.`,DEFAULT_AI_PACKAGE_VERSION=`^7.0.58`,DEFAULT_CONNECT_PACKAGE_VERSION=`0.4.3`,DEFAULT_ZOD_PACKAGE_VERSION=`4.4.3`,DEFAULT_EVE_PACKAGE_CONTRACT={version:`0.34.0`,nodeEngine:`>=24`};function resolveEvePackageContract(e=DEFAULT_EVE_PACKAGE_CONTRACT){return{version:resolveVersionToken(`evePackage.version`,e.version),nodeEngine:resolveVersionToken(`evePackage.nodeEngine`,e.nodeEngine)}}function modelProviderSlug(e){let t=(e.split(`/`)[0]??``).replaceAll(/[^A-Za-z0-9._-]/gu,``);return t.length>0?t:`anthropic`}function byokProviderEnvVar(e){let t=modelProviderSlug(e).toUpperCase().replaceAll(/[^A-Z0-9]/gu,`_`);return`${/^[0-9]/.test(t)?`_`:``}${t}_API_KEY`}function agentTemplateFiles(e,t){return{"agent/agent.ts":BASE_AGENT_TEMPLATE.replaceAll(`__EVE_INIT_MODEL__`,e).replaceAll(`__EVE_INIT_REASONING__`,reasoningTemplateLine(t)),"agent/channels/eve.ts":WEB_APP_TEMPLATE_FILES[`agent/channels/eve.ts`],"agent/instructions.md":AGENT_INSTRUCTIONS_TEMPLATE}}function reasoningTemplateLine(e){return e===void 0||e===`provider-default`?``:` reasoning: "${e}",\n`}function renderTemplate(e,t){return e.replaceAll(`__EVE_INIT_APP_NAME__`,t.appName).replaceAll(`__EVE_INIT_MODEL__`,t.model).replaceAll(`__EVE_INIT_REASONING__`,reasoningTemplateLine(t.reasoning)).replaceAll(`__EVE_INIT_BYOK_PROVIDER__`,modelProviderSlug(t.model)).replaceAll(`__EVE_INIT_BYOK_ENV_VAR__`,byokProviderEnvVar(t.model)).replaceAll(`__EVE_INIT_PACKAGE_VERSION__`,formatEveDependencySpecifier(t.eveVersion)).replaceAll(`__EVE_INIT_AI_SDK_VERSION__`,t.aiPackageVersion).replaceAll(`__EVE_INIT_CONNECT_VERSION__`,t.connectPackageVersion).replaceAll(`__EVE_INIT_ZOD_VERSION__`,t.zodPackageVersion).replaceAll(`__EVE_INIT_TYPESCRIPT_VERSION__`,t.typescriptPackageVersion).replaceAll(`__EVE_INIT_TYPES_NODE_VERSION__`,t.nodeTypesVersion).replaceAll(`__EVE_INIT_NODE_ENGINE__`,t.nodeEngine)}function formatEveDependencySpecifier(e){return/^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z-.]+)?$/.test(e)?`^${e}`:e}const BASE_AGENT_TEMPLATE=`import { defineAgent } from "eve";
2
2
 
3
3
  export default defineAgent({
4
4
  model: "__EVE_INIT_MODEL__",
@@ -1 +1 @@
1
- import{existsSync,readFileSync,realpathSync}from"node:fs";import{dirname,join}from"node:path";import{fileURLToPath}from"node:url";function versionToken(e){return`__${e}_VERSION__`}function bareToken(e){return`__${e}__`}const NODE_ENGINE_TOKEN=bareToken(`NODE_ENGINE`),TOKEN_SOURCES={[versionToken(`EVE_PACKAGE`)]:{kind:`eve-version`},[NODE_ENGINE_TOKEN]:{kind:`eve-node-engine`},[versionToken(`AI_SDK`)]:{kind:`catalog`,packageName:`ai`},[versionToken(`VERCEL_CONNECT`)]:{kind:`catalog`,packageName:`@vercel/connect`},[versionToken(`NEXT`)]:{kind:`catalog`,packageName:`next`},[versionToken(`REACT`)]:{kind:`catalog`,packageName:`react`},[versionToken(`REACT_DOM`)]:{kind:`catalog`,packageName:`react-dom`},[versionToken(`STREAMDOWN`)]:{kind:`catalog`,packageName:`streamdown`},[versionToken(`ZOD`)]:{kind:`catalog`,packageName:`zod`},[versionToken(`TYPESCRIPT`)]:{kind:`catalog`,packageName:`typescript`},[versionToken(`TYPES_REACT`)]:{kind:`catalog`,packageName:`@types/react`},[versionToken(`TYPES_REACT_DOM`)]:{kind:`catalog`,packageName:`@types/react-dom`}},resolvedTokens=new Map;function findEvePackageRoot(){let o=dirname(realpathSync(fileURLToPath(import.meta.url)));for(;;){let n=join(o,`package.json`);if(existsSync(n)&&JSON.parse(readFileSync(n,`utf8`)).name===`eve`)return o;let a=dirname(o);if(a===o)return;o=a}}function findWorkspaceManifest(t){let n=t;for(;;){let t=join(n,`pnpm-workspace.yaml`);if(existsSync(t))return t;let a=dirname(n);if(a===n)return;n=a}}function readCatalogVersion(e,n){let r=readFileSync(e,`utf8`).split(/\r?\n/),i=!1;for(let e of r){if(/^catalog:\s*$/.test(e)){i=!0;continue}if(!i)continue;if(/^\S/.test(e))break;let t=e.match(/^\s+(?:"([^"]+)"|([\w@/.-]+)):\s*"([^"]+)"/);if(t&&(t[1]??t[2])===n)return t[3]}}function resolveTokenFromDevTree(n){let r=TOKEN_SOURCES[n];if(r!==void 0)try{let n=findEvePackageRoot();if(n===void 0||!existsSync(join(n,`scripts/stamp-version-tokens.mjs`)))return;if(r.kind===`eve-version`){let e=JSON.parse(readFileSync(join(n,`package.json`),`utf8`));return typeof e.version==`string`?e.version:void 0}if(r.kind===`eve-node-engine`){let e=JSON.parse(readFileSync(join(n,`package.json`),`utf8`)).engines?.node;return typeof e==`string`?e:void 0}let a=findWorkspaceManifest(n);return a===void 0?void 0:readCatalogVersion(a,r.packageName)}catch{return}}function resolveVersionToken(e,t){if(!t.startsWith(`__`))return t;let n=resolvedTokens.get(t);if(n!==void 0)return n;let r=resolveTokenFromDevTree(t);if(r===void 0)throw Error(`Scaffold received unstamped version token (${e}=${t}). Build eve before using its dist entrypoint.`);return resolvedTokens.set(t,r),r}export{resolveVersionToken};
1
+ import{existsSync,readFileSync,realpathSync}from"node:fs";import{dirname,join}from"node:path";import{fileURLToPath}from"node:url";function versionToken(e){return`__${e}_VERSION__`}function bareToken(e){return`__${e}__`}const NODE_ENGINE_TOKEN=bareToken(`NODE_ENGINE`),TOKEN_SOURCES={[versionToken(`EVE_PACKAGE`)]:{kind:`eve-version`},[versionToken(`EVE_PACKAGE_DEPENDENCY`)]:{kind:`eve-version`},[NODE_ENGINE_TOKEN]:{kind:`eve-node-engine`},[versionToken(`AI_SDK`)]:{kind:`catalog`,packageName:`ai`},[versionToken(`VERCEL_CONNECT`)]:{kind:`catalog`,packageName:`@vercel/connect`},[versionToken(`NEXT`)]:{kind:`catalog`,packageName:`next`},[versionToken(`REACT`)]:{kind:`catalog`,packageName:`react`},[versionToken(`REACT_DOM`)]:{kind:`catalog`,packageName:`react-dom`},[versionToken(`STREAMDOWN`)]:{kind:`catalog`,packageName:`streamdown`},[versionToken(`ZOD`)]:{kind:`catalog`,packageName:`zod`},[versionToken(`TYPESCRIPT`)]:{kind:`catalog`,packageName:`typescript`},[versionToken(`TYPES_REACT`)]:{kind:`catalog`,packageName:`@types/react`},[versionToken(`TYPES_REACT_DOM`)]:{kind:`catalog`,packageName:`@types/react-dom`}},resolvedTokens=new Map;function findEvePackageRoot(){let o=dirname(realpathSync(fileURLToPath(import.meta.url)));for(;;){let n=join(o,`package.json`);if(existsSync(n)&&JSON.parse(readFileSync(n,`utf8`)).name===`eve`)return o;let a=dirname(o);if(a===o)return;o=a}}function findWorkspaceManifest(t){let n=t;for(;;){let t=join(n,`pnpm-workspace.yaml`);if(existsSync(t))return t;let a=dirname(n);if(a===n)return;n=a}}function readCatalogVersion(e,n){let r=readFileSync(e,`utf8`).split(/\r?\n/),i=!1;for(let e of r){if(/^catalog:\s*$/.test(e)){i=!0;continue}if(!i)continue;if(/^\S/.test(e))break;let t=e.match(/^\s+(?:"([^"]+)"|([\w@/.-]+)):\s*"([^"]+)"/);if(t&&(t[1]??t[2])===n)return t[3]}}function resolveTokenFromDevTree(n){let r=TOKEN_SOURCES[n];if(r!==void 0)try{let n=findEvePackageRoot();if(n===void 0||!existsSync(join(n,`scripts/stamp-version-tokens.mjs`)))return;if(r.kind===`eve-version`){let e=JSON.parse(readFileSync(join(n,`package.json`),`utf8`));return typeof e.version==`string`?e.version:void 0}if(r.kind===`eve-node-engine`){let e=JSON.parse(readFileSync(join(n,`package.json`),`utf8`)).engines?.node;return typeof e==`string`?e:void 0}let a=findWorkspaceManifest(n);return a===void 0?void 0:readCatalogVersion(a,r.packageName)}catch{return}}function resolveVersionToken(e,t){if(!t.startsWith(`__`))return t;let n=resolvedTokens.get(t);if(n!==void 0)return n;let r=resolveTokenFromDevTree(t);if(r===void 0)throw Error(`Scaffold received unstamped version token (${e}=${t}). Build eve before using its dist entrypoint.`);return resolvedTokens.set(t,r),r}export{resolveVersionToken};
@@ -0,0 +1,30 @@
1
+ import { Client, type AgentInfoResult, type ClientOptions } from "#client/index.js";
2
+ import { type RemoteAuthFlow } from "#cli/dev/tui/remote-auth.js";
3
+ import type { Prompter } from "#setup/prompter.js";
4
+ import { resolveVerifiedRemoteDevelopmentClient, type VerifiedRemoteDevelopmentClient } from "#setup/verified-remote-client.js";
5
+ /** Result of inspecting an authenticated remote eve agent. */
6
+ export interface VerifiedRemoteAgentInspection {
7
+ readonly info: AgentInfoResult;
8
+ /** Verified Vercel scope to retain when reconnecting to the same deployment. */
9
+ readonly vercelScope?: string;
10
+ }
11
+ /** @internal Dependencies for testing verified remote inspection. */
12
+ export interface InspectVerifiedRemoteAgentDeps {
13
+ readonly createClient: (options: ClientOptions) => Pick<Client, "info">;
14
+ readonly resolveVerifiedRemoteDevelopmentClient: (input: Parameters<typeof resolveVerifiedRemoteDevelopmentClient>[0]) => Promise<VerifiedRemoteDevelopmentClient>;
15
+ readonly runRemoteAuthFlow: RemoteAuthFlow;
16
+ }
17
+ /**
18
+ * Inspects a remote eve agent using the same exact-origin credential boundary
19
+ * as remote development clients. When a verified Vercel target needs login or
20
+ * Trusted Sources configuration, an optional prompter completes that flow
21
+ * before inspection is retried.
22
+ */
23
+ export declare function inspectVerifiedRemoteAgent(input: {
24
+ readonly serverUrl: string;
25
+ readonly workspaceRoot: string;
26
+ readonly prompter?: Prompter;
27
+ readonly signal?: AbortSignal;
28
+ /** @internal Test seam. */
29
+ readonly deps?: Partial<InspectVerifiedRemoteAgentDeps>;
30
+ }): Promise<VerifiedRemoteAgentInspection>;
@@ -0,0 +1 @@
1
+ import{Client,ClientError}from"#client/index.js";import{WizardCancelledError}from"#setup/step.js";import{resolveVerifiedRemoteDevelopmentClient}from"#setup/verified-remote-client.js";import{runRemoteAuthFlow}from"#cli/dev/tui/remote-auth.js";const defaultDeps={createClient:t=>new Client(t),resolveVerifiedRemoteDevelopmentClient,runRemoteAuthFlow};async function inspectVerifiedRemoteAgent(e){let t={...defaultDeps,...e.deps},n=await t.resolveVerifiedRemoteDevelopmentClient({serverUrl:e.serverUrl,signal:e.signal,workspaceRoot:e.workspaceRoot});try{return inspection(await t.createClient(n.options).info(),verifiedScope(n))}catch(t){if(e.prompter===void 0||!isAuthenticationFailure(t)||!canAuthenticateInteractively(t,n))throw t}let r=await t.runRemoteAuthFlow({configureTrustedSources:!0,prompter:e.prompter,serverUrl:e.serverUrl,signal:e.signal,workspaceRoot:e.workspaceRoot});if(r.kind===`cancelled`)throw new WizardCancelledError;if(r.kind===`failed`)throw Error(r.message);let i={...n.options,auth:{vercelOidc:{token:r.resolveToken}},host:e.serverUrl,redirect:`manual`};return inspection(await t.createClient(i).info(),r.target.deployment.ownerId)}function inspection(e,t){return t===void 0?{info:e}:{info:e,vercelScope:t}}function verifiedScope(e){let t=e.deploymentResolution;return t?.kind===`resolved`?t.target.deployment.ownerId:void 0}function isAuthenticationFailure(e){return e instanceof ClientError&&(e.status>=300&&e.status<400||e.status===401||e.status===403)}function canAuthenticateInteractively(e,t){return e.status>=300&&e.status<400&&(e.headers.location??``).includes(`vercel.com/sso-api`)?!0:t.deploymentResolution?.kind===`resolved`||t.deploymentResolution?.kind===`forbidden`}export{inspectVerifiedRemoteAgent};
@@ -164,6 +164,15 @@ export interface AgentLimitsDefinition {
164
164
  * These options are unstable and may change or be removed in any release.
165
165
  */
166
166
  export interface AgentExperimentalDefinition {
167
+ /**
168
+ * Reads instrumentation from an `instrumentation/` directory of providers
169
+ * rather than a single `agent/instrumentation.ts` config object.
170
+ *
171
+ * The two layouts are mutually exclusive: with this on, an
172
+ * `agent/instrumentation.ts` is a build error, and with it off, an
173
+ * `instrumentation/` directory is.
174
+ */
175
+ readonly instrumentationProviders?: boolean;
167
176
  /**
168
177
  * Keeps this agent's delegated subagent sessions alive after they answer.
169
178
  * The model can pass `agentId` to a subagent tool to continue a previous
@@ -3,7 +3,8 @@ import type { UserContent } from "ai";
3
3
  import type { ChannelReceiveContext } from "#channel/channel-operations.js";
4
4
  import type { RouteDefinition } from "#channel/routes.js";
5
5
  import type { Session, SessionHandle } from "#channel/session.js";
6
- import type { SessionAuthContext, TurnPolicy } from "#channel/types.js";
6
+ import type { DeliverPayload, SessionAuthContext, TurnPolicy } from "#channel/types.js";
7
+ import type { StepInput } from "#harness/types.js";
7
8
  /**
8
9
  * Enriched return shape from a channel's {@link ChannelAdapter.fetchFile}
9
10
  * function. Return a bare {@link Buffer} when only bytes are known, or
@@ -42,6 +43,7 @@ export interface GenericReceiveInput<TReceiveTarget = Record<string, unknown>> {
42
43
  export interface GenericChannelDefinition<TEvents, TState = undefined, TCtx = void, TReceiveTarget = Record<string, unknown>, TMetadata extends Record<string, unknown> = Record<string, unknown>> {
43
44
  /** Policy used by message sends that do not provide an explicit override. */
44
45
  readonly turnPolicy?: TurnPolicy;
46
+ deliver?(payload: DeliverPayload, ctx: TCtx): StepInput | void | Promise<StepInput | void>;
45
47
  readonly state?: TState;
46
48
  /**
47
49
  * CORS policy for this channel's HTTP routes. `true` enables H3/Nitro's
@@ -1,3 +1,3 @@
1
- import { n as defaultMessageReducer, t as useEveAgent } from "../chunks/use-eve-agent-B-Hky2f4.js";
1
+ import { n as defaultMessageReducer, t as useEveAgent } from "../chunks/use-eve-agent-BNdcle_M.js";
2
2
 
3
3
  export { defaultMessageReducer, useEveAgent };
@@ -1,3 +1,3 @@
1
- import { t as useEveAgent } from "../chunks/use-eve-agent-B-Hky2f4.js";
1
+ import { t as useEveAgent } from "../chunks/use-eve-agent-BNdcle_M.js";
2
2
 
3
3
  export { useEveAgent };
@@ -0,0 +1,31 @@
1
+ import { type Context, type SpanContext, type Tracer } from "#compiled/@opentelemetry/api/index.js";
2
+ import type { InstrumentationActionStartedEvent, InstrumentationAttemptScope, InstrumentationProviderDefinition } from "#harness/instrumentation-lifecycle.js";
3
+ import type { AgentSpanIdGenerator } from "#tracing/agent-span-id-generator.js";
4
+ import type { AgentTraceStateStore } from "#tracing/agent-trace-state.js";
5
+ export interface AgentActionInstrumentation {
6
+ readonly events: Pick<NonNullable<InstrumentationProviderDefinition["events"]>, "action.completed" | "action.failed" | "action.started">;
7
+ deleteForSession(sessionId: string): void | PromiseLike<void>;
8
+ deleteForTurn(sessionId: string, turnId: string): void | PromiseLike<void>;
9
+ failForAttempt(scope: InstrumentationAttemptScope, error: unknown): Promise<void>;
10
+ contextFor(sessionId: string, turnId: string, callId: string): Promise<AgentActionContext | undefined>;
11
+ }
12
+ export interface AgentActionContext {
13
+ readonly context: Context;
14
+ readonly spanContext: SpanContext;
15
+ }
16
+ /** Builds durable `agent.action` spans around eve's runtime dispatch boundary. */
17
+ export declare function createAgentActionInstrumentation(input: {
18
+ readonly frameworkVersion: string;
19
+ readonly idGenerator: AgentSpanIdGenerator;
20
+ readonly recordInputs: boolean;
21
+ readonly recordOutputs: boolean;
22
+ readonly resolveParent: (event: InstrumentationActionStartedEvent) => {
23
+ readonly context: Context;
24
+ readonly spanContext: SpanContext;
25
+ } | undefined | PromiseLike<{
26
+ readonly context: Context;
27
+ readonly spanContext: SpanContext;
28
+ } | undefined>;
29
+ readonly stateStore: AgentTraceStateStore;
30
+ readonly tracer: Tracer;
31
+ }): AgentActionInstrumentation;
@@ -0,0 +1 @@
1
+ import{ROOT_CONTEXT,SpanStatusCode,trace}from"#compiled/@opentelemetry/api/index.js";import{actionIdempotencyKey}from"#harness/instrumentation-lifecycle.js";import{contentAttribute}from"#tracing/agent-otel-content.js";import{setAgentUsage}from"#tracing/agent-otel-usage.js";function createAgentActionInstrumentation(e){let t=new Map,onStarted=async n=>{let r=await e.resolveParent(n);if(r===void 0)return;let a=await e.stateStore.getAction(n.idempotencyKey)??{attemptIndex:n.scope.attemptIndex,callId:n.callId,inputAttribute:e.recordInputs?contentAttribute(n.input,!1):void 0,kind:n.kind,name:n.name,parent:{spanId:r.spanContext.spanId,traceFlags:r.spanContext.traceFlags,traceId:r.spanContext.traceId},rootSessionId:n.scope.rootSessionId??n.scope.sessionId,sessionId:n.scope.sessionId,spanId:e.idGenerator.deriveSpanId(`action:${n.idempotencyKey}`),startTimeMs:Date.now(),stepIndex:n.scope.stepIndex,turnId:n.scope.turnId};await e.stateStore.setAction(n.idempotencyKey,a);let o=t.get(n.scope.attemptId)??new Set;o.add(n.idempotencyKey),t.set(n.scope.attemptId,o)},onTerminal=async t=>{let n=await e.stateStore.getAction(t.idempotencyKey);if(n!==void 0)try{let r=startSpan(n);if(r.setAttribute(`agent.action.outcome`,t.outcome),t.type===`action.failed`)t.errorCode!==void 0&&(r.setAttribute(`agent.action.error.code`,t.errorCode),r.setAttribute(`error.type`,t.errorCode)),recordError(r,t.error);else if(t.output.type===`error`)recordError(r,t.output.error);else if(t.usage!==void 0&&setAgentUsage(r,t.usage),e.recordOutputs){let e=contentAttribute(t.output.output,!1);e!==void 0&&r.setAttribute(`gen_ai.tool.call.result`,e)}r.end(t.acceptedAtMs)}finally{await e.stateStore.deleteAction(t.idempotencyKey),forget(t.idempotencyKey)}},startSpan=t=>{let n=e.idGenerator.withSpanId(t.spanId,()=>e.tracer.startSpan(`agent.action`,{attributes:{"agent.action.call_id":t.callId,"agent.action.kind":t.kind,"agent.action.name":t.name,"agent.framework.name":`eve`,"agent.framework.version":e.frameworkVersion,"agent.root.session.id":t.rootSessionId,"agent.session.id":t.sessionId,"agent.step.attempt":t.attemptIndex,"agent.step.index":t.stepIndex,"agent.turn.id":t.turnId},startTime:t.startTimeMs},contextFromActionState(t)));return t.inputAttribute!==void 0&&n.setAttribute(`gen_ai.tool.call.arguments`,t.inputAttribute),n};return{async contextFor(t,n,i){let a=actionIdempotencyKey(t,n,i),o=await e.stateStore.getAction(a);if(o!==void 0)return actionContext(o);let s=await e.stateStore.findAction(t,i);return s===void 0?void 0:actionContext(s)},deleteForSession:t=>e.stateStore.deleteActions(t),deleteForTurn:(t,n)=>e.stateStore.deleteActions(t,n),async failForAttempt(n,r){let i=t.get(n.attemptId);if(i!==void 0){t.delete(n.attemptId);for(let t of i){let n=await e.stateStore.getAction(t);if(n===void 0)continue;let i=startSpan(n);recordError(i,r),i.end(),await e.stateStore.deleteAction(t)}}},events:{"action.completed":onTerminal,"action.failed":onTerminal,"action.started":onStarted}};function forget(e){for(let[n,r]of t)r.delete(e),r.size===0&&t.delete(n)}}function actionContext(t){let r={isRemote:!1,spanId:t.spanId,traceFlags:t.parent.traceFlags,traceId:t.parent.traceId};return{context:trace.setSpan(ROOT_CONTEXT,trace.wrapSpanContext(r)),spanContext:r}}function contextFromActionState(t){return trace.setSpan(ROOT_CONTEXT,trace.wrapSpanContext({...t.parent,isRemote:!1}))}function recordError(e,n){n instanceof Error?(e.recordException(n),e.setStatus({code:SpanStatusCode.ERROR,message:n.message})):e.setStatus({code:SpanStatusCode.ERROR})}export{createAgentActionInstrumentation};
@@ -0,0 +1,13 @@
1
+ import { type Tracer } from "#compiled/@opentelemetry/api/index.js";
2
+ import type { InstrumentationProviderDefinition } from "#harness/instrumentation-lifecycle.js";
3
+ import type { AgentActionContext } from "#tracing/agent-action-instrumentation.js";
4
+ import type { AgentSpanIdGenerator } from "#tracing/agent-span-id-generator.js";
5
+ /** Builds durable approval wait spans under their originating runtime action. */
6
+ export declare function createAgentApprovalInstrumentation(input: {
7
+ readonly actionContextFor: (sessionId: string, turnId: string, callId: string) => Promise<AgentActionContext | undefined>;
8
+ readonly frameworkVersion: string;
9
+ readonly idGenerator: AgentSpanIdGenerator;
10
+ readonly recordInputs: boolean;
11
+ readonly recordOutputs: boolean;
12
+ readonly tracer: Tracer;
13
+ }): Pick<NonNullable<InstrumentationProviderDefinition["events"]>, "input.requested" | "input.resolved">;
@@ -0,0 +1 @@
1
+ import{ROOT_CONTEXT,SpanStatusCode,trace}from"#compiled/@opentelemetry/api/index.js";import{contentAttribute}from"#tracing/agent-otel-content.js";function createAgentApprovalInstrumentation(t){return{"input.requested":async(e,n)=>{if(e.kind!==`tool-approval`||readState(n.state.get())!==void 0)return;let i=await t.actionContextFor(e.scope.sessionId,e.scope.turnId,e.action.callId);if(i===void 0)return;let a={actionCallId:e.action.callId,actionName:e.action.name,attemptIndex:e.scope.attemptIndex,parent:{spanId:i.spanContext.spanId,traceFlags:i.spanContext.traceFlags,traceId:i.spanContext.traceId},requestId:e.requestId,rootSessionId:e.scope.rootSessionId??e.scope.sessionId,sessionId:e.scope.sessionId,startTimeMs:Date.now(),stepIndex:e.scope.stepIndex,turnId:e.scope.turnId},o=t.recordInputs?contentAttribute(e.request,!1):void 0;o!==void 0&&(a.requestAttribute=o),n.state.set(a)},"input.resolved":(i,a)=>{let o=readState(a.state.get());if(o===void 0)return;let s=t.idGenerator.withSpanId(t.idGenerator.deriveSpanId(`approval:${i.idempotencyKey}`),()=>t.tracer.startSpan(`agent.approval`,{attributes:{"agent.action.call_id":o.actionCallId,"agent.action.name":o.actionName,"agent.approval.kind":`tool-approval`,"agent.approval.outcome":i.outcome,"agent.approval.request_id":o.requestId,"agent.framework.name":`eve`,"agent.framework.version":t.frameworkVersion,"agent.root.session.id":o.rootSessionId,"agent.session.id":o.sessionId,"agent.step.attempt":o.attemptIndex,"agent.step.index":o.stepIndex,"agent.turn.id":o.turnId},startTime:o.startTimeMs},trace.setSpan(ROOT_CONTEXT,trace.wrapSpanContext({...o.parent,isRemote:!1}))));if(o.requestAttribute!==void 0&&s.setAttribute(`agent.approval.request`,o.requestAttribute),t.recordOutputs&&i.response!==void 0){let e=contentAttribute(i.response,!1);e!==void 0&&s.setAttribute(`agent.approval.response`,e)}i.outcome===`failed`&&recordError(s,i.error),s.end()}}}function readState(e){if(typeof e!=`object`||!e||Array.isArray(e))return;let t=e,n=t.parent;if(typeof n!=`object`||!n||Array.isArray(n))return;let r=n;if(typeof t.actionCallId!=`string`||typeof t.actionName!=`string`||typeof t.attemptIndex!=`number`||typeof r.spanId!=`string`||typeof r.traceFlags!=`number`||typeof r.traceId!=`string`||typeof t.requestId!=`string`||typeof t.rootSessionId!=`string`||typeof t.sessionId!=`string`||typeof t.startTimeMs!=`number`||typeof t.stepIndex!=`number`||typeof t.turnId!=`string`)return;let i=t.requestAttribute;if(!(i!==void 0&&typeof i!=`string`))return{actionCallId:t.actionCallId,actionName:t.actionName,attemptIndex:t.attemptIndex,parent:{isRemote:!1,spanId:r.spanId,traceFlags:r.traceFlags,traceId:r.traceId},requestAttribute:i,requestId:t.requestId,rootSessionId:t.rootSessionId,sessionId:t.sessionId,startTimeMs:t.startTimeMs,stepIndex:t.stepIndex,turnId:t.turnId}}function recordError(e,n){n instanceof Error?(e.recordException(n),e.setStatus({code:SpanStatusCode.ERROR,message:n.message})):e.setStatus({code:SpanStatusCode.ERROR})}export{createAgentApprovalInstrumentation};
@@ -0,0 +1,13 @@
1
+ import { type Tracer } from "#compiled/@opentelemetry/api/index.js";
2
+ import type { InstrumentationProviderDefinition, InstrumentationSessionStartedEvent } from "#harness/instrumentation-lifecycle.js";
3
+ import type { AgentSpanIdGenerator } from "#tracing/agent-span-id-generator.js";
4
+ import type { AgentSessionTraceState, AgentTraceStateStore } from "#tracing/agent-trace-state.js";
5
+ /** Builds durable channel delivery spans around the turn that consumes each request. */
6
+ export declare function createAgentChannelDeliveryInstrumentation(input: {
7
+ readonly ensureSessionContext: (event: InstrumentationSessionStartedEvent) => Promise<AgentSessionTraceState>;
8
+ readonly frameworkVersion: string;
9
+ readonly idGenerator: AgentSpanIdGenerator;
10
+ readonly recordInputs: boolean;
11
+ readonly stateStore: AgentTraceStateStore;
12
+ readonly tracer: Tracer;
13
+ }): Pick<NonNullable<InstrumentationProviderDefinition["events"]>, "channel.delivery.cancelled" | "channel.delivery.completed" | "channel.delivery.failed" | "channel.delivery.started">;
@@ -0,0 +1 @@
1
+ import{ROOT_CONTEXT,SpanKind,SpanStatusCode,trace}from"#compiled/@opentelemetry/api/index.js";import{sessionIdempotencyKey}from"#harness/instrumentation-lifecycle.js";import{contentAttribute}from"#tracing/agent-otel-content.js";function createAgentChannelDeliveryInstrumentation(e){let onStarted=async(t,n)=>{let r=await e.ensureSessionContext({agentName:t.agentName,channelKind:t.delivery.channelKind,idempotencyKey:sessionIdempotencyKey(t.sessionId),parentTraceContext:t.parentTraceContext,rootSessionId:t.rootSessionId,sessionId:t.sessionId,type:`session.started`}),o=e.recordInputs?contentAttribute(t.input,!1):void 0,s={parent:{isRemote:r.context.isRemote??!1,spanId:r.context.spanId,traceFlags:r.context.traceFlags,traceId:r.context.traceId},spanId:e.idGenerator.deriveSpanId(`channel-delivery:${t.idempotencyKey}`),startTimeMs:Date.now(),window:r.window};o!==void 0&&(s.inputAttribute=o),t.delivery.requestTraceContext!==void 0&&(s.requestTraceContext={spanId:t.delivery.requestTraceContext.spanId,traceFlags:t.delivery.requestTraceContext.traceFlags,traceId:t.delivery.requestTraceContext.traceId}),n.state.set(s)},onTerminal=async(n,r)=>{let i=readState(r.state.get());if(i===void 0)return;let a=n.turnId===void 0?void 0:await e.stateStore.getTurn(n.sessionId,n.turnId),o=await e.stateStore.getSession(n.sessionId),s=a===void 0?i.parent:{isRemote:a.parentIsRemote??!1,spanId:a.parentSpanId,traceFlags:a.context.traceFlags,traceId:a.context.traceId},c=a===void 0?i.startTimeMs:Math.max(i.startTimeMs,a.startTimeMs),l=i.requestTraceContext,u=e.idGenerator.withSpanId(i.spanId,()=>e.tracer.startSpan(`agent.channel.delivery`,{attributes:{"agent.channel.delivery.id":n.delivery.deliveryId,"agent.channel.delivery.outcome":n.outcome,"agent.channel.kind":n.delivery.channelKind,"agent.channel.name":n.delivery.channelName,"agent.channel.request.id":n.delivery.requestId,"agent.framework.name":`eve`,"agent.framework.version":e.frameworkVersion,"agent.name":n.agentName,"agent.root.session.id":n.rootSessionId,"agent.session.id":n.sessionId,"agent.session.window":o?.window??i.window,"agent.turn.id":n.turnId,"agent.turn.sequence":n.sequence},kind:SpanKind.CONSUMER,links:l===void 0?void 0:[{attributes:{"eve.link.type":`channel.request`},context:l}],startTime:c},contextFromSpanContext(s)));if(u.addEvent(`channel.delivery.started`,void 0,c),u.addEvent(n.type),i.inputAttribute!==void 0&&u.setAttribute(`agent.channel.delivery.input`,i.inputAttribute),n.outcome===`failed`){let e=n.errorCode??(n.error instanceof Error?n.error.name:`Error`);u.setAttribute(`error.type`,e),n.errorCode!==void 0&&u.setAttribute(`agent.channel.delivery.error.code`,n.errorCode),recordError(u,n.error)}u.end()};return{"channel.delivery.cancelled":onTerminal,"channel.delivery.completed":onTerminal,"channel.delivery.failed":onTerminal,"channel.delivery.started":onStarted}}function readState(e){if(!isRecord(e)||!isSpanContext(e.parent)||typeof e.spanId!=`string`||typeof e.startTimeMs!=`number`||typeof e.window!=`number`)return;let t=isSpanContext(e.requestTraceContext)?e.requestTraceContext:void 0;return{inputAttribute:typeof e.inputAttribute==`string`?e.inputAttribute:void 0,parent:e.parent,requestTraceContext:t,spanId:e.spanId,startTimeMs:e.startTimeMs,window:e.window}}function isSpanContext(e){return isRecord(e)&&typeof e.spanId==`string`&&typeof e.traceFlags==`number`&&typeof e.traceId==`string`}function isRecord(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function contextFromSpanContext(t){return trace.setSpan(ROOT_CONTEXT,trace.wrapSpanContext(t))}function recordError(e,t){t instanceof Error?(e.recordException(t),e.setStatus({code:SpanStatusCode.ERROR,message:t.message})):e.setStatus({code:SpanStatusCode.ERROR})}export{createAgentChannelDeliveryInstrumentation};
@@ -19,6 +19,12 @@ export declare function contentAttribute(value: unknown, strip?: boolean): strin
19
19
  * the cap is truncated at the text level rather than the JSON level.
20
20
  */
21
21
  export declare function messagesContentAttribute(messages: unknown): string | undefined;
22
+ /** Serializes model messages using the OpenTelemetry GenAI message schema. */
23
+ export declare function genAiInputMessagesAttribute(messages: unknown): string | undefined;
24
+ /** Serializes the system prompt using the OpenTelemetry GenAI instruction schema. */
25
+ export declare function genAiSystemInstructionsAttribute(instructions: unknown): string | undefined;
26
+ /** Serializes one model response using the OpenTelemetry GenAI message schema. */
27
+ export declare function genAiOutputMessagesAttribute(content: readonly unknown[], finishReason: string): string | undefined;
22
28
  /**
23
29
  * Serializes provider-executed tool results, keeping the attribute valid
24
30
  * JSON under the cap: when the full payload is too big, each entry's input
@@ -1,4 +1,4 @@
1
- const CONTENT_ATTRIBUTE_LIMIT=32*1024,CONTENT_NOISE_KEYS=new Set([`providerOptions`,`providerMetadata`]),TRUNCATED_MESSAGES_KEY=`eve.truncated`;function contentAttribute(e,t=!0){if(e===void 0)return;let n=t?stripContentNoise(e,0):e,r;try{r=JSON.stringify(n)}catch{return}if(r!==void 0)return textContentAttribute(r)}function messagesContentAttribute(e){if(!Array.isArray(e))return contentAttribute(e);let t=stripContentNoise(e,0),r=stringifyContent(t);if(r!==void 0&&r.length<=32768)return r;for(let e=1;e<t.length;e+=1){let r=stringifyContent([{[TRUNCATED_MESSAGES_KEY]:{omittedMessages:e}},...t.slice(e)]);if(r!==void 0&&r.length<=32768)return r}return truncateSingleMessage(t)}function toolResultsContentAttribute(t){if(t.length===0)return;let n=stringifyContent(t);if(n!==void 0&&n.length<=32768)return n;for(let n=CONTENT_ATTRIBUTE_LIMIT;n>=0;n=n>=256?Math.floor(n/2):-1){let e=stringifyContent(t.map(e=>cappedToolResult(e,n)));if(e!==void 0&&e.length<=32768)return e}}function cappedToolResult(e,t){let n={toolName:e.toolName};for(let r of[`input`,`output`,`error`]){if(!(r in e))continue;let i=e[r],a=typeof i==`string`?i:stringifyContent(i)??``;n[r]=a.length<=t?a:`${a.slice(0,t)}… [truncated]`}return n}function systemPromptAttribute(e){if(typeof e==`string`)return textContentAttribute(e);if(!isRecord(e)&&!Array.isArray(e))return;let t=Array.isArray(e)?e:[e],n=[];for(let e of t)if(isRecord(e)){if(typeof e.content==`string`)n.push(e.content);else if(Array.isArray(e.content))for(let t of e.content)isRecord(t)&&t.type===`text`&&typeof t.text==`string`&&n.push(t.text)}let r=n.join(`
1
+ const CONTENT_ATTRIBUTE_LIMIT=32*1024,CONTENT_NOISE_KEYS=new Set([`providerOptions`,`providerMetadata`]),TRUNCATED_MESSAGES_KEY=`eve.truncated`;function contentAttribute(e,t=!0){if(e===void 0)return;let n=t?stripContentNoise(e,0):e,r;try{r=JSON.stringify(n)}catch{return}if(r!==void 0)return textContentAttribute(r)}function messagesContentAttribute(e){if(!Array.isArray(e))return contentAttribute(e);let t=stripContentNoise(e,0),r=stringifyContent(t);if(r!==void 0&&r.length<=32768)return r;for(let e=1;e<t.length;e+=1){let r=stringifyContent([{[TRUNCATED_MESSAGES_KEY]:{omittedMessages:e}},...t.slice(e)]);if(r!==void 0&&r.length<=32768)return r}return truncateSingleMessage(t)}function genAiInputMessagesAttribute(e){if(!Array.isArray(e))return;let t=e.flatMap(e=>{if(!isRecord(e)||e.role===`system`||typeof e.role!=`string`)return[];let t=semanticParts(e.content);return t.length===0?[]:[{parts:t,role:e.role}]});for(let e=0;e<t.length;e+=1){let n=semanticJsonAttribute(t.slice(e));if(n!==void 0)return n}return semanticJsonAttribute([])}function genAiSystemInstructionsAttribute(e){let t=systemPromptAttribute(e);return t===void 0?void 0:semanticJsonAttribute([{content:t,type:`text`}])}function genAiOutputMessagesAttribute(e,t){let n=semanticParts(e);return semanticJsonAttribute([{finish_reason:t===`tool-calls`?`tool_call`:t,parts:n,role:`assistant`}])}function toolResultsContentAttribute(t){if(t.length===0)return;let n=stringifyContent(t);if(n!==void 0&&n.length<=32768)return n;for(let n=CONTENT_ATTRIBUTE_LIMIT;n>=0;n=n>=256?Math.floor(n/2):-1){let e=stringifyContent(t.map(e=>cappedToolResult(e,n)));if(e!==void 0&&e.length<=32768)return e}}function cappedToolResult(e,t){let n={toolName:e.toolName};for(let r of[`input`,`output`,`error`]){if(!(r in e))continue;let i=e[r],a=typeof i==`string`?i:stringifyContent(i)??``;n[r]=a.length<=t?a:`${a.slice(0,t)}… [truncated]`}return n}function systemPromptAttribute(e){if(typeof e==`string`)return textContentAttribute(e);if(!isRecord(e)&&!Array.isArray(e))return;let t=Array.isArray(e)?e:[e],n=[];for(let e of t)if(isRecord(e)){if(typeof e.content==`string`)n.push(e.content);else if(Array.isArray(e.content))for(let t of e.content)isRecord(t)&&t.type===`text`&&typeof t.text==`string`&&n.push(t.text)}let r=n.join(`
2
2
 
3
3
  `).trim();return r.length===0?void 0:textContentAttribute(r)}function textContentAttribute(t){if(t.length!==0)return t.length<=32768?t:`${t.slice(0,CONTENT_ATTRIBUTE_LIMIT)}… [truncated]`}function stripContentNoise(e,n){if(n>32||typeof e!=`object`||!e)return e;if(Array.isArray(e))return e.map(e=>stripContentNoise(e,n+1));let r={};for(let[i,a]of Object.entries(e))CONTENT_NOISE_KEYS.has(i)||(r[i]=stripContentNoise(a,n+1));return r}function truncateSingleMessage(t){if(t.length===0)return;let r=t[t.length-1];if(!isRecord(r))return;let i={[TRUNCATED_MESSAGES_KEY]:{omittedMessages:t.length-1}},a=typeof r.role==`string`?r.role:`user`,o=``;if(typeof r.content==`string`)o=r.content;else if(Array.isArray(r.content))for(let e of r.content)isRecord(e)&&e.type===`text`&&typeof e.text==`string`&&(o+=(o?`
4
- `:``)+e.text);for(let t=Math.min(o.length,CONTENT_ATTRIBUTE_LIMIT);t>0;t-=256){let e=stringifyContent([i,{role:a,content:t>=o.length?o:`${o.slice(0,t)}… [truncated]`}]);if(e!==void 0&&e.length<=32768)return e}return stringifyContent([i,{role:a,content:``}])}function stringifyContent(e){try{return JSON.stringify(e)}catch{return}}function isRecord(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}export{CONTENT_ATTRIBUTE_LIMIT,contentAttribute,messagesContentAttribute,systemPromptAttribute,textContentAttribute,toolResultsContentAttribute};
4
+ `:``)+e.text);for(let t=Math.min(o.length,CONTENT_ATTRIBUTE_LIMIT);t>0;t-=256){let e=stringifyContent([i,{role:a,content:t>=o.length?o:`${o.slice(0,t)}… [truncated]`}]);if(e!==void 0&&e.length<=32768)return e}return stringifyContent([i,{role:a,content:``}])}function stringifyContent(e){try{return JSON.stringify(e)}catch{return}}function semanticJsonAttribute(e){let t=stringifyContent(e);return t!==void 0&&t.length<=32768?t:void 0}function semanticParts(e){if(typeof e==`string`)return[{content:e,type:`text`}];if(!Array.isArray(e))return[];let t=[];for(let n of e){let e=semanticPart(n);e!==void 0&&t.push(e)}return t}function semanticPart(e){if(!(!isRecord(e)||typeof e.type!=`string`))switch(e.type){case`text`:case`reasoning`:{let t=typeof e.text==`string`?e.text:e.content;return typeof t==`string`?{content:t,type:e.type}:void 0}case`tool-call`:return{arguments:e.input,id:stringValue(e.toolCallId)??stringValue(e.callId)??null,name:e.toolName,type:`tool_call`};case`tool-result`:return{id:stringValue(e.toolCallId)??stringValue(e.callId)??null,response:toolResponse(e.output),type:`tool_call_response`};case`tool-error`:return{id:stringValue(e.toolCallId)??stringValue(e.callId)??null,response:e.error instanceof Error?e.error.message:e.error,type:`tool_call_response`};default:return{type:e.type}}}function toolResponse(e){return isRecord(e)?(e.type===`text`||e.type===`error-text`||e.type===`json`||e.type===`error-json`)&&`value`in e?e.value:e.type===`execution-denied`?{denied:!0,reason:e.reason}:e:e}function stringValue(e){return typeof e==`string`?e:void 0}function isRecord(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}export{CONTENT_ATTRIBUTE_LIMIT,contentAttribute,genAiInputMessagesAttribute,genAiOutputMessagesAttribute,genAiSystemInstructionsAttribute,messagesContentAttribute,systemPromptAttribute,textContentAttribute,toolResultsContentAttribute};
@@ -1,16 +1,16 @@
1
1
  import { type Tracer } from "#compiled/@opentelemetry/api/index.js";
2
+ import { type AgentTraceStateStore } from "#tracing/agent-trace-state.js";
2
3
  import type { AgentSpanIdGenerator } from "#tracing/agent-span-id-generator.js";
3
- import type { AgentTraceStateStore } from "#tracing/agent-trace-state.js";
4
4
  import type { InstrumentationContextRunner, InstrumentationProviderDefinition } from "#harness/instrumentation-lifecycle.js";
5
- /** Sized so an ordinary session stays one trace and only an outsized one rolls. */
6
- export declare const SESSION_WINDOW_TURN_LIMIT = 200;
7
5
  export interface AgentOtelInstrumentationInput {
8
6
  /**
9
- * Capture model prompts/responses and tool call inputs/outputs as span
10
- * attributes. Content stays on the local machine — this provider only
11
- * wires the dev-time local spool — but can be turned off per project.
7
+ * Whether to write model prompts and tool call inputs onto spans at all.
8
+ * This is the union across destinations, not one destination's policy: a
9
+ * destination that declined drops these on its way out instead.
12
10
  */
13
- readonly captureContent?: boolean;
11
+ readonly recordInputs?: boolean;
12
+ /** The same, for model responses and tool call outputs. */
13
+ readonly recordOutputs?: boolean;
14
14
  readonly frameworkVersion: string;
15
15
  readonly idGenerator: AgentSpanIdGenerator;
16
16
  readonly stateStore: AgentTraceStateStore;
@@ -1,2 +1,2 @@
1
- import{ROOT_CONTEXT,SpanStatusCode,context,trace}from"#compiled/@opentelemetry/api/index.js";import{contentAttribute,messagesContentAttribute,systemPromptAttribute,textContentAttribute,toolResultsContentAttribute}from"#tracing/agent-otel-content.js";const SESSION_WINDOW_TURN_LIMIT=200;function createAgentOtelInstrumentation(e){let t=e.captureContent??!0,l=new WeakMap,u=new WeakMap,onSessionStarted=async e=>{await ensureSessionContext(e)},onTurnStarted=async t=>{let n=advanceSessionWindow(t.sessionId,await ensureSessionContext({agentName:void 0,channelKind:void 0,parentTraceContext:t.parentTraceContext,rootSessionId:t.rootSessionId,sessionId:t.sessionId,type:`session.started`})),r={isRemote:!1,spanId:e.idGenerator.allocateSpanId(),traceFlags:n.context.traceFlags,traceId:n.context.traceId};await e.stateStore.setSession(t.sessionId,{...n,turnsInWindow:n.turnsInWindow+1}),await e.stateStore.setTurn(t.sessionId,t.turnId,{context:r,lineage:t.parentLineage,parentSpanId:n.context.spanId,rootSessionId:t.rootSessionId,sequence:t.sequence,startTimeMs:Date.now()})},onAttemptStarted=async t=>{let n=await e.stateStore.getTurn(t.scope.sessionId,t.scope.turnId);if(n===void 0)return;let i=contextFromSpanContext(n.context),a=e.tracer.startSpan(`agent.step`,{attributes:{"agent.session.id":t.scope.sessionId,"agent.framework.name":`eve`,"agent.framework.version":e.frameworkVersion,"agent.root.session.id":t.scope.rootSessionId??t.scope.sessionId,"agent.step.attempt":t.scope.attemptIndex,"agent.step.index":t.scope.stepIndex,"agent.turn.id":t.scope.turnId,"agent.name":t.scope.functionId}},i);a.addEvent(`step.started`);let o=trace.setSpan(i,a),s=t.operation.operationId,c=e.tracer.startSpan(s,{attributes:{"gen_ai.operation.name":s,"gen_ai.provider.name":t.operation.provider,"gen_ai.request.model":t.operation.modelId}},o);u.set(t.scope,{operation:{context:trace.setSpan(o,c),name:s,span:c},step:{context:o,span:a}})},onAttemptTerminal=e=>{l.delete(e.scope);let t=u.get(e.scope);t!==void 0&&(t.step.span.addEvent(e.type===`attempt.completed`?`step.completed`:`step.failed`),e.type===`attempt.failed`&&(recordError(t.operation.span,e.error),recordError(t.step.span,e.error)),t.operation.span.end(),t.step.span.end(),u.delete(e.scope))},onTurnTerminal=async t=>{let n=await e.stateStore.getTurn(t.sessionId,t.turnId);n!==void 0&&await e.stateStore.setTurn(t.sessionId,t.turnId,{...n,terminal:{error:t.error,type:t.type}})},onSessionTransition=async t=>{if(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),i=e.idGenerator.withSpanId(n.context.spanId,()=>e.tracer.startSpan(`agent.turn`,{attributes:{"agent.framework.name":`eve`,"agent.framework.version":e.frameworkVersion,"agent.name":r?.agentName,...parentLineageAttributes(n.lineage),"agent.root.session.id":n.rootSessionId,"agent.session.id":t.sessionId,"agent.session.window":r?.window,"agent.turn.id":t.turnId,"agent.turn.sequence":n.sequence},startTime:n.startTimeMs},contextFromSpanContext({isRemote:!1,spanId:n.parentSpanId,traceFlags:n.context.traceFlags,traceId:n.context.traceId})));i.addEvent(`turn.started`,void 0,n.startTimeMs),n.terminal!==void 0&&(i.addEvent(n.terminal.type),n.terminal.type===`turn.failed`&&recordError(i,n.terminal.error)),i.addEvent(t.type),i.end(),await e.stateStore.deleteTurn(t.sessionId,t.turnId)}}(t.type===`session.completed`||t.type===`session.failed`)&&await e.stateStore.deleteSession(t.sessionId)},beforeModelCall=n=>{let i=u.get(n.scope);if(i===void 0)return;i.step.span.setAttribute(`agent.model.id`,n.source.modelId),i.step.span.setAttribute(`agent.model.provider`,n.source.provider);let s=e.tracer.startSpan(modelSpanName(i.operation.name),{attributes:{"gen_ai.operation.name":i.operation.name,"gen_ai.provider.name":n.source.provider,"gen_ai.request.model":n.source.modelId}},i.operation.context);if(t){let e=messagesContentAttribute(n.source.messages);e!==void 0&&s.setAttribute(`ai.prompt.messages`,e);let t=systemPromptAttribute(n.source.instructions);t!==void 0&&s.setAttribute(`ai.prompt.system`,t)}let c={context:trace.setSpan(i.operation.context,s),span:s};return getExecutionContexts(n.scope).models.set(n.id,c.context),c},afterModelCall=(e,n)=>{if(l.get(e.scope)?.models.delete(e.id),isSpanState(n)){if(e.type===`model.call.failed`)recordError(n.span,e.error);else{setUsage(n.span,e.source.usage);let r=u.get(e.scope);if(r!==void 0&&setUsage(r.step.span,e.source.usage),t){n.span.setAttribute(`ai.response.finish_reason`,e.source.finishReason);let t=textContentAttribute(e.source.content.filter(e=>e.type===`reasoning`).map(e=>e.text).filter(e=>e.trim().length>0).join(`
2
- `));t!==void 0&&n.span.setAttribute(`ai.response.reasoning`,t);let r=textContentAttribute(e.source.content.filter(e=>e.type===`text`).map(e=>e.text).join(``));r!==void 0&&n.span.setAttribute(`ai.response.text`,r);let a=e.source.content.filter(e=>e.type===`tool-call`).map(e=>({input:e.input,toolName:e.toolName}));if(a.length>0){let e=contentAttribute(a,!1);e!==void 0&&n.span.setAttribute(`ai.response.tool_calls`,e)}let o=e.source.content.filter(e=>e.type===`tool-result`||e.type===`tool-error`).map(e=>e.type===`tool-result`?{input:e.input,output:e.output,toolName:e.toolName}:{error:errorText(e.error),input:e.input,toolName:e.toolName});if(o.length>0){let e=toolResultsContentAttribute(o);e!==void 0&&n.span.setAttribute(`ai.response.tool_results`,e)}}}n.span.end()}},beforeToolCall=n=>{let a=u.get(n.scope);if(a===void 0)return;let o=e.tracer.startSpan(`agent.action`,{attributes:{"agent.action.call_id":n.source.toolCall.toolCallId,"agent.action.kind":`tool`,"agent.action.name":n.source.toolCall.toolName,"agent.framework.name":`eve`,"agent.framework.version":e.frameworkVersion,"agent.root.session.id":n.scope.rootSessionId??n.scope.sessionId,"agent.session.id":n.scope.sessionId,"agent.step.attempt":n.scope.attemptIndex,"agent.step.index":n.scope.stepIndex,"agent.turn.id":n.scope.turnId}},a.step.context),s=trace.setSpan(a.step.context,o),c=e.tracer.startSpan(`ai.toolCall`,{attributes:{"gen_ai.operation.name":`execute_tool`,"gen_ai.tool.call.id":n.source.toolCall.toolCallId,"gen_ai.tool.name":n.source.toolCall.toolName}},s);if(t){let e=contentAttribute(n.source.toolCall.input,!1);e!==void 0&&c.setAttribute(`gen_ai.tool.call.arguments`,e)}let l={context:trace.setSpan(s,c),span:o,toolSpan:c};return getExecutionContexts(n.scope).tools.set(n.id,l.context),l},afterToolCall=(e,n)=>{if(l.get(e.scope)?.tools.delete(e.id),isToolSpanState(n)){if(e.type===`tool.call.failed`)recordError(n.toolSpan,e.error),recordError(n.span,e.error);else if(e.source.toolOutput.type!==`tool-result`)recordError(n.toolSpan,e.source.toolOutput.error),recordError(n.span,e.source.toolOutput.error);else if(t){let t=contentAttribute(e.source.toolOutput.output,!1);t!==void 0&&n.toolSpan.setAttribute(`gen_ai.tool.call.result`,t)}n.toolSpan.end(),n.span.end()}},openSessionWindow=t=>{let n=e.tracer.startSpan(`agent.session`,{attributes:{"agent.framework.name":`eve`,"agent.framework.version":e.frameworkVersion,"agent.name":t.agentName,"agent.root.session.id":t.rootSessionId,"agent.session.id":t.sessionId,"agent.session.window":t.index,...t.previousTraceId===void 0?{}:{"agent.session.window.previous.trace.id":t.previousTraceId}},root:!0});return n.addEvent(t.index===0?`session.started`:`session.window.opened`),n.end(),n.spanContext()},ensureSessionContext=async t=>{let n=await e.stateStore.getSession(t.sessionId);return n===void 0&&(n={agentName:t.agentName,channelKind:t.channelKind,context:t.parentTraceContext===void 0?openSessionWindow({agentName:t.agentName,index:0,rootSessionId:t.rootSessionId,sessionId:t.sessionId}):adoptedSpanContext(t.parentTraceContext),rootSessionId:t.rootSessionId,turnsInWindow:0,window:0},await e.stateStore.setSession(t.sessionId,n)),n},advanceSessionWindow=(e,t)=>{if(t.turnsInWindow<200)return t;let n=t.window+1;return{...t,context:openSessionWindow({agentName:t.agentName,index:n,previousTraceId:t.context.traceId,rootSessionId:t.rootSessionId,sessionId:e}),turnsInWindow:0,window:n}};return{hook:{events:{"attempt.completed":onAttemptTerminal,"attempt.failed":onAttemptTerminal,"attempt.metadata":e=>{let t=u.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.step.span.setAttribute(e,r)},"attempt.started":onAttemptStarted,"model.call":{after:afterModelCall,before:beforeModelCall},"session.completed":onSessionTransition,"session.failed":onSessionTransition,"session.started":onSessionStarted,"session.waiting":onSessionTransition,"tool.call":{after:afterToolCall,before:beforeToolCall},"turn.cancelled":onTurnTerminal,"turn.completed":onTurnTerminal,"turn.failed":onTurnTerminal,"turn.started":onTurnStarted}},runInContext(e,t){let r=l.get(e.scope),i=e.type===`model.call`?r?.models.get(e.id):r?.tools.get(e.id);return i===void 0?t():context.with(i,t)}};function getExecutionContexts(e){let t=l.get(e);return t===void 0&&(t={models:new Map,tools:new Map},l.set(e,t)),t}}function parentLineageAttributes(e){if(e===void 0)return{};let t={"agent.parent.call_id":e.callId,"agent.parent.session.id":e.sessionId,"agent.parent.turn.id":e.turnId};return e.subagentName!==void 0&&(t[`agent.subagent.name`]=e.subagentName),t}function adoptedSpanContext(e){return{isRemote:!1,spanId:e.spanId,traceFlags:e.traceFlags,traceId:e.traceId}}function contextFromSpanContext(t){return trace.setSpan(ROOT_CONTEXT,trace.wrapSpanContext(t))}function readGatewayCost(e){let t=e.gateway;if(!isRecord(t))return;let n={},r=readUsd(t.cost);r!==void 0&&(n[`gen_ai.usage.cost`]=r);let i=readUsd(t.gatewayCost);i!==void 0&&(n[`gen_ai.usage.gateway_cost`]=i);let a=readUsd(t.inputInferenceCost);a!==void 0&&(n[`gen_ai.usage.input_cost`]=a);let o=readUsd(t.outputInferenceCost);return o!==void 0&&(n[`gen_ai.usage.output_cost`]=o),typeof t.generationId==`string`&&t.generationId.length>0&&(n[`gen_ai.generation.id`]=t.generationId),Object.keys(n).length===0?void 0:n}function readUsd(e){if(typeof e!=`string`)return;let t=Number(e);return Number.isFinite(t)?t:void 0}function isSpanState(e){return typeof e==`object`&&!!e&&`context`in e&&`span`in e}function isToolSpanState(e){return isSpanState(e)&&`toolSpan`in e}function isRecord(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function modelSpanName(e){return e===`ai.generateText`?`ai.generateText.doGenerate`:`ai.streamText.doStream`}function setUsage(e,t){t.inputTokens!==void 0&&e.setAttribute(`agent.usage.input_tokens`,t.inputTokens),t.outputTokens!==void 0&&e.setAttribute(`agent.usage.output_tokens`,t.outputTokens);let n=t.inputTokenDetails;n?.cacheReadTokens!==void 0&&e.setAttribute(`gen_ai.usage.cache_read.input_tokens`,n.cacheReadTokens),n?.cacheWriteTokens!==void 0&&e.setAttribute(`gen_ai.usage.cache_creation.input_tokens`,n.cacheWriteTokens)}function errorText(e){return e instanceof Error?e.message:e}function recordError(e,n){n instanceof Error?(e.recordException(n),e.setStatus({code:SpanStatusCode.ERROR,message:n.message})):e.setStatus({code:SpanStatusCode.ERROR})}export{SESSION_WINDOW_TURN_LIMIT,createAgentOtelInstrumentation};
1
+ import{ROOT_CONTEXT,SpanStatusCode,context,trace}from"#compiled/@opentelemetry/api/index.js";import{sessionIdempotencyKey}from"#harness/instrumentation-lifecycle.js";import{contentAttribute,genAiInputMessagesAttribute,genAiOutputMessagesAttribute,genAiSystemInstructionsAttribute,messagesContentAttribute,systemPromptAttribute,textContentAttribute,toolResultsContentAttribute}from"#tracing/agent-otel-content.js";import{setAgentUsage}from"#tracing/agent-otel-usage.js";import{SESSION_WINDOW_TURN_LIMIT}from"#tracing/agent-trace-state.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";function createAgentOtelInstrumentation(e){let t=e.recordInputs??!0,d=e.recordOutputs??!0,f=new WeakMap,p=new Map,m=new WeakMap,h=new WeakMap,g=createAgentActionInstrumentation({frameworkVersion:e.frameworkVersion,idGenerator:e.idGenerator,recordInputs:t,recordOutputs:d,resolveParent:async t=>{let n=await e.stateStore.getTurn(t.scope.sessionId,t.scope.turnId);return n===void 0?void 0:{context:contextFromSpanContext(n.context),spanContext:n.context}},stateStore:e.stateStore,tracer:e.tracer}),_=createAgentApprovalInstrumentation({actionContextFor:g.contextFor,frameworkVersion:e.frameworkVersion,idGenerator:e.idGenerator,recordInputs:t,recordOutputs:d,tracer:e.tracer}),v=createAgentToolInstrumentation({actionContextFor:g.contextFor,idGenerator:e.idGenerator,recordInputs:t,recordOutputs:d,resolveFallback:e=>{let t=p.get(e.scope.attemptId)??e.scope,n=m.get(t)?.step;return n===void 0?void 0:{context:n.context,spanContext:n.span.spanContext()}},tracer:e.tracer}),onSessionStarted=async e=>{await ensureSessionContext(e)},onTurnStarted=async t=>{let n=advanceSessionWindow(t.sessionId,await ensureSessionContext({agentName:void 0,channelKind:void 0,idempotencyKey:sessionIdempotencyKey(t.sessionId),parentTraceContext:t.parentTraceContext,rootSessionId:t.rootSessionId,sessionId:t.sessionId,type:`session.started`})),r={isRemote:!1,spanId:e.idGenerator.deriveSpanId(`turn:${t.idempotencyKey}`),traceFlags:n.context.traceFlags,traceId:n.context.traceId};await e.stateStore.setSession(t.sessionId,{...n,turnsInWindow:n.turnsInWindow+1}),await e.stateStore.setTurn(t.sessionId,t.turnId,{context:r,lineage:t.parentLineage,parentIsRemote:n.context.isRemote,parentSpanId:n.context.spanId,rootSessionId:t.rootSessionId,sequence:t.sequence,startTimeMs:Date.now()})},onStepStarted=async t=>{let i=await e.stateStore.getTurn(t.scope.sessionId,t.scope.turnId);if(i===void 0)return;let a=contextFromSpanContext(i.context),o=trace.getSpan(context.active())?.spanContext(),s=e.tracer.startSpan(`agent.step`,{attributes:{"agent.session.id":t.scope.sessionId,"agent.framework.name":`eve`,"agent.framework.version":e.frameworkVersion,"agent.root.session.id":t.scope.rootSessionId??t.scope.sessionId,"agent.step.attempt":t.scope.attemptIndex,"agent.step.index":t.scope.stepIndex,"agent.turn.id":t.scope.turnId,"agent.name":t.scope.functionId},links:o===void 0||o.traceId===i.context.traceId?void 0:[{attributes:{"eve.link.type":`workflow.delivery`},context:o}]},a);s.addEvent(`step.started`);let c=trace.setSpan(a,s),l=t.operation.operationId,u=e.tracer.startSpan(l,{attributes:{"ai.operation.name":l,"ai.provider.name":t.operation.provider,"ai.request.model":t.operation.modelId}},c);m.set(t.scope,{operation:{context:trace.setSpan(c,u),name:l,span:u},step:{context:c,span:s}}),p.set(t.scope.attemptId,t.scope)},onStepTerminal=async e=>{let t=p.get(e.scope.attemptId)??e.scope;f.delete(t),drainOpenSpans({...e,scope:t}),v.drain(e.scope.attemptId,e.type===`step.attempt.failed`?{error:e.error}:void 0),e.type===`step.attempt.failed`&&await g.failForAttempt(t,e.error),p.delete(e.scope.attemptId);let n=m.get(t);n!==void 0&&(n.step.span.addEvent(e.type===`step.attempt.completed`?`step.completed`:`step.failed`),e.type===`step.attempt.failed`&&(recordError(n.operation.span,e.error),recordError(n.step.span,e.error)),n.operation.span.end(),n.step.span.end(),m.delete(t))},onTurnTerminal=async t=>{(t.type===`turn.cancelled`||t.type===`turn.failed`)&&await g.deleteForTurn(t.sessionId,t.turnId);let n=await e.stateStore.getTurn(t.sessionId,t.turnId);n!==void 0&&await e.stateStore.setTurn(t.sessionId,t.turnId,{...n,terminal:t.type===`turn.failed`?{error:t.error,type:t.type}:{type:t.type}})},onSessionTransition=async t=>{if(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),i=e.idGenerator.withSpanId(n.context.spanId,()=>e.tracer.startSpan(`agent.turn`,{attributes:{"agent.framework.name":`eve`,"agent.framework.version":e.frameworkVersion,"agent.name":r?.agentName,...parentLineageAttributes(n.lineage),"agent.root.session.id":n.rootSessionId,"agent.session.id":t.sessionId,"agent.session.window":r?.window,"agent.turn.id":t.turnId,"agent.turn.sequence":n.sequence},startTime:n.startTimeMs},contextFromSpanContext({isRemote:n.parentIsRemote??!1,spanId:n.parentSpanId,traceFlags:n.context.traceFlags,traceId:n.context.traceId})));i.addEvent(`turn.started`,void 0,n.startTimeMs),n.terminal!==void 0&&(i.addEvent(n.terminal.type),n.terminal.type===`turn.failed`&&recordError(i,n.terminal.error)),i.end(),await e.stateStore.deleteTurn(t.sessionId,t.turnId)}}(t.type===`session.completed`||t.type===`session.failed`)&&(await g.deleteForSession(t.sessionId),await e.stateStore.deleteSession(t.sessionId))},onModelCallStarted=n=>{let i=m.get(n.scope);if(i===void 0)return;i.step.span.setAttribute(`agent.model.id`,n.model.modelId),i.step.span.setAttribute(`agent.model.provider`,n.model.provider);let a=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}},i.operation.context);if(t&&n.input!==void 0){let e=messagesContentAttribute(n.input.messages);e!==void 0&&a.setAttribute(`ai.prompt.messages`,e);let t=genAiInputMessagesAttribute(n.input.messages);t!==void 0&&a.setAttribute(`gen_ai.input.messages`,t);let r=systemPromptAttribute(n.input.instructions);r!==void 0&&a.setAttribute(`ai.prompt.system`,r);let i=genAiSystemInstructionsAttribute(n.input.instructions);i!==void 0&&a.setAttribute(`gen_ai.system_instructions`,i)}let s={context:trace.setSpan(i.operation.context,a),span:a};getExecutionContexts(n.scope).set(n.idempotencyKey,s.context),getSpanStates(h,n.scope).set(n.idempotencyKey,s)},onModelCallTerminal=e=>{f.get(e.scope)?.delete(e.idempotencyKey);let t=takeSpanState(h,e.scope,e.idempotencyKey);if(t!==void 0){if(e.type===`model.call.failed`)recordError(t.span,e.error);else{setAgentUsage(t.span,e.usage),t.span.setAttribute(`gen_ai.response.finish_reasons`,[e.finishReason]);let n=m.get(e.scope);if(n!==void 0&&setAgentUsage(n.step.span,e.usage),d){t.span.setAttribute(`ai.response.finish_reason`,e.finishReason);let n=e.content??[],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 o=textContentAttribute(n.filter(e=>e.type===`text`).map(e=>e.text).join(``));o!==void 0&&t.span.setAttribute(`ai.response.text`,o);let c=n.filter(e=>e.type===`tool-call`).map(e=>({callId:e.callId,input:e.input,toolName:e.toolName}));if(c.length>0){let e=contentAttribute(c,!1);e!==void 0&&t.span.setAttribute(`ai.response.tool_calls`,e)}let l=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(l.length>0){let e=toolResultsContentAttribute(l);e!==void 0&&t.span.setAttribute(`ai.response.tool_results`,e)}}}t.span.end()}},openSessionWindow=t=>{let n=e.tracer.startSpan(`agent.session`,{attributes:{"agent.framework.name":`eve`,"agent.framework.version":e.frameworkVersion,"agent.name":t.agentName,"agent.root.session.id":t.rootSessionId,"agent.session.id":t.sessionId,"agent.session.window":t.index,"agent.trace.schema.version":1,...t.previousTraceId===void 0?{}:{"agent.session.window.previous.trace.id":t.previousTraceId}},root:!0});return n.addEvent(t.index===0?`session.started`:`session.window.opened`),n.end(),n.spanContext()},ensureSessionContext=async t=>{let n=await e.stateStore.getSession(t.sessionId);return n===void 0&&(n={agentName:t.agentName,channelKind:t.channelKind,context:t.parentTraceContext===void 0?openSessionWindow({agentName:t.agentName,index:0,rootSessionId:t.rootSessionId,sessionId:t.sessionId}):adoptedSpanContext(t.parentTraceContext),rootSessionId:t.rootSessionId,turnsInWindow:0,window:0},await e.stateStore.setSession(t.sessionId,n)),n},y=createAgentChannelDeliveryInstrumentation({ensureSessionContext,frameworkVersion:e.frameworkVersion,idGenerator:e.idGenerator,recordInputs:t,stateStore:e.stateStore,tracer:e.tracer}),advanceSessionWindow=(e,t)=>{if(t.turnsInWindow<SESSION_WINDOW_TURN_LIMIT)return t;let n=t.window+1;return{...t,context:openSessionWindow({agentName:t.agentName,index:n,previousTraceId:t.context.traceId,rootSessionId:t.rootSessionId,sessionId:e}),turnsInWindow:0,window:n}},onStepMetadata=e=>{let t=m.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.step.span.setAttribute(e,r)};return{hook:{capture:t||d?`content`:`metadata`,events:{...y,"action.completed":g.events[`action.completed`],"action.failed":g.events[`action.failed`],async"action.started"(e,t){await g.events[`action.started`](e,t),await v.actionStarted(e)},..._,"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,...v.events,"turn.cancelled":onTurnTerminal,"turn.completed":onTurnTerminal,"turn.failed":onTurnTerminal,"turn.started":onTurnStarted},name:`eve.otel`},runInContext(e,t){let r=p.get(e.scope.attemptId)??e.scope,i=f.get(r),a=e.type===`model.call`?i?.get(e.idempotencyKey):v.contextFor(e.scope.attemptId,e.idempotencyKey);return a===void 0?t():context.with(a,t)}};function getExecutionContexts(e){let t=f.get(e);return t===void 0&&(t=new Map,f.set(e,t)),t}function drainOpenSpans(e){for(let t of h.get(e.scope)?.values()??[])e.type===`step.attempt.failed`&&recordError(t.span,e.error),t.span.end();h.delete(e.scope)}}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 parentLineageAttributes(e){if(e===void 0)return{};let t={"agent.parent.call_id":e.callId,"agent.parent.session.id":e.sessionId,"agent.parent.turn.id":e.turnId};return e.subagentName!==void 0&&(t[`agent.subagent.name`]=e.subagentName),t}function adoptedSpanContext(e){return{isRemote:`isRemote`in e&&e.isRemote===!0,spanId:e.spanId,traceFlags:e.traceFlags,traceId:e.traceId}}function contextFromSpanContext(t){return trace.setSpan(ROOT_CONTEXT,trace.wrapSpanContext(t))}function readGatewayCost(e){let t=e.gateway;if(!isRecord(t))return;let n={},r=readUsd(t.cost);r!==void 0&&(n[`gen_ai.usage.cost`]=r);let i=readUsd(t.gatewayCost);i!==void 0&&(n[`gen_ai.usage.gateway_cost`]=i);let a=readUsd(t.inputInferenceCost);a!==void 0&&(n[`gen_ai.usage.input_cost`]=a);let o=readUsd(t.outputInferenceCost);return o!==void 0&&(n[`gen_ai.usage.output_cost`]=o),typeof t.generationId==`string`&&t.generationId.length>0&&(n[`gen_ai.generation.id`]=t.generationId),Object.keys(n).length===0?void 0:n}function readUsd(e){if(typeof e!=`string`)return;let t=Number(e);return Number.isFinite(t)?t:void 0}function isRecord(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function modelSpanName(e){return`chat ${e}`}function errorText(e){return e instanceof Error?e.message:e}function recordError(e,n){n instanceof Error?(e.recordException(n),e.setStatus({code:SpanStatusCode.ERROR,message:n.message})):e.setStatus({code:SpanStatusCode.ERROR})}export{createAgentOtelInstrumentation};
@@ -0,0 +1,4 @@
1
+ import type { Span } from "#compiled/@opentelemetry/api/index.js";
2
+ import type { InstrumentationUsage } from "#harness/instrumentation-lifecycle.js";
3
+ /** Applies eve's structural token usage attributes to an agent span. */
4
+ export declare function setAgentUsage(span: Span, usage: InstrumentationUsage): void;
@@ -0,0 +1 @@
1
+ function setAgentUsage(e,t){t.inputTokens!==void 0&&e.setAttribute(`agent.usage.input_tokens`,t.inputTokens),t.outputTokens!==void 0&&e.setAttribute(`agent.usage.output_tokens`,t.outputTokens);let n=t.inputTokenDetails;n?.cacheReadTokens!==void 0&&e.setAttribute(`gen_ai.usage.cache_read.input_tokens`,n.cacheReadTokens),n?.cacheWriteTokens!==void 0&&e.setAttribute(`gen_ai.usage.cache_creation.input_tokens`,n.cacheWriteTokens)}export{setAgentUsage};
@@ -8,6 +8,8 @@ export declare class AgentSpanIdGenerator {
8
8
  #private;
9
9
  /** Reserves a span id for a span emitted later via {@link withSpanId}. */
10
10
  allocateSpanId(): string;
11
+ /** Derives one span id for a replay-stable instrumentation event. */
12
+ deriveSpanId(key: string): string;
11
13
  generateSpanId(): string;
12
14
  generateTraceId(): string;
13
15
  /** Runs `startSpan` so the next span started carries `spanId`. */
@@ -1 +1 @@
1
- var AgentSpanIdGenerator=class{#e;allocateSpanId(){return randomHexId(16)}generateSpanId(){let e=this.#e;return e===void 0?randomHexId(16):(this.#e=void 0,e)}generateTraceId(){return randomHexId(32)}withSpanId(e,t){this.#e=e;try{return t()}finally{this.#e=void 0}}};function randomHexId(e){let t;do{t=``;for(let n=0;n<e;n+=1)t+=`0123456789abcdef`[Math.trunc(Math.random()*16)]}while(!/[1-9a-f]/u.test(t));return t}export{AgentSpanIdGenerator};
1
+ import{createHash}from"node:crypto";var AgentSpanIdGenerator=class{#e;allocateSpanId(){return randomHexId(16)}deriveSpanId(t){let n=createHash(`sha256`).update(t).digest(`hex`).slice(0,16);return/^0+$/u.test(n)?`0000000000000001`:n}generateSpanId(){let e=this.#e;return e===void 0?randomHexId(16):(this.#e=void 0,e)}generateTraceId(){return randomHexId(32)}withSpanId(e,t){this.#e=e;try{return t()}finally{this.#e=void 0}}};function randomHexId(e){let t;do{t=``;for(let n=0;n<e;n+=1)t+=`0123456789abcdef`[Math.trunc(Math.random()*16)]}while(!/[1-9a-f]/u.test(t));return t}export{AgentSpanIdGenerator};
@@ -0,0 +1,28 @@
1
+ import { type Context, type SpanContext, type Tracer } from "#compiled/@opentelemetry/api/index.js";
2
+ import type { InstrumentationActionStartedEvent, InstrumentationToolCallStartedEvent, InstrumentationToolCallTerminalEvent } from "#harness/instrumentation-lifecycle.js";
3
+ import type { AgentSpanIdGenerator } from "#tracing/agent-span-id-generator.js";
4
+ import type { AgentActionContext } from "#tracing/agent-action-instrumentation.js";
5
+ export interface AgentToolInstrumentation {
6
+ actionStarted(event: InstrumentationActionStartedEvent): Promise<void>;
7
+ contextFor(attemptId: string, idempotencyKey: string): Context | undefined;
8
+ drain(attemptId: string, failure?: {
9
+ readonly error: unknown;
10
+ }): void;
11
+ readonly events: {
12
+ readonly "tool.call.completed": (event: InstrumentationToolCallTerminalEvent) => Promise<void>;
13
+ readonly "tool.call.failed": (event: InstrumentationToolCallTerminalEvent) => Promise<void>;
14
+ readonly "tool.call.started": (event: InstrumentationToolCallStartedEvent) => Promise<void>;
15
+ };
16
+ }
17
+ /** Keeps SDK tool spans parented to actions even when SDK telemetry wins the event race. */
18
+ export declare function createAgentToolInstrumentation(input: {
19
+ readonly actionContextFor: (sessionId: string, turnId: string, callId: string) => Promise<AgentActionContext | undefined>;
20
+ readonly idGenerator: AgentSpanIdGenerator;
21
+ readonly recordInputs: boolean;
22
+ readonly recordOutputs: boolean;
23
+ readonly resolveFallback: (event: InstrumentationToolCallStartedEvent) => {
24
+ readonly context: Context;
25
+ readonly spanContext: SpanContext;
26
+ } | undefined;
27
+ readonly tracer: Tracer;
28
+ }): AgentToolInstrumentation;
@@ -0,0 +1 @@
1
+ import{ROOT_CONTEXT,SpanStatusCode,trace}from"#compiled/@opentelemetry/api/index.js";import{actionIdempotencyKey}from"#harness/instrumentation-lifecycle.js";import{contentAttribute}from"#tracing/agent-otel-content.js";function createAgentToolInstrumentation(e){let t=new Map,n=new Map,onStarted=async t=>{let n=actionIdempotencyKey(t.scope.sessionId,t.scope.turnId,t.callId),i=e.resolveFallback(t),a=i===void 0?void 0:reserve(t,n,i),o=await e.actionContextFor(t.scope.sessionId,t.scope.turnId,t.callId);if(a===void 0){if(o===void 0)return;a=reserve(t,n,o)}o!==void 0&&startSpan(a,o.context)},onTerminal=async t=>{let r=n.get(t.scope.attemptId)?.get(t.idempotencyKey);if(r!==void 0){if(r.terminal=t,r.span===void 0){let t=await e.actionContextFor(r.event.scope.sessionId,r.event.scope.turnId,r.event.callId);t!==void 0&&startSpan(r,t.context)}finishIfReady(r)}};return{async actionStarted(n){let r=t.get(n.idempotencyKey);if(r===void 0||r.span!==void 0||r.finished===!0)return;let i=await e.actionContextFor(n.scope.sessionId,n.scope.turnId,n.callId);i!==void 0&&(startSpan(r,i.context),finishIfReady(r))},contextFor:(e,t)=>n.get(e)?.get(t)?.context,drain(e,t){let r=n.get(e);if(r!==void 0){for(let e of r.values())e.finished!==!0&&(e.span===void 0&&startSpan(e,e.fallbackParent),finish(e,t));n.delete(e)}},events:{"tool.call.completed":onTerminal,"tool.call.failed":onTerminal,"tool.call.started":onStarted}};function getAttemptStates(e){let t=n.get(e);return t===void 0&&(t=new Map,n.set(e,t)),t}function reserve(n,r,i){let a=e.idGenerator.deriveSpanId(`tool:${n.idempotencyKey}`),o={actionKey:r,attemptId:n.scope.attemptId,context:contextFromSpanContext({isRemote:!1,spanId:a,traceFlags:i.spanContext.traceFlags,traceId:i.spanContext.traceId}),event:n,fallbackParent:i.context,idempotencyKey:n.idempotencyKey,spanId:a,startTimeMs:Date.now()};return getAttemptStates(n.scope.attemptId).set(n.idempotencyKey,o),t.set(r,o),o}function startSpan(t,n){if(!(t.span!==void 0||t.finished===!0)&&(t.span=e.idGenerator.withSpanId(t.spanId,()=>e.tracer.startSpan(`ai.toolCall`,{attributes:toolAttributes(t.event),startTime:t.startTimeMs},n)),e.recordInputs)){let e=contentAttribute(t.event.input,!1);e!==void 0&&t.span.setAttribute(`gen_ai.tool.call.arguments`,e)}}function finishIfReady(e){e.span===void 0||e.terminal===void 0||finish(e)}function finish(r,a){let o=r.span;if(o===void 0||r.finished===!0)return;r.finished=!0;let s=r.terminal;if(a!==void 0)recordError(o,a.error);else if(s?.type===`tool.call.failed`)recordError(o,s.error);else if(s?.output.type===`error`)recordError(o,s.output.error);else if(s!==void 0&&e.recordOutputs){let e=contentAttribute(s.output.output,!1);e!==void 0&&o.setAttribute(`gen_ai.tool.call.result`,e)}o.end(),t.delete(r.actionKey);let c=n.get(r.attemptId);c?.delete(r.idempotencyKey),c?.size===0&&n.delete(r.attemptId)}}function toolAttributes(e){return{"gen_ai.operation.name":`execute_tool`,"gen_ai.tool.call.id":e.callId,"gen_ai.tool.name":e.toolName}}function contextFromSpanContext(t){return trace.setSpan(ROOT_CONTEXT,trace.wrapSpanContext(t))}function recordError(e,n){n instanceof Error?(e.recordException(n),e.setStatus({code:SpanStatusCode.ERROR,message:n.message})):e.setStatus({code:SpanStatusCode.ERROR})}export{createAgentToolInstrumentation};
@@ -1,5 +1,5 @@
1
1
  import type { SpanContext } from "#compiled/@opentelemetry/api/index.js";
2
- import type { AgentSessionTraceState, AgentTraceStateStore, AgentTurnTraceState } from "#tracing/agent-trace-state.js";
2
+ import type { AgentActionTraceState, AgentSessionTraceState, AgentTraceStateStore, AgentTurnTraceState } from "#tracing/agent-trace-state.js";
3
3
  /** Keeps only framework trace state from an interrupted step's context changes. */
4
4
  export declare function preserveSerializedAgentTraceState(original: Record<string, unknown>, interrupted: Record<string, unknown>): Record<string, unknown>;
5
5
  /**
@@ -8,12 +8,19 @@ export declare function preserveSerializedAgentTraceState(original: Record<strin
8
8
  * to the ambient session.
9
9
  */
10
10
  export declare function readSessionTraceContext(serializedContext: Readonly<Record<string, unknown>>, sessionId: string): SpanContext | undefined;
11
+ /** Reads the durable action span that should parent a dispatched child agent. */
12
+ export declare function readActionTraceContext(serializedContext: Readonly<Record<string, unknown>>, sessionId: string, turnId: string, callId: string): SpanContext | undefined;
11
13
  /** Durable trace state backed by eve's serialized Workflow context. */
12
14
  export declare class ContextAgentTraceStateStore implements AgentTraceStateStore {
15
+ deleteAction(idempotencyKey: string): void;
16
+ deleteActions(sessionId: string, turnId?: string): void;
13
17
  deleteSession(sessionId: string): void;
14
18
  deleteTurn(sessionId: string, turnId: string): void;
19
+ findAction(sessionId: string, callId: string): AgentActionTraceState | undefined;
20
+ getAction(idempotencyKey: string): AgentActionTraceState | undefined;
15
21
  getSession(sessionId: string): AgentSessionTraceState | undefined;
16
22
  getTurn(sessionId: string, turnId: string): AgentTurnTraceState | undefined;
23
+ setAction(idempotencyKey: string, value: AgentActionTraceState): void;
17
24
  setSession(sessionId: string, value: AgentSessionTraceState): void;
18
25
  setTurn(sessionId: string, turnId: string, value: AgentTurnTraceState): void;
19
26
  }
@@ -1 +1 @@
1
- import{contextStorage,loadContext}from"#context/container.js";import{ContextKey}from"#context/key.js";const AgentTraceContextKey=new ContextKey(`eve.harness.agentTrace`,{codec:{deserialize:deserializeState,serialize:serializeState}});function preserveSerializedAgentTraceState(e,t){let n=t[AgentTraceContextKey.name];return n===void 0?e:{...e,[AgentTraceContextKey.name]:n}}function readSessionTraceContext(e,t){let n=e[AgentTraceContextKey.name];if(n!==void 0)return deserializeState(n).sessions[t]?.context}var ContextAgentTraceStateStore=class{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}})}getSession(t){return contextStorage.getStore()?.get(AgentTraceContextKey)?.sessions[t]}getTurn(t,n){return contextStorage.getStore()?.get(AgentTraceContextKey)?.turns[turnKey(t,n)]}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}}))}};function updateState(e){loadContext().set(AgentTraceContextKey,t=>e(t??{sessions:{},turns:{}}))}function turnKey(e,t){return`${e}\0${t}`}function serializeState(e){return{sessions:Object.fromEntries(Object.entries(e.sessions).map(([e,t])=>[e,{...t,context:serializeSpanContext(t.context)}])),turns:Object.fromEntries(Object.entries(e.turns).map(([e,t])=>[e,{...t,context:serializeSpanContext(t.context),terminal:t.terminal===void 0?void 0:{error:serializeError(t.terminal.error),type:t.terminal.type}}]))}}function deserializeState(e){return isRecord(e)?{sessions:deserializeRecord(e.sessions,e=>{if(!(!isRecord(e)||!isSpanContext(e.context)))return{agentName:typeof e.agentName==`string`?e.agentName:void 0,channelKind:typeof e.channelKind==`string`?e.channelKind:void 0,context:e.context,rootSessionId:typeof e.rootSessionId==`string`?e.rootSessionId:``,turnsInWindow:typeof e.turnsInWindow==`number`?e.turnsInWindow:0,window:typeof e.window==`number`?e.window:0}}),turns:deserializeRecord(e.turns,e=>{if(!(!isRecord(e)||!isSpanContext(e.context))&&!(typeof e.parentSpanId!=`string`||typeof e.startTimeMs!=`number`))return{context:e.context,lineage:deserializeLineage(e.lineage),parentSpanId:e.parentSpanId,rootSessionId:typeof e.rootSessionId==`string`?e.rootSessionId:``,sequence:typeof e.sequence==`number`?e.sequence:0,startTimeMs:e.startTimeMs,terminal:deserializeTerminal(e.terminal)}})}:{sessions:{},turns:{}}}function deserializeRecord(e,t){if(!isRecord(e))return{};let n={};for(let[r,i]of Object.entries(e)){let e=t(i);e!==void 0&&(n[r]=e)}return n}function deserializeLineage(e){if(!(!isRecord(e)||typeof e.callId!=`string`||typeof e.sessionId!=`string`||typeof e.turnId!=`string`))return{callId:e.callId,sessionId:e.sessionId,subagentName:typeof e.subagentName==`string`?e.subagentName:void 0,turnId:e.turnId}}function deserializeTerminal(e){if(!isRecord(e)||typeof e.type!=`string`)return;let t=e.type;if(isTurnTerminalType(t))return{error:deserializeError(e.error),type:t}}function serializeSpanContext(e){return{isRemote:e.isRemote,spanId:e.spanId,traceFlags:e.traceFlags,traceId:e.traceId}}function isSpanContext(e){return isRecord(e)&&typeof e.spanId==`string`&&typeof e.traceFlags==`number`&&typeof e.traceId==`string`}function serializeError(e){return e instanceof Error?{message:e.message,name:e.name,stack:e.stack}:void 0}function deserializeError(e){if(!isRecord(e)||typeof e.message!=`string`)return;let t=Error(e.message);return typeof e.name==`string`&&(t.name=e.name),typeof e.stack==`string`&&(t.stack=e.stack),t}function isTurnTerminalType(e){return e===`turn.cancelled`||e===`turn.completed`||e===`turn.failed`}function isRecord(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}export{ContextAgentTraceStateStore,preserveSerializedAgentTraceState,readSessionTraceContext};
1
+ import{contextStorage,loadContext}from"#context/container.js";import{ContextKey}from"#context/key.js";const AgentTraceContextKey=new ContextKey(`eve.harness.agentTrace`,{codec:{deserialize:deserializeState,serialize:serializeState}});function preserveSerializedAgentTraceState(e,t){let n=t[AgentTraceContextKey.name];return n===void 0?e:{...e,[AgentTraceContextKey.name]:n}}function readSessionTraceContext(e,t){let n=e[AgentTraceContextKey.name];if(n!==void 0)return deserializeState(n).sessions[t]?.context}function readActionTraceContext(e,t,n,i){let a=e[AgentTraceContextKey.name];if(a===void 0)return;let o=Object.values(deserializeState(a).actions).find(e=>e.sessionId===t&&e.turnId===n&&e.callId===i);if(o!==void 0)return{isRemote:!1,spanId:o.spanId,traceFlags:o.parent.traceFlags,traceId:o.parent.traceId}}var ContextAgentTraceStateStore=class{deleteAction(e){updateState(t=>{let n={...t.actions};return delete n[e],{...t,actions:n}})}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}})}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(t,n){return Object.values(contextStorage.getStore()?.get(AgentTraceContextKey)?.actions??{}).find(e=>e.sessionId===t&&e.callId===n)}getAction(t){return contextStorage.getStore()?.get(AgentTraceContextKey)?.actions[t]}getSession(t){return contextStorage.getStore()?.get(AgentTraceContextKey)?.sessions[t]}getTurn(t,n){return contextStorage.getStore()?.get(AgentTraceContextKey)?.turns[turnKey(t,n)]}setAction(e,t){updateState(n=>({...n,actions:{...n.actions,[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}}))}};function updateState(e){loadContext().set(AgentTraceContextKey,t=>e(t??{actions:{},sessions:{},turns:{}}))}function turnKey(e,t){return`${e}\0${t}`}function serializeState(e){return{actions:e.actions,sessions:Object.fromEntries(Object.entries(e.sessions).map(([e,t])=>[e,{...t,context:serializeSpanContext(t.context)}])),turns:Object.fromEntries(Object.entries(e.turns).map(([e,t])=>[e,{...t,context:serializeSpanContext(t.context),terminal:t.terminal===void 0?void 0:t.terminal.type===`turn.failed`?{error:serializeError(t.terminal.error),type:t.terminal.type}:{type:t.terminal.type}}]))}}function deserializeState(e){return isRecord(e)?{actions:deserializeRecord(e.actions,deserializeAction),sessions:deserializeRecord(e.sessions,e=>{if(!(!isRecord(e)||!isSpanContext(e.context)))return{agentName:typeof e.agentName==`string`?e.agentName:void 0,channelKind:typeof e.channelKind==`string`?e.channelKind:void 0,context:e.context,rootSessionId:typeof e.rootSessionId==`string`?e.rootSessionId:``,turnsInWindow:typeof e.turnsInWindow==`number`?e.turnsInWindow:0,window:typeof e.window==`number`?e.window:0}}),turns:deserializeRecord(e.turns,e=>{if(!(!isRecord(e)||!isSpanContext(e.context))&&!(typeof e.parentSpanId!=`string`||typeof e.startTimeMs!=`number`))return{context:e.context,lineage:deserializeLineage(e.lineage),parentIsRemote:typeof e.parentIsRemote==`boolean`?e.parentIsRemote:void 0,parentSpanId:e.parentSpanId,rootSessionId:typeof e.rootSessionId==`string`?e.rootSessionId:``,sequence:typeof e.sequence==`number`?e.sequence:0,startTimeMs:e.startTimeMs,terminal:deserializeTerminal(e.terminal)}})}:{actions:{},sessions:{},turns:{}}}function deserializeAction(e){if(!(!isRecord(e)||typeof e.attemptIndex!=`number`||typeof e.callId!=`string`||!isActionKind(e.kind)||typeof e.name!=`string`||!isSpanContext(e.parent)||typeof e.rootSessionId!=`string`||typeof e.sessionId!=`string`||typeof e.spanId!=`string`||typeof e.startTimeMs!=`number`||typeof e.stepIndex!=`number`||typeof e.turnId!=`string`))return{attemptIndex:e.attemptIndex,callId:e.callId,inputAttribute:typeof e.inputAttribute==`string`?e.inputAttribute:void 0,kind:e.kind,name:e.name,parent:e.parent,rootSessionId:e.rootSessionId,sessionId:e.sessionId,spanId:e.spanId,startTimeMs:e.startTimeMs,stepIndex:e.stepIndex,turnId:e.turnId}}function isActionKind(e){return e===`load-skill`||e===`remote-agent-call`||e===`subagent-call`||e===`tool-call`}function deserializeRecord(e,t){if(!isRecord(e))return{};let n={};for(let[r,i]of Object.entries(e)){let e=t(i);e!==void 0&&(n[r]=e)}return n}function deserializeLineage(e){if(!(!isRecord(e)||typeof e.callId!=`string`||typeof e.sessionId!=`string`||typeof e.turnId!=`string`))return{callId:e.callId,sessionId:e.sessionId,subagentName:typeof e.subagentName==`string`?e.subagentName:void 0,turnId:e.turnId}}function deserializeTerminal(e){if(!isRecord(e)||typeof e.type!=`string`)return;let t=e.type;if(isTurnTerminalType(t))return t===`turn.failed`?{error:deserializeError(e.error),type:t}:{type:t}}function serializeSpanContext(e){return{isRemote:e.isRemote,spanId:e.spanId,traceFlags:e.traceFlags,traceId:e.traceId}}function isSpanContext(e){return isRecord(e)&&typeof e.spanId==`string`&&typeof e.traceFlags==`number`&&typeof e.traceId==`string`}function serializeError(e){return e instanceof Error?{message:e.message,name:e.name,stack:e.stack}:void 0}function deserializeError(e){if(!isRecord(e)||typeof e.message!=`string`)return;let t=Error(e.message);return typeof e.name==`string`&&(t.name=e.name),typeof e.stack==`string`&&(t.stack=e.stack),t}function isTurnTerminalType(e){return e===`turn.cancelled`||e===`turn.completed`||e===`turn.failed`}function isRecord(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}export{ContextAgentTraceStateStore,preserveSerializedAgentTraceState,readActionTraceContext,readSessionTraceContext};
@@ -4,7 +4,6 @@ export declare class AgentTraceSpanProcessor implements SpanProcessor {
4
4
  #private;
5
5
  constructor(children: readonly SpanProcessor[]);
6
6
  forceFlush(): Promise<void>;
7
- isAttached(): boolean;
8
7
  onStart(span: unknown, parentContext: unknown): void;
9
8
  onEnd(span: unknown): void;
10
9
  /** Trace ids whose session is still open, so retention never evicts them. */
@@ -1 +1 @@
1
- var AgentTraceSpanProcessor=class{#e;#t=new Set;#n=new Map;#r=!1;constructor(e){this.#e=e}async forceFlush(){await Promise.all(this.#e.map(e=>e.forceFlush()))}isAttached(){return this.#r}onStart(e,t){if(this.#r=!0,!isSpanLike(e))return;let n=e.attributes[`agent.session.id`];if(typeof n==`string`){let t=e.attributes[`agent.root.session.id`],r=typeof t==`string`?t:n,i=e.spanContext().traceId;this.#t.add(i);let a=this.#n.get(r)??new Set;a.add(i),this.#n.set(r,a)}if(this.#i(e))for(let n of this.#e)n.onStart(e,t)}onEnd(e){if(!(!isSpanLike(e)||!this.#i(e)))for(let t of this.#e)t.onEnd(e)}activeTraceIds(){return this.#t}releaseSession(e){let t=this.#n.get(e);if(t===void 0)return!1;for(let e of t)this.#t.delete(e);return this.#n.delete(e),!0}async shutdown(){await Promise.all(this.#e.map(e=>e.shutdown()))}#i(e){return e.instrumentationScope?.name!==`workflow`&&this.#t.has(e.spanContext().traceId)}};function isSpanLike(e){return typeof e==`object`&&!!e&&`attributes`in e&&`spanContext`in e&&typeof e.spanContext==`function`}export{AgentTraceSpanProcessor};
1
+ var AgentTraceSpanProcessor=class{#e;#t=new Set;#n=new Map;constructor(e){this.#e=e}async forceFlush(){await Promise.all(this.#e.map(e=>e.forceFlush()))}onStart(e,t){if(!isSpanLike(e))return;let n=e.attributes[`agent.session.id`];if(typeof n==`string`){let t=e.attributes[`agent.root.session.id`],r=typeof t==`string`?t:n,i=e.spanContext().traceId;this.#t.add(i);let a=this.#n.get(r)??new Set;a.add(i),this.#n.set(r,a)}if(this.#r(e))for(let n of this.#e)n.onStart(e,t)}onEnd(e){if(!(!isSpanLike(e)||!this.#r(e)))for(let t of this.#e)t.onEnd(e)}activeTraceIds(){return this.#t}releaseSession(e){let t=this.#n.get(e);if(t===void 0)return!1;for(let e of t)this.#t.delete(e);return this.#n.delete(e),!0}async shutdown(){await Promise.all(this.#e.map(e=>e.shutdown()))}#r(e){return e.instrumentationScope?.name!==`workflow`&&this.#t.has(e.spanContext().traceId)}};function isSpanLike(e){return typeof e==`object`&&!!e&&`attributes`in e&&`spanContext`in e&&typeof e.spanContext==`function`}export{AgentTraceSpanProcessor};
@@ -1,5 +1,7 @@
1
1
  import type { SpanContext } from "#compiled/@opentelemetry/api/index.js";
2
- import type { InstrumentationParentLineage, InstrumentationTurnTerminalEvent } from "#harness/instrumentation-lifecycle.js";
2
+ import type { InstrumentationActionKind, InstrumentationParentLineage, InstrumentationTraceContext, InstrumentationTurnFailedEvent, InstrumentationTurnSettledEvent } from "#harness/instrumentation-lifecycle.js";
3
+ /** Sized so an ordinary session stays one trace and only an outsized one rolls. */
4
+ export declare const SESSION_WINDOW_TURN_LIMIT = 200;
3
5
  export interface AgentSessionTraceState {
4
6
  readonly agentName?: string;
5
7
  readonly channelKind?: string;
@@ -11,31 +13,59 @@ export interface AgentSessionTraceState {
11
13
  export interface AgentTurnTraceState {
12
14
  readonly context: SpanContext;
13
15
  readonly lineage?: InstrumentationParentLineage;
16
+ readonly parentIsRemote?: boolean;
14
17
  readonly parentSpanId: string;
15
18
  readonly rootSessionId: string;
16
19
  readonly sequence: number;
17
20
  readonly startTimeMs: number;
18
21
  readonly terminal?: {
19
- readonly error?: unknown;
20
- readonly type: InstrumentationTurnTerminalEvent["type"];
22
+ readonly error: unknown;
23
+ readonly type: InstrumentationTurnFailedEvent["type"];
24
+ } | {
25
+ readonly type: InstrumentationTurnSettledEvent["type"];
21
26
  };
22
27
  }
28
+ export interface AgentActionTraceState {
29
+ readonly attemptIndex: number;
30
+ readonly callId: string;
31
+ readonly inputAttribute?: string;
32
+ readonly kind: InstrumentationActionKind;
33
+ readonly name: string;
34
+ readonly parent: InstrumentationTraceContext;
35
+ readonly rootSessionId: string;
36
+ readonly sessionId: string;
37
+ readonly spanId: string;
38
+ readonly startTimeMs: number;
39
+ readonly stepIndex: number;
40
+ readonly turnId: string;
41
+ }
23
42
  /** Provider-owned serializable storage for durable agent trace state. */
24
43
  export interface AgentTraceStateStore {
44
+ deleteAction(idempotencyKey: string): void | PromiseLike<void>;
45
+ deleteActions(sessionId: string, turnId?: string): void | PromiseLike<void>;
25
46
  deleteSession(sessionId: string): void | PromiseLike<void>;
26
47
  deleteTurn(sessionId: string, turnId: string): void | PromiseLike<void>;
48
+ findAction(sessionId: string, callId: string): AgentActionTraceState | undefined | PromiseLike<AgentActionTraceState | undefined>;
49
+ getAction(idempotencyKey: string): AgentActionTraceState | undefined | PromiseLike<AgentActionTraceState | undefined>;
27
50
  getSession(sessionId: string): AgentSessionTraceState | undefined | PromiseLike<AgentSessionTraceState | undefined>;
28
51
  getTurn(sessionId: string, turnId: string): AgentTurnTraceState | undefined | PromiseLike<AgentTurnTraceState | undefined>;
52
+ setAction(idempotencyKey: string, state: AgentActionTraceState): void | PromiseLike<void>;
29
53
  setSession(sessionId: string, state: AgentSessionTraceState): void | PromiseLike<void>;
30
54
  setTurn(sessionId: string, turnId: string, state: AgentTurnTraceState): void | PromiseLike<void>;
31
55
  }
32
56
  /** In-memory trace state used by tests and non-durable runtimes. */
33
57
  export declare class InMemoryAgentTraceStateStore implements AgentTraceStateStore {
34
58
  #private;
59
+ deleteAction(idempotencyKey: string): void;
60
+ deleteActions(sessionId: string, turnId?: string): void;
35
61
  deleteSession(sessionId: string): void;
36
62
  deleteTurn(sessionId: string, turnId: string): void;
63
+ findAction(sessionId: string, callId: string): AgentActionTraceState | undefined;
64
+ getAction(idempotencyKey: string): AgentActionTraceState | undefined;
37
65
  getSession(sessionId: string): AgentSessionTraceState | undefined;
38
66
  getTurn(sessionId: string, turnId: string): AgentTurnTraceState | undefined;
67
+ setAction(idempotencyKey: string, state: AgentActionTraceState): void;
39
68
  setSession(sessionId: string, state: AgentSessionTraceState): void;
40
69
  setTurn(sessionId: string, turnId: string, state: AgentTurnTraceState): void;
41
70
  }
71
+ export declare function turnKey(sessionId: string, turnId: string): string;
@@ -1 +1 @@
1
- var InMemoryAgentTraceStateStore=class{#e=new Map;#t=new Map;deleteSession(e){this.#e.delete(e)}deleteTurn(e,t){this.#t.delete(turnKey(e,t))}getSession(e){return this.#e.get(e)}getTurn(e,t){return this.#t.get(turnKey(e,t))}setSession(e,t){this.#e.set(e,t)}setTurn(e,t,n){this.#t.set(turnKey(e,t),n)}};function turnKey(e,t){return`${e}:${t}`}export{InMemoryAgentTraceStateStore};
1
+ const SESSION_WINDOW_TURN_LIMIT=200;var InMemoryAgentTraceStateStore=class{#e=new Map;#t=new Map;#n=new Map;deleteAction(e){this.#e.delete(e)}deleteActions(e,t){for(let[n,r]of this.#e)r.sessionId===e&&(t===void 0||r.turnId===t)&&this.#e.delete(n)}deleteSession(e){this.#t.delete(e)}deleteTurn(e,t){this.#n.delete(turnKey(e,t))}findAction(e,t){return[...this.#e.values()].find(n=>n.sessionId===e&&n.callId===t)}getAction(e){return this.#e.get(e)}getSession(e){return this.#t.get(e)}getTurn(e,t){return this.#n.get(turnKey(e,t))}setAction(e,t){this.#e.set(e,t)}setSession(e,t){this.#t.set(e,t)}setTurn(e,t,n){this.#n.set(turnKey(e,t),n)}};function turnKey(e,t){return`${e}:${t}`}export{InMemoryAgentTraceStateStore,SESSION_WINDOW_TURN_LIMIT,turnKey};
@@ -0,0 +1,20 @@
1
+ import type { SpanExporter, SpanProcessor } from "#compiled/@vercel/otel/index.js";
2
+ /** @internal — exposed for tests; authors get the defaults. */
3
+ export interface BatchSpanProcessorOptions {
4
+ readonly exportTimeoutMillis?: number;
5
+ readonly maxExportBatchSize?: number;
6
+ readonly maxQueueSize?: number;
7
+ readonly scheduledDelayMillis?: number;
8
+ }
9
+ /**
10
+ * Buffers ended spans and hands them to one exporter in batches.
11
+ *
12
+ * eve owns this rather than taking `@opentelemetry/sdk-trace-base` as a runtime
13
+ * dependency: an exporter needs exactly one thing done for it, and the
14
+ * dependency would arrive with the whole SDK behind it.
15
+ *
16
+ * A full queue drops the newest span rather than growing without bound. An
17
+ * exporter that has stopped draining is already losing telemetry; taking the
18
+ * agent's memory with it would turn that into an outage.
19
+ */
20
+ export declare function batchSpanProcessor(exporter: SpanExporter, options?: BatchSpanProcessorOptions): SpanProcessor;
@@ -0,0 +1 @@
1
+ import{createLogger,formatError}from"#internal/logging.js";import{TraceFlags,context,createContextKey}from"#compiled/@opentelemetry/api/index.js";const log=createLogger(`harness.batch-span-processor`),SUPPRESS_TRACING_KEY=createContextKey(`OpenTelemetry SDK Context Key SUPPRESS_TRACING`),DEFAULTS={exportTimeoutMillis:3e4,maxExportBatchSize:512,maxQueueSize:2048,scheduledDelayMillis:5e3};function batchSpanProcessor(e,n={}){let i=n.exportTimeoutMillis??DEFAULTS.exportTimeoutMillis,o=n.maxExportBatchSize??DEFAULTS.maxExportBatchSize,s=n.maxQueueSize??DEFAULTS.maxQueueSize,c=n.scheduledDelayMillis??DEFAULTS.scheduledDelayMillis,l=[],u,d=Promise.resolve(),f=!1;function cancelTimer(){u!==void 0&&(clearTimeout(u),u=void 0)}function scheduleDrain(){u===void 0&&(u=setTimeout(()=>{u=void 0,drain()},c),u.unref?.())}function drain(){return waitForExporter(pendingDrain(),`span export`).then(()=>void 0)}async function exportBatch(n){try{await new Promise((t,i)=>{try{context.with(context.active().setValue(SUPPRESS_TRACING_KEY,!0),()=>{e.export(n,e=>{if(e.code===0){t();return}i(e.error??Error(`Span export failed.`))})})}catch(e){i(e instanceof Error?e:Error(String(e)))}})}catch(e){log.warn(`span export failed`,{error:formatError(e)})}}return{async forceFlush(){f||!await waitForExporter(pendingDrain(),`span export`)||e.forceFlush===void 0||await waitForExporter(settleExporter(`exporter flush`,e.forceFlush),`exporter flush`)},onEnd(e){if(!f&&isSampled(e)&&!(l.length>=s)){if(l.push(e),l.length>=o){drain();return}scheduleDrain()}},onStart(){},async shutdown(){f=!0;let t=pendingDrain();if(!await waitForExporter(t,`span export`)){t.then(()=>settleExporter(`exporter shutdown`,e.shutdown));return}await waitForExporter(settleExporter(`exporter shutdown`,e.shutdown),`exporter shutdown`)}};function pendingDrain(){return cancelTimer(),d=d.then(async()=>{for(;l.length>0;)await exportBatch(l.splice(0,o))}),d}async function waitForExporter(e,t){let n,r=new Promise(e=>{n=setTimeout(()=>{log.warn(`${t} timed out; preserving exporter serialization`,{timeoutMillis:i}),e(!1)},i),n.unref?.()}),a=e.then(()=>!0);try{return await Promise.race([a,r])}finally{clearTimeout(n)}}async function settleExporter(n,r){try{await r.call(e)}catch(e){log.warn(`${n} failed`,{error:formatError(e)})}}}function isSampled(e){if(typeof e!=`object`||!e||!(`spanContext`in e))return!1;let t=e.spanContext;if(typeof t!=`function`)return!1;let r=Reflect.apply(t,e,[]);return typeof r.traceFlags==`number`&&(r.traceFlags&TraceFlags.SAMPLED)===TraceFlags.SAMPLED}export{batchSpanProcessor};