eve 0.29.2 → 0.29.4

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 (356) hide show
  1. package/CHANGELOG.md +41 -0
  2. package/dist/src/acp/adapter.d.ts +43 -0
  3. package/dist/src/acp/adapter.js +1 -0
  4. package/dist/src/acp/line-limit.d.ts +3 -0
  5. package/dist/src/acp/line-limit.js +1 -0
  6. package/dist/src/acp/server.d.ts +24 -0
  7. package/dist/src/acp/server.js +1 -0
  8. package/dist/src/channel/types.d.ts +15 -0
  9. package/dist/src/chunks/{use-eve-agent-DaH3cf8K.js → use-eve-agent-8mofdZcO.js} +45 -10
  10. package/dist/src/chunks/{use-eve-agent-CyDt3Lny.js → use-eve-agent-bKJbH0k4.js} +45 -10
  11. package/dist/src/cli/acp/command.d.ts +22 -0
  12. package/dist/src/cli/acp/command.js +4 -0
  13. package/dist/src/cli/commands/agent-prompt/build-and-verify.md +4 -0
  14. package/dist/src/cli/commands/extension-init.js +1 -1
  15. package/dist/src/cli/commands/init-git.js +1 -1
  16. package/dist/src/cli/commands/init-repl.js +1 -1
  17. package/dist/src/cli/commands/init.js +1 -1
  18. package/dist/src/cli/commands/integration-setup.d.ts +3 -7
  19. package/dist/src/cli/commands/integration-setup.js +1 -1
  20. package/dist/src/cli/commands/logs.js +2 -2
  21. package/dist/src/cli/commands/register-integration-commands.js +1 -1
  22. package/dist/src/cli/commands/register-registry-commands.js +1 -1
  23. package/dist/src/cli/commands/registry-project.js +1 -1
  24. package/dist/src/cli/commands/registry-setup-command.js +1 -1
  25. package/dist/src/cli/commands/registry.d.ts +15 -2
  26. package/dist/src/cli/commands/registry.js +1 -1
  27. package/dist/src/cli/commands/trace.d.ts +6 -23
  28. package/dist/src/cli/commands/trace.js +7 -5
  29. package/dist/src/cli/dev/command-options.d.ts +22 -0
  30. package/dist/src/cli/dev/diagnostic-dump.js +1 -1
  31. package/dist/src/cli/dev/diagnostic-sink.js +1 -1
  32. package/dist/src/cli/dev/local-server-cleanup.js +1 -1
  33. package/dist/src/cli/dev/local-server-process.js +1 -1
  34. package/dist/src/cli/dev/tui/blocks.js +1 -1
  35. package/dist/src/cli/dev/tui/clipboard.d.ts +17 -0
  36. package/dist/src/cli/dev/tui/clipboard.js +1 -0
  37. package/dist/src/cli/dev/tui/command-typeahead.js +1 -1
  38. package/dist/src/cli/dev/tui/prompt-commands.d.ts +3 -0
  39. package/dist/src/cli/dev/tui/prompt-commands.js +1 -1
  40. package/dist/src/cli/dev/tui/remote-auth.d.ts +6 -3
  41. package/dist/src/cli/dev/tui/remote-auth.js +1 -1
  42. package/dist/src/cli/dev/tui/remote-connection-probe.js +1 -1
  43. package/dist/src/cli/dev/tui/runner.d.ts +6 -0
  44. package/dist/src/cli/dev/tui/runner.js +1 -1
  45. package/dist/src/cli/dev/tui/stream-format.d.ts +22 -0
  46. package/dist/src/cli/dev/tui/stream-format.js +2 -2
  47. package/dist/src/cli/dev/tui/terminal-background.d.ts +23 -0
  48. package/dist/src/cli/dev/tui/terminal-background.js +1 -0
  49. package/dist/src/cli/dev/tui/terminal-renderer.d.ts +3 -0
  50. package/dist/src/cli/dev/tui/terminal-renderer.js +12 -12
  51. package/dist/src/cli/dev/tui/test/mock-terminal.js +3 -3
  52. package/dist/src/cli/dev/tui/traces/trace-content.d.ts +35 -0
  53. package/dist/src/cli/dev/tui/traces/trace-content.js +2 -0
  54. package/dist/src/cli/dev/tui/traces/trace-conversation.d.ts +63 -0
  55. package/dist/src/cli/dev/tui/traces/trace-conversation.js +2 -0
  56. package/dist/src/cli/dev/tui/traces/trace-store.d.ts +27 -0
  57. package/dist/src/cli/dev/tui/traces/trace-store.js +1 -0
  58. package/dist/src/cli/dev/tui/traces/trace-surfaces.d.ts +40 -0
  59. package/dist/src/cli/dev/tui/traces/trace-surfaces.js +1 -0
  60. package/dist/src/cli/dev/tui/traces/trace-view.d.ts +55 -0
  61. package/dist/src/cli/dev/tui/traces/trace-view.js +2 -0
  62. package/dist/src/cli/dev/tui/traces/trace-viewer-session.d.ts +54 -0
  63. package/dist/src/cli/dev/tui/traces/trace-viewer-session.js +1 -0
  64. package/dist/src/cli/dev/tui/traces/trace-viewer-state.d.ts +110 -0
  65. package/dist/src/cli/dev/tui/traces/trace-viewer-state.js +1 -0
  66. package/dist/src/cli/dev/tui/tui.js +1 -1
  67. package/dist/src/cli/invoke/invoke.js +1 -1
  68. package/dist/src/cli/invoke/result.js +1 -1
  69. package/dist/src/cli/run.d.ts +3 -0
  70. package/dist/src/cli/run.js +3 -3
  71. package/dist/src/cli/ui/alt-screen.d.ts +42 -0
  72. package/dist/src/cli/ui/alt-screen.js +1 -0
  73. package/dist/src/cli/ui/terminal-text.d.ts +4 -3
  74. package/dist/src/cli/ui/terminal-text.js +1 -1
  75. package/dist/src/client/index.d.ts +1 -1
  76. package/dist/src/client/open-stream.js +1 -1
  77. package/dist/src/client/session.d.ts +15 -1
  78. package/dist/src/client/session.js +1 -1
  79. package/dist/src/client/types.d.ts +9 -0
  80. package/dist/src/compiled/.vendor-stamp.json +3 -1
  81. package/dist/src/compiled/@agentclientprotocol/sdk/LICENSE +191 -0
  82. package/dist/src/compiled/@agentclientprotocol/sdk/index.d.ts +1835 -0
  83. package/dist/src/compiled/@agentclientprotocol/sdk/index.js +65 -0
  84. package/dist/src/compiled/@agentclientprotocol/sdk/jsonrpc.d.ts +603 -0
  85. package/dist/src/compiled/@agentclientprotocol/sdk/schema/guards.gen.d.ts +199 -0
  86. package/dist/src/compiled/@agentclientprotocol/sdk/schema/index.d.ts +51 -0
  87. package/dist/src/compiled/@agentclientprotocol/sdk/schema/types.gen.d.ts +6118 -0
  88. package/dist/src/compiled/@agentclientprotocol/sdk/stream.d.ts +35 -0
  89. package/dist/src/compiled/@photon-ai/chat-adapter-imessage/LICENSE +21 -0
  90. package/dist/src/compiled/@photon-ai/chat-adapter-imessage/_spectrum-core.d.ts +3 -0
  91. package/dist/src/compiled/@photon-ai/chat-adapter-imessage/_spectrum-imessage.d.ts +2 -0
  92. package/dist/src/compiled/@photon-ai/chat-adapter-imessage/index.d.ts +496 -0
  93. package/dist/src/compiled/@photon-ai/chat-adapter-imessage/index.js +137 -0
  94. package/dist/src/compiled/@vercel/sandbox/index.js +13 -107
  95. package/dist/src/compiled/_chunks/node/auth-BS3UoyvT.js +2 -0
  96. package/dist/src/compiled/_chunks/node/compat-Dm2n85Mx.js +1 -0
  97. package/dist/src/compiled/_chunks/node/schemas-DtQwuPdM.js +65 -0
  98. package/dist/src/compiled/_chunks/node/undici-DWL_MYmT.js +95 -0
  99. package/dist/src/compiled/_chunks/node/version-Cztrk7z6.js +1 -0
  100. package/dist/src/compiled/shadcn-registry/index.js +461 -893
  101. package/dist/src/compiler/artifacts.js +1 -1
  102. package/dist/src/compiler/extension-compatibility.js +1 -1
  103. package/dist/src/compiler/model-catalog.js +1 -1
  104. package/dist/src/compiler/normalize-sandbox.js +1 -1
  105. package/dist/src/compiler/workspace-resources.js +1 -1
  106. package/dist/src/context/keys.d.ts +3 -1
  107. package/dist/src/context/keys.js +1 -1
  108. package/dist/src/discover/project-source.js +1 -1
  109. package/dist/src/evals/cli/eval.js +2 -2
  110. package/dist/src/evals/loaders/json.js +1 -1
  111. package/dist/src/evals/loaders/yaml.js +1 -1
  112. package/dist/src/evals/runner/artifacts.js +1 -1
  113. package/dist/src/evals/runner/discover.js +1 -1
  114. package/dist/src/evals/runner/reporters/junit.js +1 -1
  115. package/dist/src/evals/session.js +1 -1
  116. package/dist/src/execution/delegated-parent-notification.js +1 -1
  117. package/dist/src/execution/delegated-parent-result.js +1 -1
  118. package/dist/src/execution/dispatch-runtime-actions-step.js +1 -1
  119. package/dist/src/execution/runtime-context.js +1 -1
  120. package/dist/src/execution/sandbox/bindings/docker-cli.js +1 -1
  121. package/dist/src/execution/sandbox/bindings/docker-templates.js +1 -1
  122. package/dist/src/execution/sandbox/bindings/just-bash-runtime.js +1 -1
  123. package/dist/src/execution/sandbox/bindings/just-bash.js +1 -1
  124. package/dist/src/execution/sandbox/bindings/local-backend-utils.js +1 -1
  125. package/dist/src/execution/sandbox/bindings/microsandbox-lifecycle.js +1 -1
  126. package/dist/src/execution/sandbox/bindings/microsandbox-metadata.js +1 -1
  127. package/dist/src/execution/sandbox/bindings/microsandbox-platform.js +1 -1
  128. package/dist/src/execution/sandbox/bindings/microsandbox-runtime.js +1 -1
  129. package/dist/src/execution/sandbox/bindings/microsandbox-templates.js +1 -1
  130. package/dist/src/execution/sandbox/development-cleanup.js +1 -1
  131. package/dist/src/execution/sandbox/glob-tool.js +3 -3
  132. package/dist/src/execution/sandbox/grep-tool.js +1 -1
  133. package/dist/src/execution/sandbox/read-file-tool.js +3 -3
  134. package/dist/src/execution/sandbox/require-sandbox.d.ts +3 -3
  135. package/dist/src/execution/sandbox/require-sandbox.js +1 -1
  136. package/dist/src/execution/sandbox/template-prewarm-lock.js +1 -1
  137. package/dist/src/execution/sandbox/write-file-tool.js +1 -1
  138. package/dist/src/execution/subagent-adapter-state.d.ts +39 -0
  139. package/dist/src/execution/subagent-adapter-state.js +1 -0
  140. package/dist/src/execution/subagent-adapter.d.ts +0 -34
  141. package/dist/src/execution/subagent-adapter.js +1 -1
  142. package/dist/src/execution/subagent-tool.d.ts +2 -1
  143. package/dist/src/execution/subagent-tool.js +1 -1
  144. package/dist/src/execution/workflow-steps.js +1 -1
  145. package/dist/src/harness/attachment-staging.js +1 -1
  146. package/dist/src/harness/instrumentation-lifecycle.d.ts +18 -0
  147. package/dist/src/harness/instrumentation-native-events.d.ts +3 -1
  148. package/dist/src/harness/instrumentation-native-events.js +1 -1
  149. package/dist/src/harness/parent-lineage.d.ts +11 -0
  150. package/dist/src/harness/parent-lineage.js +1 -0
  151. package/dist/src/harness/tool-loop.js +2 -2
  152. package/dist/src/internal/application/build-profile.js +1 -1
  153. package/dist/src/internal/application/build-workspace.js +1 -1
  154. package/dist/src/internal/application/cache-metadata.js +1 -1
  155. package/dist/src/internal/application/compiled-artifacts.js +8 -8
  156. package/dist/src/internal/application/optional-package-install.js +2 -2
  157. package/dist/src/internal/application/output-publication-artifacts.js +1 -1
  158. package/dist/src/internal/application/output-publication-journal.js +1 -1
  159. package/dist/src/internal/application/output-publication-lock.js +1 -1
  160. package/dist/src/internal/application/output-publication.js +1 -1
  161. package/dist/src/internal/application/package.js +1 -1
  162. package/dist/src/internal/application/paths.js +1 -1
  163. package/dist/src/internal/application/production-compiler-artifacts.js +1 -1
  164. package/dist/src/internal/application/tsconfig-dependencies.js +1 -1
  165. package/dist/src/internal/authored-asset-import-plugin.js +1 -1
  166. package/dist/src/internal/authored-module-loader.js +3 -3
  167. package/dist/src/internal/authored-package-tsconfig-paths.js +1 -1
  168. package/dist/src/internal/materialized-authored-modules.js +1 -1
  169. package/dist/src/internal/nitro/dev-runtime-artifacts-retention.js +1 -1
  170. package/dist/src/internal/nitro/dev-runtime-artifacts.js +1 -1
  171. package/dist/src/internal/nitro/dev-runtime-source-snapshot-copy.js +1 -1
  172. package/dist/src/internal/nitro/dev-runtime-source-snapshot.js +1 -1
  173. package/dist/src/internal/nitro/host/build-application.js +1 -1
  174. package/dist/src/internal/nitro/host/build-extension.js +1 -1
  175. package/dist/src/internal/nitro/host/build-vercel-agent-summary.js +1 -1
  176. package/dist/src/internal/nitro/host/configure-nitro-routes.js +3 -3
  177. package/dist/src/internal/nitro/host/copy-host-middleware.js +1 -1
  178. package/dist/src/internal/nitro/host/create-application-nitro.js +1 -1
  179. package/dist/src/internal/nitro/host/cron-handler-route.js +1 -1
  180. package/dist/src/internal/nitro/host/dev-authored-rebuild-coordinator.js +1 -1
  181. package/dist/src/internal/nitro/host/dev-authored-source-watcher.js +1 -1
  182. package/dist/src/internal/nitro/host/dev-host-fingerprint.js +1 -1
  183. package/dist/src/internal/nitro/host/dev-host-workspace.js +1 -1
  184. package/dist/src/internal/nitro/host/dev-server-http.js +1 -1
  185. package/dist/src/internal/nitro/host/dev-server-state.js +1 -1
  186. package/dist/src/internal/nitro/host/dev-workspace-extensions.js +1 -1
  187. package/dist/src/internal/nitro/host/extension-build-config.js +1 -1
  188. package/dist/src/internal/nitro/host/extension-declarations.js +2 -2
  189. package/dist/src/internal/nitro/host/extension-distribution.js +3 -3
  190. package/dist/src/internal/nitro/host/extension-state-usage.js +1 -1
  191. package/dist/src/internal/nitro/host/local-tracing-runtime-plugin.js +1 -1
  192. package/dist/src/internal/nitro/host/normalize-vercel-service-crons.js +1 -1
  193. package/dist/src/internal/nitro/host/start-development-server.js +2 -2
  194. package/dist/src/internal/nitro/host/start-production-server.js +2 -2
  195. package/dist/src/internal/nitro/host/types.d.ts +2 -0
  196. package/dist/src/internal/vercel/project-link.js +1 -1
  197. package/dist/src/internal/workflow/development-world-client.js +1 -1
  198. package/dist/src/internal/workflow-bundle/builder-support.js +6 -6
  199. package/dist/src/internal/workflow-bundle/builder.js +3 -3
  200. package/dist/src/internal/workflow-bundle/nitro-step-entry.js +2 -2
  201. package/dist/src/internal/workflow-bundle/vercel-workflow-output.js +1 -1
  202. package/dist/src/internal/workflow-bundle/workflow-builders.js +1 -1
  203. package/dist/src/packages/eve-catalog/src/index.js +1 -1
  204. package/dist/src/public/channels/chat-sdk/chatSdkChannel.d.ts +7 -0
  205. package/dist/src/public/channels/chat-sdk/chatSdkChannel.js +2 -2
  206. package/dist/src/public/channels/discord/discordChannel.js +1 -1
  207. package/dist/src/public/channels/discord/verify.js +1 -1
  208. package/dist/src/public/channels/github/auth.js +2 -2
  209. package/dist/src/public/channels/github/githubChannel.js +1 -1
  210. package/dist/src/public/channels/github/verify.js +1 -1
  211. package/dist/src/public/channels/linear/inbound.js +2 -2
  212. package/dist/src/public/channels/linear/linearChannel.js +1 -1
  213. package/dist/src/public/channels/linear/verify.js +1 -1
  214. package/dist/src/public/channels/photon/inboundContent.d.ts +4 -0
  215. package/dist/src/public/channels/photon/inboundContent.js +1 -0
  216. package/dist/src/public/channels/photon/index.d.ts +1 -0
  217. package/dist/src/public/channels/photon/index.js +1 -0
  218. package/dist/src/public/channels/photon/photonIMessageChannel.d.ts +54 -0
  219. package/dist/src/public/channels/photon/photonIMessageChannel.js +1 -0
  220. package/dist/src/public/channels/teams/teamsChannel.js +1 -1
  221. package/dist/src/public/channels/telegram/verify.js +1 -1
  222. package/dist/src/public/channels/twilio/twilioChannel.js +1 -1
  223. package/dist/src/public/models/openai/chatgpt/auth.js +1 -1
  224. package/dist/src/public/next/server.js +2 -2
  225. package/dist/src/public/next/vercel-output-config.js +1 -1
  226. package/dist/src/public/nuxt/dev-server.js +1 -1
  227. package/dist/src/public/nuxt/vercel-services.js +1 -1
  228. package/dist/src/public/sveltekit/dev-server.js +1 -1
  229. package/dist/src/public/sveltekit/vercel-json.js +1 -1
  230. package/dist/src/runtime/channels/registry.js +1 -1
  231. package/dist/src/runtime/framework-tools/file-state.js +1 -1
  232. package/dist/src/runtime/framework-tools/glob.js +1 -1
  233. package/dist/src/runtime/framework-tools/grep.js +1 -1
  234. package/dist/src/runtime/framework-tools/read-file.js +1 -1
  235. package/dist/src/runtime/framework-tools/write-file.js +1 -1
  236. package/dist/src/runtime/sandbox/keys.js +1 -1
  237. package/dist/src/runtime/workspace/seed-files.js +1 -1
  238. package/dist/src/setup/boxes/detect-ai-gateway.js +1 -1
  239. package/dist/src/setup/boxes/resolve-provisioning.js +1 -1
  240. package/dist/src/setup/connect-provisioning.d.ts +32 -0
  241. package/dist/src/setup/connect-provisioning.js +1 -0
  242. package/dist/src/setup/flows/login.js +1 -1
  243. package/dist/src/setup/flows/registry.js +1 -1
  244. package/dist/src/setup/index.d.ts +1 -0
  245. package/dist/src/setup/index.js +1 -1
  246. package/dist/src/setup/integrations/discord/api.d.ts +15 -0
  247. package/dist/src/setup/integrations/discord/api.js +1 -0
  248. package/dist/src/setup/integrations/discord/connect.d.ts +24 -0
  249. package/dist/src/setup/integrations/discord/connect.js +1 -0
  250. package/dist/src/setup/integrations/discord/setup.d.ts +19 -0
  251. package/dist/src/setup/integrations/discord/setup.js +8 -0
  252. package/dist/src/setup/integrations/photon/connect.d.ts +40 -0
  253. package/dist/src/setup/integrations/photon/connect.js +1 -0
  254. package/dist/src/setup/integrations/photon/management.d.ts +34 -0
  255. package/dist/src/setup/integrations/photon/management.js +1 -0
  256. package/dist/src/setup/integrations/photon/setup-flow.d.ts +39 -0
  257. package/dist/src/setup/integrations/photon/setup-flow.js +20 -0
  258. package/dist/src/setup/integrations/photon/setup.d.ts +3 -0
  259. package/dist/src/setup/integrations/photon/setup.js +1 -0
  260. package/dist/src/setup/integrations/registry.d.ts +6 -0
  261. package/dist/src/setup/integrations/registry.js +1 -0
  262. package/dist/src/setup/integrations/runner.d.ts +25 -0
  263. package/dist/src/setup/integrations/runner.js +1 -0
  264. package/dist/src/setup/integrations/{channels → shared}/environment.d.ts +3 -3
  265. package/dist/src/setup/integrations/shared/environment.js +1 -0
  266. package/dist/src/setup/integrations/shared/scaffold.d.ts +19 -0
  267. package/dist/src/setup/integrations/shared/scaffold.js +1 -0
  268. package/dist/src/setup/integrations/{channels → shared}/ui.d.ts +3 -3
  269. package/dist/src/setup/integrations/shared/ui.js +2 -0
  270. package/dist/src/setup/integrations/slack/setup.d.ts +16 -0
  271. package/dist/src/setup/integrations/slack/setup.js +1 -0
  272. package/dist/src/setup/integrations/types.d.ts +26 -0
  273. package/dist/src/setup/integrations/types.js +1 -0
  274. package/dist/src/setup/integrations/web/setup.d.ts +3 -0
  275. package/dist/src/setup/integrations/web/setup.js +1 -0
  276. package/dist/src/setup/package-manager.js +1 -1
  277. package/dist/src/setup/primitives/pm/pnpm.js +3 -3
  278. package/dist/src/setup/primitives/run-vercel.d.ts +2 -7
  279. package/dist/src/setup/primitives/run-vercel.js +1 -1
  280. package/dist/src/setup/project-resolution.js +1 -1
  281. package/dist/src/setup/prompter.js +1 -1
  282. package/dist/src/setup/registry-setup-client.d.ts +6 -2
  283. package/dist/src/setup/registry-setup-client.js +1 -1
  284. package/dist/src/setup/scaffold/create/add-to-project.js +1 -1
  285. package/dist/src/setup/scaffold/create/extension.js +1 -1
  286. package/dist/src/setup/scaffold/create/project.js +3 -10
  287. package/dist/src/setup/scaffold/files.js +1 -1
  288. package/dist/src/setup/scaffold/update/channels.js +2 -2
  289. package/dist/src/setup/scaffold/update/connections.js +1 -1
  290. package/dist/src/setup/scaffold/workspace-root.js +1 -1
  291. package/dist/src/setup/slack-connect-lifecycle.d.ts +2 -8
  292. package/dist/src/setup/slack-connect-lifecycle.js +1 -1
  293. package/dist/src/setup/state.d.ts +0 -12
  294. package/dist/src/setup/state.js +1 -1
  295. package/dist/src/setup/vercel-project-framework.js +1 -1
  296. package/dist/src/shared/guards.d.ts +2 -0
  297. package/dist/src/shared/guards.js +1 -1
  298. package/dist/src/shared/skill-package.js +1 -1
  299. package/dist/src/shared/skill-paths.d.ts +14 -4
  300. package/dist/src/shared/skill-paths.js +2 -2
  301. package/dist/src/shared/vercel-output-directory.js +1 -1
  302. package/dist/src/source-change/static-source-change.js +1 -1
  303. package/dist/src/svelte/index.js +1 -1
  304. package/dist/src/svelte/use-eve-agent.js +1 -1
  305. package/dist/src/tracing/agent-otel-content.d.ts +32 -0
  306. package/dist/src/tracing/agent-otel-content.js +4 -0
  307. package/dist/src/{harness → tracing}/agent-otel-provider.d.ts +10 -1
  308. package/dist/src/tracing/agent-otel-provider.js +2 -0
  309. package/dist/src/{harness → tracing}/agent-trace-context-store.d.ts +8 -1
  310. package/dist/src/tracing/agent-trace-context-store.js +1 -0
  311. package/dist/src/{harness → tracing}/agent-trace-span-processor.d.ts +5 -1
  312. package/dist/src/tracing/agent-trace-span-processor.js +1 -0
  313. package/dist/src/tracing/local-instrumentation-runtime.js +1 -0
  314. package/dist/src/tracing/local-trace-reader.d.ts +74 -0
  315. package/dist/src/tracing/local-trace-reader.js +1 -0
  316. package/dist/src/{harness → tracing}/local-trace-retention.js +1 -1
  317. package/dist/src/{harness → tracing}/local-trace-span-processor.js +1 -1
  318. package/dist/src/vue/index.js +1 -1
  319. package/dist/src/vue/use-eve-agent.js +1 -1
  320. package/docs/channels/chat-sdk.mdx +18 -1
  321. package/docs/channels/discord.mdx +30 -14
  322. package/docs/channels/meta.json +1 -0
  323. package/docs/channels/overview.mdx +1 -1
  324. package/docs/channels/photon.mdx +78 -0
  325. package/docs/concepts/default-harness.md +2 -0
  326. package/docs/guides/acp.md +91 -0
  327. package/docs/guides/client/streaming.mdx +24 -0
  328. package/docs/guides/dev-tui.md +20 -1
  329. package/docs/guides/instrumentation.md +8 -7
  330. package/docs/guides/meta.json +1 -0
  331. package/docs/reference/cli.md +12 -1
  332. package/docs/sandbox.mdx +1 -1
  333. package/package.json +8 -1
  334. package/dist/src/compiled/_chunks/node/auth-DMsLOrh7.js +0 -2
  335. package/dist/src/compiled/_chunks/node/version-BQBAL95V.js +0 -64
  336. package/dist/src/harness/agent-otel-provider.js +0 -1
  337. package/dist/src/harness/agent-trace-context-store.js +0 -1
  338. package/dist/src/harness/agent-trace-span-processor.js +0 -1
  339. package/dist/src/harness/local-instrumentation-runtime.js +0 -1
  340. package/dist/src/setup/integrations/channels/environment.js +0 -1
  341. package/dist/src/setup/integrations/channels/index.d.ts +0 -7
  342. package/dist/src/setup/integrations/channels/index.js +0 -1
  343. package/dist/src/setup/integrations/channels/runner.d.ts +0 -7
  344. package/dist/src/setup/integrations/channels/runner.js +0 -1
  345. package/dist/src/setup/integrations/channels/setup.d.ts +0 -130
  346. package/dist/src/setup/integrations/channels/setup.js +0 -2
  347. package/dist/src/setup/integrations/channels/slack.d.ts +0 -3
  348. package/dist/src/setup/integrations/channels/slack.js +0 -1
  349. package/dist/src/setup/integrations/channels/types.d.ts +0 -49
  350. package/dist/src/setup/integrations/channels/ui.js +0 -2
  351. package/dist/src/setup/integrations/channels/web.d.ts +0 -3
  352. package/dist/src/setup/integrations/channels/web.js +0 -1
  353. /package/dist/src/{setup/integrations/channels/types.js → cli/dev/command-options.js} +0 -0
  354. /package/dist/src/{harness → tracing}/local-instrumentation-runtime.d.ts +0 -0
  355. /package/dist/src/{harness → tracing}/local-trace-retention.d.ts +0 -0
  356. /package/dist/src/{harness → tracing}/local-trace-span-processor.d.ts +0 -0
@@ -1,11 +1,14 @@
1
1
  import { type SpanContext, type Tracer } from "#compiled/@opentelemetry/api/index.js";
2
2
  import type { InstrumentationContextRunner, InstrumentationProviderDefinition, InstrumentationTurnTerminalEvent } 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;
6
8
  readonly context: SpanContext;
7
- readonly pendingStarted: boolean;
8
9
  readonly rootSessionId: string;
10
+ readonly turnsInWindow: number;
11
+ readonly window: number;
9
12
  }
10
13
  export interface AgentTurnTraceState {
11
14
  readonly context: SpanContext;
@@ -36,6 +39,12 @@ export declare class InMemoryAgentTraceStateStore implements AgentTraceStateStor
36
39
  setTurn(sessionId: string, turnId: string, state: AgentTurnTraceState): void;
37
40
  }
38
41
  export interface AgentOtelInstrumentationInput {
42
+ /**
43
+ * Capture model prompts/responses and tool call inputs/outputs as span
44
+ * attributes. Content stays on the local machine — this provider only
45
+ * wires the dev-time local spool — but can be turned off per project.
46
+ */
47
+ readonly captureContent?: boolean;
39
48
  readonly frameworkVersion: string;
40
49
  readonly stateStore: AgentTraceStateStore;
41
50
  readonly tracer: Tracer;
@@ -0,0 +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;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 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=e.tracer.startSpan(`agent.turn`,{attributes:{"agent.framework.name":`eve`,"agent.framework.version":e.frameworkVersion,"agent.name":n.agentName,...parentLineageAttributes(t.parentLineage),"agent.root.session.id":t.rootSessionId,"agent.session.id":t.sessionId,"agent.session.window":n.window,"agent.turn.id":t.turnId,"agent.turn.sequence":t.sequence}},contextFromSpanContext(n.context));r.addEvent(`turn.started`),await e.stateStore.setSession(t.sessionId,{...n,turnsInWindow:n.turnsInWindow+1}),await e.stateStore.setTurn(t.sessionId,t.turnId,{context:r.spanContext(),rootSessionId:t.rootSessionId,sequence:t.sequence}),r.end()},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=e.tracer.startSpan(`agent.turn.terminal`,{attributes:{"agent.root.session.id":n.rootSessionId,"agent.session.id":t.sessionId,"agent.turn.id":t.turnId,"agent.turn.sequence":n.sequence}},contextFromSpanContext(n.context));n.terminal!==void 0&&(r.addEvent(n.terminal.type),n.terminal.type===`turn.failed`&&recordError(r,n.terminal.error)),r.addEvent(t.type),r.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 turnKey(e,t){return`${e}:${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{InMemoryAgentTraceStateStore,SESSION_WINDOW_TURN_LIMIT,createAgentOtelInstrumentation};
@@ -1,6 +1,13 @@
1
- import type { AgentSessionTraceState, AgentTraceStateStore, AgentTurnTraceState } from "#harness/agent-otel-provider.js";
1
+ import type { SpanContext } from "#compiled/@opentelemetry/api/index.js";
2
+ import type { AgentSessionTraceState, AgentTraceStateStore, AgentTurnTraceState } from "#tracing/agent-otel-provider.js";
2
3
  /** Keeps only framework trace state from an interrupted step's context changes. */
3
4
  export declare function preserveSerializedAgentTraceState(original: Record<string, unknown>, interrupted: Record<string, unknown>): Record<string, unknown>;
5
+ /**
6
+ * Reads a named session's trace window straight out of a serialized context,
7
+ * which {@link ContextAgentTraceStateStore} cannot do — its reads are scoped
8
+ * to the ambient session.
9
+ */
10
+ export declare function readSessionTraceContext(serializedContext: Readonly<Record<string, unknown>>, sessionId: string): SpanContext | undefined;
4
11
  /** Durable trace state backed by eve's serialized Workflow context. */
5
12
  export declare class ContextAgentTraceStateStore implements AgentTraceStateStore {
6
13
  deleteSession(sessionId: string): void;
@@ -0,0 +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)))return{context:e.context,rootSessionId:typeof e.rootSessionId==`string`?e.rootSessionId:``,sequence:typeof e.sequence==`number`?e.sequence:0,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 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};
@@ -9,7 +9,11 @@ export declare class AgentTraceSpanProcessor implements SpanProcessor {
9
9
  onEnd(span: unknown): void;
10
10
  /** Trace ids whose session is still open, so retention never evicts them. */
11
11
  activeTraceIds(): ReadonlySet<string>;
12
- /** Forgets one session's trace, reporting whether it owned one. */
12
+ /**
13
+ * Forgets every trace one root session owned, reporting whether it owned any.
14
+ * A subagent child owns none, so releasing one reports `false` and leaves the
15
+ * shared trace pinned until its root finishes.
16
+ */
13
17
  releaseSession(sessionId: string): boolean;
14
18
  shutdown(): Promise<void>;
15
19
  }
@@ -0,0 +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};
@@ -0,0 +1 @@
1
+ import{ContextAgentTraceStateStore}from"#tracing/agent-trace-context-store.js";import{getInstrumentationRuntime,registerInstrumentationRuntime}from"#harness/instrumentation-runtime.js";import{context,trace}from"#compiled/@opentelemetry/api/index.js";import{registerOTel}from"#compiled/@vercel/otel/index.js";import{createAgentOtelInstrumentation}from"#tracing/agent-otel-provider.js";import{AgentTraceSpanProcessor}from"#tracing/agent-trace-span-processor.js";import{createInstrumentationHooks}from"#harness/instrumentation-lifecycle.js";import{requestLocalTraceStorePrune,resolveLocalTraceRetentionSettings}from"#tracing/local-trace-retention.js";import{LocalTraceSpanProcessor}from"#tracing/local-trace-span-processor.js";function installLocalInstrumentationRuntime(t){let n=getInstrumentationRuntime();if(n!==void 0)return n;let r=resolveLocalTraceRetentionSettings(),i=new AgentTraceSpanProcessor(r.enabled?[new LocalTraceSpanProcessor(t.appRoot)]:[]);registerOTel({autoDetectResources:!1,instrumentations:[],propagators:[`none`],serviceName:t.serviceName,spanProcessors:[i]});let a=trace.getTracer(`eve.registration`).startSpan(`eve.otel.registration`),o=trace.setSpan(context.active(),a),s=context.with(o,()=>trace.getActiveSpan()===a);if(a.end(),!i.isAttached()||!s)throw Error(`eve could not register OpenTelemetry because another runtime already exists.`);let c=createAgentOtelInstrumentation({captureContent:process.env.EVE_TRACES_CONTENT!==`off`,frameworkVersion:t.frameworkVersion,stateStore:new ContextAgentTraceStateStore,tracer:trace.getTracer(`eve.agent`,t.frameworkVersion)}),l={events:{"session.completed":releaseSessionTrace,"session.failed":releaseSessionTrace}};return requestPrune(),registerInstrumentationRuntime({forceFlush:()=>i.forceFlush(),hooks:createInstrumentationHooks([c.hook,l]),runInContext:c.runInContext});async function releaseSessionTrace(e){await i.forceFlush(),i.releaseSession(e.sessionId)&&requestPrune()}function requestPrune(){r.enabled&&requestLocalTraceStorePrune({activeTraceIds:i.activeTraceIds(),appRoot:t.appRoot,maxAgeMs:r.maxAgeMs,maxTotalBytes:r.maxTotalBytes,retainCount:r.retainCount})}}export{installLocalInstrumentationRuntime};
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Reads the local trace spool written by {@link LocalTraceSpanProcessor}.
3
+ *
4
+ * The spool is the contract between the dev-time writer and every viewer
5
+ * (`eve traces`, the TUI trace viewer): one directory per trace under
6
+ * `.eve/traces/v1/<traceId>/segments/`, one immutable OTLP/JSON file per
7
+ * span. Parsing is defensive end to end — malformed or oversized segments
8
+ * are skipped so a partial write never breaks a view.
9
+ */
10
+ export interface LocalTraceSpan {
11
+ readonly attributes: Readonly<Record<string, unknown>>;
12
+ readonly endTimeNs: bigint;
13
+ readonly name: string;
14
+ readonly parentSpanId?: string;
15
+ readonly scope?: string;
16
+ readonly spanId: string;
17
+ readonly startTimeNs: bigint;
18
+ readonly statusCode: number;
19
+ readonly traceId: string;
20
+ }
21
+ export interface LocalTrace {
22
+ readonly agentName?: string;
23
+ readonly endTimeNs: bigint;
24
+ /** Session that opened the trace, which is the one the list shows. */
25
+ readonly sessionId?: string;
26
+ /**
27
+ * Every session recorded in the trace, opener first.
28
+ *
29
+ * A subagent child records into the window its parent had open, so one
30
+ * trace can hold several sessions and any of their ids resolves to it.
31
+ */
32
+ readonly sessionIds: readonly string[];
33
+ readonly spans: readonly LocalTraceSpan[];
34
+ readonly startTimeNs: bigint;
35
+ readonly traceId: string;
36
+ /** Zero-based session window this trace holds, when the spans record one. */
37
+ readonly window?: number;
38
+ }
39
+ /**
40
+ * Trace ids held by the spool, unordered. Empty when nothing has been written
41
+ * yet; any other read fault propagates.
42
+ */
43
+ export declare function listLocalTraceIds(appRoot: string): Promise<string[]>;
44
+ /**
45
+ * Instant one trace last received a span, or `undefined` once retention has
46
+ * pruned it. Reads the segments directory's mtime, so it stays cheap enough to
47
+ * poll a large spool without parsing any span.
48
+ */
49
+ export declare function readLocalTraceActivityMs(appRoot: string, traceId: string): Promise<number | undefined>;
50
+ /**
51
+ * Segment file names of one trace in read order, or `undefined` when the trace
52
+ * is gone. Segments are immutable and named for their span, so the order is
53
+ * stable across reads and a caller can treat names it has seen as parsed.
54
+ */
55
+ export declare function listLocalTraceSegments(appRoot: string, traceId: string): Promise<string[] | undefined>;
56
+ /**
57
+ * Spans held by one segment file. An oversized, unreadable, or malformed
58
+ * segment yields none, so a partial write never breaks a view.
59
+ */
60
+ export declare function readLocalTraceSegment(appRoot: string, traceId: string, fileName: string): Promise<LocalTraceSpan[]>;
61
+ /** Reads valid local traces, newest first, while ignoring malformed segments. */
62
+ export declare function listLocalTraces(appRoot: string): Promise<LocalTrace[]>;
63
+ /** Sorts spans into timeline order: start, then end, then a stable tiebreak. */
64
+ export declare function compareLocalTraceSpans(left: LocalTraceSpan, right: LocalTraceSpan): number;
65
+ /** Builds a trace from already-parsed spans, deriving summary fields. */
66
+ export declare function assembleLocalTrace(traceId: string, spans: readonly LocalTraceSpan[]): LocalTrace;
67
+ /**
68
+ * Extracts short human-facing details from a span's structural attributes
69
+ * (turn id, step index/attempt, action kind/name, model id) for one-line
70
+ * span labels. Raw values — callers sanitize for their output surface.
71
+ */
72
+ export declare function describeLocalTraceSpan(span: LocalTraceSpan): string[];
73
+ /** Parses one OTLP/JSON segment file into spans belonging to `expectedTraceId`. */
74
+ export declare function parseLocalTraceSegment(content: string, expectedTraceId: string): LocalTraceSpan[];
@@ -0,0 +1 @@
1
+ import{readFile,readdir,stat}from"node:fs/promises";import{join}from"node:path";import{resolveLocalTraceSchemaDirectory,resolveLocalTraceSegmentsDirectory}from"#tracing/local-trace-span-processor.js";const TRACE_ID_PATTERN=/^[0-9a-f]{32}$/u,SPAN_FILE_PATTERN=/^[0-9a-f]{16}\.otlp\.json$/u;async function listLocalTraceIds(e){let n;try{n=await readdir(resolveLocalTraceSchemaDirectory(e),{withFileTypes:!0})}catch(e){if(isMissing(e))return[];throw e}return n.filter(e=>e.isDirectory()&&TRACE_ID_PATTERN.test(e.name)).map(e=>e.name)}async function readLocalTraceActivityMs(e,t){try{return(await stat(resolveLocalTraceSegmentsDirectory(e,t))).mtimeMs}catch(e){if(isMissing(e))return;throw e}}async function listLocalTraceSegments(e,n){let r;try{r=await readdir(resolveLocalTraceSegmentsDirectory(e,n),{withFileTypes:!0})}catch(e){if(isMissing(e))return;throw e}return r.filter(e=>e.isFile()&&SPAN_FILE_PATTERN.test(e.name)).map(e=>e.name).sort((e,t)=>e.localeCompare(t))}async function readLocalTraceSegment(t,i,o){let s=join(resolveLocalTraceSegmentsDirectory(t,i),o),c;try{if((await stat(s)).size>8388608)return[];c=await readFile(s,`utf8`)}catch{return[]}return parseLocalTraceSegment(c,i)}async function listLocalTraces(e){let t=[];for(let n of await listLocalTraceIds(e)){let r=await readLocalTrace(e,n).catch(()=>void 0);r!==void 0&&t.push(r)}return t.sort((e,t)=>e.startTimeNs===t.startTimeNs?e.traceId.localeCompare(t.traceId):e.startTimeNs>t.startTimeNs?-1:1)}async function readLocalTrace(e,t){let n=await listLocalTraceSegments(e,t);if(n===void 0)return;let r=new Map;for(let i of n)for(let n of await readLocalTraceSegment(e,t,i))r.has(n.spanId)||r.set(n.spanId,n);if(r.size!==0)return assembleLocalTrace(t,[...r.values()])}function compareLocalTraceSpans(e,t){return e.startTimeNs===t.startTimeNs?e.endTimeNs===t.endTimeNs?e.name.localeCompare(t.name)||e.spanId.localeCompare(t.spanId):e.endTimeNs<t.endTimeNs?-1:1:e.startTimeNs<t.startTimeNs?-1:1}function assembleLocalTrace(e,t){let n=[...t].sort(compareLocalTraceSpans),r=n.map(e=>e.attributes),i=distinctAttributes(r,`agent.session.id`);return{agentName:firstAttribute(r,`agent.name`),endTimeNs:n.reduce((e,t)=>t.endTimeNs>e?t.endTimeNs:e,0n),sessionId:i[0],sessionIds:i,spans:n,startTimeNs:n.reduce((e,t)=>t.startTimeNs<e?t.startTimeNs:e,n[0].startTimeNs),traceId:e,window:firstNumberAttribute(r,`agent.session.window`)}}function describeLocalTraceSpan(e){let t=[],n=stringSpanAttribute(e,`agent.turn.id`),r=valueSpanAttribute(e,`agent.step.index`),i=valueSpanAttribute(e,`agent.step.attempt`),a=stringSpanAttribute(e,`agent.action.kind`),o=stringSpanAttribute(e,`agent.action.name`),s=stringSpanAttribute(e,`agent.model.id`)??stringSpanAttribute(e,`gen_ai.request.model`);return e.name===`agent.turn`&&n!==void 0&&t.push(n),e.name===`agent.step`&&r!==void 0&&t.push(`step ${String(r)}${i===void 0?``:`, attempt ${String(i)}`}`),e.name===`agent.action`&&o!==void 0&&t.push(`${a??`action`}: ${o}`),s!==void 0&&e.name.includes(`do`)&&t.push(`model ${s}`),t}function parseLocalTraceSegment(e,t){try{let n=JSON.parse(e);if(!isRecord(n)||!Array.isArray(n.resourceSpans))return[];let r=[];for(let e of n.resourceSpans)if(!(!isRecord(e)||!Array.isArray(e.scopeSpans)))for(let n of e.scopeSpans){if(!isRecord(n)||!Array.isArray(n.spans))continue;let e=isRecord(n.scope)&&typeof n.scope.name==`string`?n.scope.name:void 0;for(let i of n.spans){let n=parseLocalTraceSpan(i,t,e);n!==void 0&&r.push(n)}}return r}catch{return[]}}function parseLocalTraceSpan(e,t,n){if(!isRecord(e)||e.traceId!==t||typeof e.spanId!=`string`||!/^[0-9a-f]{16}$/u.test(e.spanId)||typeof e.name!=`string`)return;let r=parseNanos(e.startTimeUnixNano),i=parseNanos(e.endTimeUnixNano);if(!(r===void 0||i===void 0||i<r))return{attributes:parseAttributes(e.attributes),endTimeNs:i,name:e.name,parentSpanId:typeof e.parentSpanId==`string`&&/^[0-9a-f]{16}$/u.test(e.parentSpanId)?e.parentSpanId:void 0,scope:n,spanId:e.spanId,startTimeNs:r,statusCode:parseStatusCode(e.status),traceId:t}}function parseAttributes(e){if(!Array.isArray(e))return{};let t={};for(let n of e){if(!isRecord(n)||typeof n.key!=`string`||!isRecord(n.value))continue;let e=parseAnyValue(n.value);e!==void 0&&(t[n.key]=e)}return t}function parseAnyValue(e){for(let t of[`stringValue`,`boolValue`,`intValue`,`doubleValue`])if(t in e)return e[t];if(isRecord(e.arrayValue)&&Array.isArray(e.arrayValue.values))return e.arrayValue.values.filter(isRecord).map(e=>parseAnyValue(e))}function parseNanos(e){if(!(typeof e!=`string`&&typeof e!=`number`))try{let t=BigInt(e);return t>=0n&&t<=18446744073709551615n?t:void 0}catch{return}}function parseStatusCode(e){return isRecord(e)?typeof e.code==`number`?e.code:e.code===`STATUS_CODE_ERROR`?2:0:0}function firstAttribute(e,t){for(let n of e){let e=n[t];if(typeof e==`string`&&e.length>0)return e}}function firstNumberAttribute(e,t){for(let n of e){let e=n[t];if(typeof e==`number`)return e;if(typeof e==`bigint`)return Number(e)}}function distinctAttributes(e,t){let n=new Set;for(let r of e){let e=r[t];typeof e==`string`&&e.length>0&&n.add(e)}return[...n]}function stringSpanAttribute(e,t){let n=e.attributes[t];return typeof n==`string`?n:void 0}function valueSpanAttribute(e,t){let n=e.attributes[t];return typeof n==`string`||typeof n==`number`?n:void 0}function isMissing(e){return e.code===`ENOENT`}function isRecord(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}export{assembleLocalTrace,compareLocalTraceSpans,describeLocalTraceSpan,listLocalTraceIds,listLocalTraceSegments,listLocalTraces,parseLocalTraceSegment,readLocalTraceActivityMs,readLocalTraceSegment};
@@ -1 +1 @@
1
- import{createLogger,formatError}from"#internal/logging.js";import{join}from"node:path";import{readdir,rm,stat}from"node:fs/promises";import{resolveLocalTraceSchemaDirectory,resolveLocalTraceSegmentsDirectory}from"#harness/local-trace-span-processor.js";const log=createLogger(`harness.local-trace-retention`),LOCAL_TRACE_QUIESCENCE_MS=300*1e3,LOCAL_TRACE_MAX_AGE_MS=10080*60*1e3,LOCAL_TRACE_MAX_TOTAL_BYTES=512*1024*1024;function resolveLocalTraceRetentionSettings(e=process.env){return{enabled:!isDisabled(e.EVE_TRACES),maxAgeMs:readBound(e,`EVE_TRACES_MAX_AGE_MS`,LOCAL_TRACE_MAX_AGE_MS),maxTotalBytes:readBound(e,`EVE_TRACES_MAX_TOTAL_BYTES`,LOCAL_TRACE_MAX_TOTAL_BYTES),retainCount:readBound(e,`EVE_TRACES_RETAIN_COUNT`,20)}}async function pruneLocalTraceStore(e){let t=e.now??Date.now(),n=clampBound(e.maxAgeMs??LOCAL_TRACE_MAX_AGE_MS),r=clampBound(e.maxTotalBytes??LOCAL_TRACE_MAX_TOTAL_BYTES),a=clampCount(e.retainCount??20),o=await readStoredTraces(e.appRoot,t),s=[...o].sort((e,t)=>t.modifiedAtMs-e.modifiedAtMs),c=new Set(s.slice(0,a===!1?0:a)),l=new Set,u=o.reduce((e,t)=>e+t.byteSize,0),d=0,f=0,p=0;for(let a of s.toReversed()){let o=t-a.modifiedAtMs,s=e.activeTraceIds.has(a.traceId)||c.has(a)||o<=LOCAL_TRACE_QUIESCENCE_MS?void 0:n!==!1&&o>n?`maxAgeMs`:r!==!1&&u>r?`maxTotalBytes`:void 0;if(s===void 0){p+=1;continue}await rm(a.path,{force:!0,recursive:!0}),u-=a.byteSize,d+=a.byteSize,f+=1,l.add(s)}return{reasons:[...l],reclaimedBytes:d,removedTraces:f,retainedTraces:p}}const pruneRequest={input:{activeTraceIds:new Set,appRoot:``},requested:!1,running:void 0};function requestLocalTraceStorePrune(e){pruneRequest.input=e,pruneRequest.requested=!0,pruneRequest.running===void 0&&startPruning()}function startPruning(){pruneRequest.running=(async()=>{for(;pruneRequest.requested;)pruneRequest.requested=!1,report(await pruneLocalTraceStore(pruneRequest.input))})().catch(e=>{log.warn(`local trace retention failed`,{error:formatError(e)})}).finally(()=>{pruneRequest.running=void 0,pruneRequest.requested&&startPruning()})}function report(e){e.removedTraces!==0&&log.info(`pruned local traces`,{reasons:e.reasons.join(`,`),reclaimedBytes:e.reclaimedBytes,removedTraces:e.removedTraces,retainedTraces:e.retainedTraces})}async function readStoredTraces(e,t){let r=resolveLocalTraceSchemaDirectory(e),i=await readDirectoryEntries(r);return i===void 0?[]:(await Promise.all(i.filter(e=>e.isDirectory()).map(async i=>{let a=join(r,i.name),o=resolveLocalTraceSegmentsDirectory(e,i.name);await reapAbandonedTemporaryFiles(o,t);let c=await directoryMtime(o)??await directoryMtime(a);if(c!==void 0)return{byteSize:await directorySize(a),modifiedAtMs:c,path:a,traceId:i.name}}))).filter(e=>e!==void 0)}async function reapAbandonedTemporaryFiles(e,t){let r=await readDirectoryEntries(e);if(r!==void 0)for(let o of r){if(!o.isFile()||!o.name.includes(`.tmp-`))continue;let r=join(e,o.name);try{if(t-(await stat(r)).mtimeMs<=LOCAL_TRACE_QUIESCENCE_MS)continue;await rm(r,{force:!0})}catch{}}}async function directoryMtime(e){try{return(await stat(e)).mtimeMs}catch{return}}async function directorySize(e){let t=await readDirectoryEntries(e);if(t===void 0)return 0;let r=0;for(let i of t){let t=join(e,i.name);if(i.isDirectory()){r+=await directorySize(t);continue}try{r+=(await stat(t)).size}catch{}}return r}async function readDirectoryEntries(e){try{return await readdir(e,{withFileTypes:!0})}catch(e){if(e instanceof Error&&`code`in e&&(e.code===`ENOENT`||e.code===`ENOTDIR`))return;throw e}}function isDisabled(e){if(e===void 0)return!1;let t=e.trim().toLowerCase();return t===`off`||t===`false`||t===`0`}function readBound(e,t,n){let r=e[t];if(r===void 0)return n;let i=r.trim().toLowerCase();if(i===`off`||i===`false`)return!1;let a=Number(i);return!Number.isFinite(a)||a<0?(log.warn(`ignoring invalid local trace retention value`,{fallback:n,name:t,value:r}),n):a}function clampBound(e){return e!==!1&&Math.max(0,e)}function clampCount(e){return e!==!1&&Math.max(0,Math.trunc(e))}export{pruneLocalTraceStore,requestLocalTraceStorePrune,resolveLocalTraceRetentionSettings};
1
+ import{readdir,rm,stat}from"node:fs/promises";import{createLogger,formatError}from"#internal/logging.js";import{join}from"node:path";import{resolveLocalTraceSchemaDirectory,resolveLocalTraceSegmentsDirectory}from"#tracing/local-trace-span-processor.js";const log=createLogger(`harness.local-trace-retention`),LOCAL_TRACE_QUIESCENCE_MS=300*1e3,LOCAL_TRACE_MAX_AGE_MS=10080*60*1e3,LOCAL_TRACE_MAX_TOTAL_BYTES=512*1024*1024;function resolveLocalTraceRetentionSettings(e=process.env){return{enabled:!isDisabled(e.EVE_TRACES),maxAgeMs:readBound(e,`EVE_TRACES_MAX_AGE_MS`,LOCAL_TRACE_MAX_AGE_MS),maxTotalBytes:readBound(e,`EVE_TRACES_MAX_TOTAL_BYTES`,LOCAL_TRACE_MAX_TOTAL_BYTES),retainCount:readBound(e,`EVE_TRACES_RETAIN_COUNT`,20)}}async function pruneLocalTraceStore(e){let n=e.now??Date.now(),r=clampBound(e.maxAgeMs??LOCAL_TRACE_MAX_AGE_MS),i=clampBound(e.maxTotalBytes??LOCAL_TRACE_MAX_TOTAL_BYTES),a=clampCount(e.retainCount??20),o=await readStoredTraces(e.appRoot,n),s=[...o].sort((e,t)=>t.modifiedAtMs-e.modifiedAtMs),c=new Set(s.slice(0,a===!1?0:a)),l=new Set,u=o.reduce((e,t)=>e+t.byteSize,0),d=0,f=0,p=0;for(let a of s.toReversed()){let o=n-a.modifiedAtMs,s=e.activeTraceIds.has(a.traceId)||c.has(a)||o<=LOCAL_TRACE_QUIESCENCE_MS?void 0:r!==!1&&o>r?`maxAgeMs`:i!==!1&&u>i?`maxTotalBytes`:void 0;if(s===void 0){p+=1;continue}await rm(a.path,{force:!0,recursive:!0}),u-=a.byteSize,d+=a.byteSize,f+=1,l.add(s)}return{reasons:[...l],reclaimedBytes:d,removedTraces:f,retainedTraces:p}}const pruneRequest={input:{activeTraceIds:new Set,appRoot:``},requested:!1,running:void 0};function requestLocalTraceStorePrune(e){pruneRequest.input=e,pruneRequest.requested=!0,pruneRequest.running===void 0&&startPruning()}function startPruning(){pruneRequest.running=(async()=>{for(;pruneRequest.requested;)pruneRequest.requested=!1,report(await pruneLocalTraceStore(pruneRequest.input))})().catch(e=>{log.warn(`local trace retention failed`,{error:formatError(e)})}).finally(()=>{pruneRequest.running=void 0,pruneRequest.requested&&startPruning()})}function report(e){e.removedTraces!==0&&log.info(`pruned local traces`,{reasons:e.reasons.join(`,`),reclaimedBytes:e.reclaimedBytes,removedTraces:e.removedTraces,retainedTraces:e.retainedTraces})}async function readStoredTraces(e,t){let n=resolveLocalTraceSchemaDirectory(e),r=await readDirectoryEntries(n);return r===void 0?[]:(await Promise.all(r.filter(e=>e.isDirectory()).map(async r=>{let i=join(n,r.name),o=resolveLocalTraceSegmentsDirectory(e,r.name);await reapAbandonedTemporaryFiles(o,t);let c=await directoryMtime(o)??await directoryMtime(i);if(c!==void 0)return{byteSize:await directorySize(i),modifiedAtMs:c,path:i,traceId:r.name}}))).filter(e=>e!==void 0)}async function reapAbandonedTemporaryFiles(e,r){let i=await readDirectoryEntries(e);if(i!==void 0)for(let o of i){if(!o.isFile()||!o.name.includes(`.tmp-`))continue;let i=join(e,o.name);try{if(r-(await stat(i)).mtimeMs<=LOCAL_TRACE_QUIESCENCE_MS)continue;await rm(i,{force:!0})}catch{}}}async function directoryMtime(e){try{return(await stat(e)).mtimeMs}catch{return}}async function directorySize(e){let t=await readDirectoryEntries(e);if(t===void 0)return 0;let r=0;for(let i of t){let t=join(e,i.name);if(i.isDirectory()){r+=await directorySize(t);continue}try{r+=(await stat(t)).size}catch{}}return r}async function readDirectoryEntries(t){try{return await readdir(t,{withFileTypes:!0})}catch(e){if(e instanceof Error&&`code`in e&&(e.code===`ENOENT`||e.code===`ENOTDIR`))return;throw e}}function isDisabled(e){if(e===void 0)return!1;let t=e.trim().toLowerCase();return t===`off`||t===`false`||t===`0`}function readBound(e,t,n){let r=e[t];if(r===void 0)return n;let i=r.trim().toLowerCase();if(i===`off`||i===`false`)return!1;let a=Number(i);return!Number.isFinite(a)||a<0?(log.warn(`ignoring invalid local trace retention value`,{fallback:n,name:t,value:r}),n):a}function clampBound(e){return e!==!1&&Math.max(0,e)}function clampCount(e){return e!==!1&&Math.max(0,Math.trunc(e))}export{pruneLocalTraceStore,requestLocalTraceStorePrune,resolveLocalTraceRetentionSettings};
@@ -1 +1 @@
1
- import{createLogger,formatError}from"#internal/logging.js";import{join}from"node:path";import{mkdir}from"node:fs/promises";import{JsonTraceSerializer}from"#compiled/@opentelemetry/otlp-transformer/index.js";import{atomicWriteFile}from"#shared/atomic-write-file.js";const log=createLogger(`harness.local-trace-span-processor`);function resolveLocalTraceStoreDirectory(e){return join(e,`.eve`,`traces`)}function resolveLocalTraceSchemaDirectory(e){return join(resolveLocalTraceStoreDirectory(e),`v1`)}function resolveLocalTraceSegmentsDirectory(e,t){return join(resolveLocalTraceSchemaDirectory(e),t,`segments`)}var LocalTraceSpanProcessor=class{#e;#t=Promise.resolve();#n=!1;constructor(e){this.#e=e}forceFlush(){return this.#t}onStart(){}onEnd(e){if(!isReadableSpan(e))return;let{spanId:n,traceId:r}=e.spanContext();if(!isHexId(r,32)||!isHexId(n,16))return;let i=JsonTraceSerializer.serializeRequest([e]);i!==void 0&&(this.#t=this.#t.then(async()=>{let e=resolveLocalTraceSegmentsDirectory(this.#e,r);await mkdir(e,{recursive:!0}),await atomicWriteFile(join(e,`${n}.otlp.json`),i)}).catch(e=>{this.#n||(this.#n=!0,log.warn(`local trace persistence failed`,{error:formatError(e)}))}))}shutdown(){return this.forceFlush()}};function isReadableSpan(e){return typeof e==`object`&&!!e&&`attributes`in e&&`spanContext`in e&&typeof e.spanContext==`function`}function isHexId(e,t){return e.length===t&&/^[0-9a-f]+$/u.test(e)}export{LocalTraceSpanProcessor,resolveLocalTraceSchemaDirectory,resolveLocalTraceSegmentsDirectory};
1
+ import{mkdir}from"node:fs/promises";import{createLogger,formatError}from"#internal/logging.js";import{join}from"node:path";import{atomicWriteFile}from"#shared/atomic-write-file.js";import{JsonTraceSerializer}from"#compiled/@opentelemetry/otlp-transformer/index.js";const log=createLogger(`harness.local-trace-span-processor`);function resolveLocalTraceStoreDirectory(e){return join(e,`.eve`,`traces`)}function resolveLocalTraceSchemaDirectory(e){return join(resolveLocalTraceStoreDirectory(e),`v1`)}function resolveLocalTraceSegmentsDirectory(e,t){return join(resolveLocalTraceSchemaDirectory(e),t,`segments`)}var LocalTraceSpanProcessor=class{#e;#t=Promise.resolve();#n=!1;constructor(e){this.#e=e}forceFlush(){return this.#t}onStart(){}onEnd(t){if(!isReadableSpan(t))return;let{spanId:n,traceId:r}=t.spanContext();if(!isHexId(r,32)||!isHexId(n,16))return;let i=JsonTraceSerializer.serializeRequest([t]);i!==void 0&&(this.#t=this.#t.then(async()=>{let t=resolveLocalTraceSegmentsDirectory(this.#e,r);await mkdir(t,{recursive:!0}),await atomicWriteFile(join(t,`${n}.otlp.json`),i)}).catch(e=>{this.#n||(this.#n=!0,log.warn(`local trace persistence failed`,{error:formatError(e)}))}))}shutdown(){return this.forceFlush()}};function isReadableSpan(e){return typeof e==`object`&&!!e&&`attributes`in e&&`spanContext`in e&&typeof e.spanContext==`function`}function isHexId(e,t){return e.length===t&&/^[0-9a-f]+$/u.test(e)}export{LocalTraceSpanProcessor,resolveLocalTraceSchemaDirectory,resolveLocalTraceSegmentsDirectory};
@@ -1,3 +1,3 @@
1
- import { n as defaultMessageReducer, t as useEveAgent } from "../chunks/use-eve-agent-CyDt3Lny.js";
1
+ import { n as defaultMessageReducer, t as useEveAgent } from "../chunks/use-eve-agent-bKJbH0k4.js";
2
2
 
3
3
  export { defaultMessageReducer, useEveAgent };
@@ -1,3 +1,3 @@
1
- import { t as useEveAgent } from "../chunks/use-eve-agent-CyDt3Lny.js";
1
+ import { t as useEveAgent } from "../chunks/use-eve-agent-bKJbH0k4.js";
2
2
 
3
3
  export { useEveAgent };
@@ -97,7 +97,24 @@ bot.onNewMention(async (thread, message) => {
97
97
  });
98
98
  ```
99
99
 
100
- `options` accepts `{ thread, auth?, title?, mode?, callback?, adapterName? }`. `title` sets the eve session's display title without changing the model message; `auth` attaches an authenticated principal to the turn.
100
+ `options` accepts `{ thread, auth?, title?, mode?, callback?, adapterName?, turnPolicy? }`. `title` sets the eve session's display title without changing the model message; `auth` attaches an authenticated principal to the turn.
101
+
102
+ ### Experimental steering
103
+
104
+ By default, a message sent while an eve turn is active waits for the next turn. Pass `turnPolicy: "experimental-steer"` to cancel the active turn before sending the new message:
105
+
106
+ ```ts
107
+ bot.onSubscribedMessage(async (thread, message) => {
108
+ await send(message.text, {
109
+ thread,
110
+ turnPolicy: "experimental-steer",
111
+ });
112
+ });
113
+ ```
114
+
115
+ This is cancellation-backed steering: the interrupted turn emits `turn.cancelled`, and the replacement message starts a new turn with a new turn ID. Partial output and completed side effects from the interrupted turn are not rolled back. If no turn is active, the message is sent normally. Use the default `turnPolicy: "queue"` when every turn should finish in order.
116
+
117
+ This policy controls overlapping eve turns. Chat SDK's separate `concurrency` option controls overlapping webhook handlers; use `concurrency: "concurrent"` when each inbound message should reach the experimental steering path immediately.
101
118
 
102
119
  ### Delivery
103
120
 
@@ -4,27 +4,43 @@ description: "Reach your agent from Discord HTTP Interactions, including slash c
4
4
  type: integration
5
5
  ---
6
6
 
7
- The Discord channel wires your agent into Discord's HTTP Interactions, including slash and application commands, message components, and modal submissions. Discord enforces a three-second ACK deadline, so the channel verifies the Ed25519 signature headers, acknowledges the command right away, and runs the eve work in the background. See [Channels](./overview) for the contract this builds on.
7
+ The Discord channel wires your agent into Discord's HTTP Interactions, including slash and application commands, message components, and modal submissions. Discord enforces a three-second ACK deadline, so the channel acknowledges the command right away and runs the eve work in the background. Credentials and inbound request verification run through [Vercel Connect](../guides/auth-and-route-protection), so Discord's bot token stays out of your environment and Connect verifies Discord's signature before forwarding an interaction to eve. See [Channels](./overview) for the contract this builds on.
8
8
 
9
- ## Add the channel
9
+ ## Set up Discord
10
10
 
11
- ```ts title="agent/channels/discord.ts"
12
- import { discordChannel } from "eve/channels/discord";
11
+ Run the guided setup from your eve project:
13
12
 
14
- export default discordChannel();
13
+ ```bash
14
+ pnpm eve add channel/discord
15
15
  ```
16
16
 
17
- ```bash
18
- DISCORD_PUBLIC_KEY=... # verifies X-Signature-Ed25519 + X-Signature-Timestamp
19
- DISCORD_APPLICATION_ID=... # edits the deferred response and sends followups
20
- DISCORD_BOT_TOKEN=... # proactive messages + fallback + typing indicators
17
+ The setup guides you through creating a Discord application and bot, then:
18
+
19
+ - validates the bot token;
20
+ - creates a Vercel Connect client and attaches `/eve/v1/discord` as its trigger destination;
21
+ - registers an application command with a required `message` option;
22
+ - configures the Discord application's Interactions Endpoint URL;
23
+ - scaffolds the channel with Connect-managed credentials; and
24
+ - prints the bot installation URL.
25
+
26
+ The command defaults to `/ask` with the description **Ask the eve agent**. You can edit both during setup. Discord global commands can take up to an hour to appear after registration.
27
+
28
+ The generated channel looks like this:
29
+
30
+ ```ts title="agent/channels/discord.ts"
31
+ import { connectDiscordCredentials } from "@vercel/connect/eve";
32
+ import { discordChannel } from "eve/channels/discord";
33
+
34
+ export default discordChannel({
35
+ credentials: connectDiscordCredentials("discord/my-agent"),
36
+ });
21
37
  ```
22
38
 
23
- To skip env vars, pass the same values through `credentials: { applicationId, botToken, publicKey }`. The route is `POST /eve/v1/discord` by default. Paste that public URL into your Discord application's Interactions Endpoint URL.
39
+ The route is `POST /eve/v1/discord` by default. Connect resolves the application ID and bot token lazily and verifies forwarded interactions with same-project Vercel OIDC.
24
40
 
25
- ## Register a command
41
+ ### Configure Discord manually
26
42
 
27
- Registering commands is on you, not the channel. Use Discord's API or the Developer Portal. A string option named `message` lines up with eve's default prompt extraction:
43
+ If you do not use the guided Connect setup, register a command with Discord's API or the Developer Portal. A string option named `message` lines up with eve's default prompt extraction:
28
44
 
29
45
  ```bash
30
46
  curl -X PUT "https://discord.com/api/v10/applications/$DISCORD_APPLICATION_ID/commands" \
@@ -33,7 +49,7 @@ curl -X PUT "https://discord.com/api/v10/applications/$DISCORD_APPLICATION_ID/co
33
49
  "options":[{"name":"message","description":"What should the agent do?","type":3,"required":true}]}]'
34
50
  ```
35
51
 
36
- Use guild commands during development for faster propagation.
52
+ Then configure the public `https://…/eve/v1/discord` route as the application's Interactions Endpoint URL. Pass `credentials: { applicationId, botToken, publicKey }` to `discordChannel`, or set the corresponding `DISCORD_APPLICATION_ID`, `DISCORD_BOT_TOKEN`, and `DISCORD_PUBLIC_KEY` environment variables.
37
53
 
38
54
  ## How the channel handles messages
39
55
 
@@ -74,7 +90,7 @@ HITL renders as Discord components. Confirmations and options become buttons, `d
74
90
 
75
91
  ### Proactive sessions
76
92
 
77
- Start a session without an inbound interaction through `receive(discord, { message, target, auth })` from a schedule `run` handler, or `args.receive(discord, ...)` from another channel. The proactive target shape is `{ channelId, conversationId?, initialMessage? }`. Either path needs `DISCORD_BOT_TOKEN`.
93
+ Start a session without an inbound interaction through `receive(discord, { message, target, auth })` from a schedule `run` handler, or `args.receive(discord, ...)` from another channel. The proactive target shape is `{ channelId, conversationId?, initialMessage? }`. Either path needs a bot token, supplied by Connect or `DISCORD_BOT_TOKEN`.
78
94
 
79
95
  ### Attachments
80
96
 
@@ -4,6 +4,7 @@
4
4
  "overview",
5
5
  "eve",
6
6
  "slack",
7
+ "photon",
7
8
  "discord",
8
9
  "teams",
9
10
  "telegram",
@@ -28,7 +28,7 @@ agent/
28
28
  intake.ts
29
29
  ```
30
30
 
31
- Install a built-in channel with `eve add channel/slack` or `eve add channel/web`. You can also author the file by hand.
31
+ Install a channel from the registry with `eve add channel/photon-imessage`, `eve add channel/slack`, or `eve add channel/web`. You can also author the file by hand.
32
32
 
33
33
  ## The eve HTTP channel (default)
34
34
 
@@ -0,0 +1,78 @@
1
+ ---
2
+ title: Photon
3
+ description: Connect an eve agent to iMessage through Photon.
4
+ ---
5
+
6
+ Use `photonIMessageChannel` to receive and reply to iMessages through a Photon project.
7
+
8
+ Run `eve add channel/photon-imessage` to create or use a Photon project and register
9
+ your phone number. It then asks whether to configure Vercel Connect or portable
10
+ credentials. With Vercel Connect, eve creates the connector and configures
11
+ Photon’s webhook through Connect. The channel resolves credentials lazily when
12
+ the adapter first initializes:
13
+
14
+ ```ts title="agent/channels/photon.ts"
15
+ import { connectPhotonCredentials } from "@vercel/connect/eve";
16
+ import { photonIMessageChannel } from "eve/channels/photon";
17
+
18
+ export default photonIMessageChannel({
19
+ credentials: connectPhotonCredentials("photon/my-agent"),
20
+ });
21
+ ```
22
+
23
+ The default webhook route is `/eve/v1/photon`. The channel verifies forwarded
24
+ webhooks with same-project Vercel OIDC by default, marks accepted messages as
25
+ read, and continues the same eve session for every message in an iMessage
26
+ conversation. A new accepted message cooperatively cancels an active turn and
27
+ steers its replacement turn.
28
+
29
+ Customize inbound dispatch with `onMessage`. Return `null` to ignore a message:
30
+
31
+ ```ts
32
+ export default photonIMessageChannel({
33
+ credentials: connectPhotonCredentials("photon/my-agent"),
34
+ onMessage(_ctx, message) {
35
+ if (message.author.isBot) return null;
36
+ return {
37
+ auth: null,
38
+ context: [`The sender is ${message.author.fullName}.`],
39
+ };
40
+ },
41
+ });
42
+ ```
43
+
44
+ Set `route` to override the webhook path or `webhookVerifier` to use a different
45
+ trusted-forwarder verifier.
46
+
47
+ ## Other hosts
48
+
49
+ For a host without Vercel Connect, choose **Use portable credentials** during
50
+ `eve add channel/photon-imessage`. eve scaffolds the channel and writes
51
+ `IMESSAGE_PROJECT_ID` and `IMESSAGE_PROJECT_SECRET` to `.env.local`.
52
+
53
+ After deploying the agent:
54
+
55
+ 1. Create a Photon webhook for your public `https://…/eve/v1/photon` URL.
56
+ 2. Copy its signing secret into `IMESSAGE_WEBHOOK_SECRET`.
57
+ 3. Set `IMESSAGE_PROJECT_ID`, `IMESSAGE_PROJECT_SECRET`, and
58
+ `IMESSAGE_WEBHOOK_SECRET` in the host’s encrypted environment variables.
59
+
60
+ To configure the channel by hand, use lazy environment-backed credentials:
61
+
62
+ ```ts title="agent/channels/photon.ts"
63
+ import { photonIMessageChannel } from "eve/channels/photon";
64
+
65
+ export default photonIMessageChannel({
66
+ async credentials() {
67
+ const projectId = process.env.IMESSAGE_PROJECT_ID;
68
+ const projectSecret = process.env.IMESSAGE_PROJECT_SECRET;
69
+ if (!projectId || !projectSecret) throw new Error("Photon project credentials are required.");
70
+ return { projectId, projectSecret };
71
+ },
72
+ webhookSecret: process.env.IMESSAGE_WEBHOOK_SECRET,
73
+ });
74
+ ```
75
+
76
+ For direct Photon webhooks, pass `webhookSecret` or set
77
+ `IMESSAGE_WEBHOOK_SECRET`; the signing secret takes precedence over the default
78
+ OIDC verifier.
@@ -41,6 +41,8 @@ The shell and file tools (`bash`, `read_file`, `write_file`, `glob`, `grep`) run
41
41
  | `load_skill` | Pull an on-demand [skill](../skills)'s instructions into the current turn. Present only when the agent declares skills. | App runtime |
42
42
  | `connection_search` | Discover tools across declared [connections](../connections); matched tools become directly callable. Present only when the agent declares connections. | App runtime |
43
43
 
44
+ The model-facing file tools accept absolute paths and paths beginning with `$HOME/`. eve resolves `$HOME` against the sandbox before invoking non-shell file operations, so packaged skill references such as `$HOME/.agents/skills/<skill>/references/...` work consistently across `read_file`, `write_file`, `glob`, and `grep`.
45
+
44
46
  Notes:
45
47
 
46
48
  - **`agent`** is available only in the root session. Its child uses the root's instructions, tools, connections, and sandbox, but starts with fresh conversation history and fresh [state](../guides/state). The child receives neither `agent` nor `Workflow`; declared subagents do not receive the built-in `agent` either. See [Subagents](../subagents).
@@ -0,0 +1,91 @@
1
+ ---
2
+ title: "Use eve through ACP"
3
+ description: "Use local or deployed eve agents from Agent Client Protocol clients."
4
+ ---
5
+
6
+ Agent Client Protocol (ACP) clients can launch an authored eve application as a local subprocess. eve serves stable ACP v1 over stdio while its normal development server remains the execution runtime.
7
+
8
+ ```sh
9
+ eve acp
10
+ ```
11
+
12
+ Without a URL, the client starts one process from the eve application root. It supervises a local development server, and closing the ACP connection stops that owned server. To bridge ACP to a deployed eve agent, pass its URL:
13
+
14
+ ```sh
15
+ eve acp https://agent.example.com
16
+ ```
17
+
18
+ For a recognized Vercel deployment, eve verifies the exact origin and resolves a short-lived project-scoped OIDC token from the local Vercel session. If login or a Trusted Sources change is required, run `eve dev <url>` and complete `/vc:login` before launching ACP. `VERCEL_AUTOMATION_BYPASS_SECRET` remains available for deployments configured with a Protection Bypass for Automation token.
19
+
20
+ ## Configure Zed
21
+
22
+ Open the eve application root as the Zed workspace. In **Agent Settings → External Agents**, add a custom agent:
23
+
24
+ ```json
25
+ {
26
+ "agent_servers": {
27
+ "eve-local": {
28
+ "type": "custom",
29
+ "command": "pnpm",
30
+ "args": ["exec", "eve", "acp"],
31
+ "env": {}
32
+ }
33
+ }
34
+ }
35
+ ```
36
+
37
+ Use an absolute command path if Zed cannot find `pnpm` in its environment. The workspace must be the same directory as the eve application root; eve rejects a different `session/new.cwd` instead of running the wrong application.
38
+
39
+ Disable Zed project MCP servers for this agent. The initial eve adapter does not accept client-provided MCP servers.
40
+
41
+ ## Supported behavior
42
+
43
+ ACP clients receive:
44
+
45
+ - streamed assistant text and reasoning;
46
+ - tool-call requests and results;
47
+ - one-time tool approval and denial requests;
48
+ - fixed-choice and freeform questions when the client supports ACP form elicitation;
49
+ - cooperative turn cancellation;
50
+ - independent concurrent ACP sessions;
51
+ - session closure and process cleanup.
52
+
53
+ Development rebuilds retain normal eve semantics. In-flight work stays pinned to its generation, and the next turn uses the newest successful generation.
54
+
55
+ ## Security and capability limits
56
+
57
+ ACP mode does not give the agent access to the editor's host filesystem or terminal. `session/new.cwd` identifies the eve application being launched; it is not mounted into the agent sandbox.
58
+
59
+ The initial adapter does not support:
60
+
61
+ - a deployed ACP HTTP or WebSocket endpoint;
62
+ - ACP authentication (remote bridges use the deployed eve agent's existing HTTP authentication);
63
+ - ACP v2;
64
+ - client filesystem or terminal methods;
65
+ - client-provided MCP servers;
66
+ - images, audio, files, or embedded resources in prompts;
67
+ - session loading, listing, resumption, or durable ACP IDs across process restarts;
68
+ - ACP model or mode configuration.
69
+
70
+ The agent continues to use the connections, tools, credentials, and sandbox policy authored in the eve application. Prompt text and ACP metadata never establish an authenticated end-user principal.
71
+
72
+ ## Diagnose a connection
73
+
74
+ ACP reserves stdout for newline-delimited JSON-RPC. eve sends compilation output, server logs, and diagnostics to stderr so they cannot corrupt the protocol stream.
75
+
76
+ For a quick headless smoke test, run an ACP client such as `acpx` from the application root. `acpx` launches the ACP process itself; do not start `eve acp` separately.
77
+
78
+ ```sh
79
+ npx acpx@latest \
80
+ --agent 'pnpm exec eve acp' \
81
+ exec 'Reply with exactly: ACP works'
82
+ ```
83
+
84
+ When testing from the eve source checkout, use an authored fixture rather than the monorepo root, which does not provide an `eve` executable:
85
+
86
+ ```sh
87
+ cd apps/fixtures/weather-agent
88
+ npx acpx@latest --agent 'pnpm exec eve acp' exec 'Reply with exactly: ACP works'
89
+ ```
90
+
91
+ If startup fails, inspect the ACP client's logs together with eve's stderr. A non-empty client MCP configuration, a mismatched working directory, and unsupported prompt content produce explicit protocol errors before model work begins.
@@ -180,6 +180,30 @@ Because a tail-relative cursor cannot be bounded, `follow: false` throws when co
180
180
 
181
181
  `stream()` throws if the session has no `sessionId`, because there's no stream to attach to before the first send.
182
182
 
183
+ ## Snapshot a session
184
+
185
+ Use `snapshot()` when you need the complete event prefix and its matching cursor
186
+ as one value, such as when hydrating a server-rendered chat:
187
+
188
+ ```ts
189
+ const session = client.session({ sessionId, streamIndex: 0 });
190
+ const snapshot = await session.snapshot();
191
+
192
+ // snapshot.events contains event indexes 0 through snapshot.session.streamIndex - 1.
193
+ ```
194
+
195
+ The read pins the durable tail when it opens, just like
196
+ `stream({ follow: false })`. Events written afterward are not included, and
197
+ `snapshot.session.streamIndex` is the exact index from which a live consumer can
198
+ continue. `snapshot()` always reads from index `0`; use a bounded stream directly
199
+ when you only need the unread suffix from an existing cursor.
200
+
201
+ Unlike `stream()`, `snapshot()` does not advance or reset the originating
202
+ `ClientSession`. Its returned session includes a continuation token only when
203
+ the captured prefix ends in `session.waiting`, or when completed sessions are
204
+ explicitly preserved by the client. Active and terminal snapshots remain
205
+ inspectable at their returned stream cursor but cannot accept another turn.
206
+
183
207
  ## Abort a request
184
208
 
185
209
  Pass an `AbortSignal` to cancel the POST or stream. Aborting is local transport cancellation: turns are resumable across disconnects, so detaching never stops the server-side turn — it keeps running and remains attachable by index. To stop the turn itself, POST the session's [cancel route](../../channels/eve#routes) and watch the stream settle with `turn.cancelled` followed by `session.waiting`.