eve 0.69.0 → 0.70.1

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 (361) hide show
  1. package/CHANGELOG.md +49 -0
  2. package/dist/src/acp/adapter.js +1 -1
  3. package/dist/src/channel/task-card.d.ts +3 -3
  4. package/dist/src/channel/task-card.js +1 -1
  5. package/dist/src/channel/types.d.ts +18 -0
  6. package/dist/src/chunks/{use-eve-agent-Dab2MnT2.js → use-eve-agent-CJQeE7-t.js} +1873 -1236
  7. package/dist/src/chunks/{use-eve-agent-D_5129A9.js → use-eve-agent-DdemtY6C.js} +1874 -1234
  8. package/dist/src/cli/dev/command.js +1 -1
  9. package/dist/src/cli/dev/console-records-preload.d.ts +1 -0
  10. package/dist/src/cli/dev/console-records-preload.js +1 -0
  11. package/dist/src/cli/dev/console-records.d.ts +17 -0
  12. package/dist/src/cli/dev/console-records.js +3 -0
  13. package/dist/src/cli/dev/diagnostic-sink.d.ts +1 -0
  14. package/dist/src/cli/dev/local-server-process.js +1 -1
  15. package/dist/src/cli/dev/tui/blocks.d.ts +2 -1
  16. package/dist/src/cli/dev/tui/blocks.js +3 -3
  17. package/dist/src/cli/dev/tui/conversation-view.d.ts +54 -0
  18. package/dist/src/cli/dev/tui/conversation-view.js +1 -0
  19. package/dist/src/cli/dev/tui/flow-drawer.d.ts +5 -2
  20. package/dist/src/cli/dev/tui/flow-drawer.js +1 -1
  21. package/dist/src/cli/dev/tui/log-display-mode.d.ts +4 -10
  22. package/dist/src/cli/dev/tui/log-display-mode.js +1 -1
  23. package/dist/src/cli/dev/tui/message-queue.d.ts +7 -63
  24. package/dist/src/cli/dev/tui/message-queue.js +3 -1
  25. package/dist/src/cli/dev/tui/prompt-commands.d.ts +7 -7
  26. package/dist/src/cli/dev/tui/prompt-commands.js +1 -1
  27. package/dist/src/cli/dev/tui/question-panel.d.ts +3 -1
  28. package/dist/src/cli/dev/tui/question-panel.js +1 -1
  29. package/dist/src/cli/dev/tui/runner.d.ts +58 -195
  30. package/dist/src/cli/dev/tui/runner.js +3 -3
  31. package/dist/src/cli/dev/tui/task-activity.d.ts +11 -24
  32. package/dist/src/cli/dev/tui/task-activity.js +1 -1
  33. package/dist/src/cli/dev/tui/task-records.d.ts +17 -0
  34. package/dist/src/cli/dev/tui/task-records.js +1 -0
  35. package/dist/src/cli/dev/tui/terminal-renderer.d.ts +15 -37
  36. package/dist/src/cli/dev/tui/terminal-renderer.js +10 -13
  37. package/dist/src/cli/dev/tui/terminal-tool-part.d.ts +2 -0
  38. package/dist/src/cli/dev/tui/terminal-tool-part.js +1 -0
  39. package/dist/src/cli/dev/tui/test/fake-eve-server.d.ts +34 -0
  40. package/dist/src/cli/dev/tui/test/fake-eve-server.js +1 -0
  41. package/dist/src/cli/dev/tui/test/index.d.ts +1 -0
  42. package/dist/src/cli/dev/tui/test/index.js +1 -1
  43. package/dist/src/cli/dev/tui/tool-block-groups.js +1 -1
  44. package/dist/src/cli/dev/tui/tool-presentation.d.ts +1 -0
  45. package/dist/src/cli/dev/tui/tool-presentation.js +1 -1
  46. package/dist/src/cli/dev/tui/tool-rows.d.ts +1 -0
  47. package/dist/src/cli/dev/tui/tool-rows.js +2 -2
  48. package/dist/src/cli/dev/tui/transcript-parts.d.ts +81 -0
  49. package/dist/src/cli/dev/tui/transcript-parts.js +3 -0
  50. package/dist/src/cli/dev/tui/transcript.d.ts +47 -0
  51. package/dist/src/cli/dev/tui/transcript.js +1 -0
  52. package/dist/src/cli/dev/tui/tui.js +1 -1
  53. package/dist/src/cli/dev/tui/turn-clock.d.ts +11 -26
  54. package/dist/src/cli/dev/tui/turn-clock.js +1 -1
  55. package/dist/src/cli/dev/tui/types.d.ts +2 -4
  56. package/dist/src/cli/dev/ui-options.js +1 -1
  57. package/dist/src/client/agent-stream-follower.d.ts +26 -0
  58. package/dist/src/client/agent-stream-follower.js +1 -0
  59. package/dist/src/client/authorization-message-parts.js +1 -1
  60. package/dist/src/client/conversation-client.d.ts +40 -0
  61. package/dist/src/client/conversation-client.js +1 -0
  62. package/dist/src/client/conversation-reducer.d.ts +29 -0
  63. package/dist/src/client/conversation-reducer.js +1 -0
  64. package/dist/src/client/conversation-state.d.ts +110 -0
  65. package/dist/src/client/conversation-state.js +1 -0
  66. package/dist/src/client/eve-agent-projection.d.ts +24 -7
  67. package/dist/src/client/eve-agent-projection.js +1 -1
  68. package/dist/src/client/eve-agent-store-helpers.d.ts +21 -2
  69. package/dist/src/client/eve-agent-store-helpers.js +2 -2
  70. package/dist/src/client/eve-agent-store-state.d.ts +15 -3
  71. package/dist/src/client/eve-agent-store.d.ts +10 -1
  72. package/dist/src/client/eve-agent-store.js +1 -1
  73. package/dist/src/client/index.d.ts +4 -1
  74. package/dist/src/client/index.js +1 -1
  75. package/dist/src/client/message-reducer-primitives.d.ts +1 -2
  76. package/dist/src/client/message-reducer-primitives.js +1 -1
  77. package/dist/src/client/message-reducer-types.d.ts +9 -2
  78. package/dist/src/client/message-reducer.js +1 -1
  79. package/dist/src/client/message-response.js +1 -1
  80. package/dist/src/client/message-run-parts.d.ts +10 -6
  81. package/dist/src/client/message-run-parts.js +1 -1
  82. package/dist/src/client/optimistic-message-submissions.d.ts +6 -4
  83. package/dist/src/client/optimistic-message-submissions.js +1 -1
  84. package/dist/src/client/reducer.d.ts +5 -1
  85. package/dist/src/client/session-turn-dispatch.d.ts +15 -0
  86. package/dist/src/client/session-turn-dispatch.js +1 -0
  87. package/dist/src/client/session-utils.d.ts +27 -10
  88. package/dist/src/client/session-utils.js +1 -1
  89. package/dist/src/client/session.js +1 -1
  90. package/dist/src/client/types.d.ts +2 -1
  91. package/dist/src/compiled/.vendor-stamp.json +2 -2
  92. package/dist/src/compiled/{gray-matter → js-yaml}/LICENSE +2 -2
  93. package/dist/src/compiled/js-yaml/index.d.ts +12 -0
  94. package/dist/src/compiled/js-yaml/index.js +34 -0
  95. package/dist/src/compiler/extension-compatibility.d.ts +18 -18
  96. package/dist/src/compiler/extension-compatibility.js +1 -1
  97. package/dist/src/compiler/load-binding-namespace.js +1 -1
  98. package/dist/src/context/keys.d.ts +5 -2
  99. package/dist/src/context/keys.js +1 -1
  100. package/dist/src/context/provider.d.ts +5 -9
  101. package/dist/src/context/run-step.d.ts +4 -4
  102. package/dist/src/context/run-step.js +1 -1
  103. package/dist/src/context/serialize.d.ts +5 -1
  104. package/dist/src/context/serialize.js +1 -1
  105. package/dist/src/evals/loaders/yaml.js +1 -1
  106. package/dist/src/evals/runner/derive-run-facts.js +1 -1
  107. package/dist/src/evals/runner/execute-task.js +1 -1
  108. package/dist/src/evals/session.js +2 -2
  109. package/dist/src/evals/types.d.ts +16 -0
  110. package/dist/src/eve-channel/index.js +1 -1
  111. package/dist/src/execution/agent-sessions/context.d.ts +4 -2
  112. package/dist/src/execution/agent-sessions/context.js +1 -1
  113. package/dist/src/execution/agent-sessions/steps.js +1 -1
  114. package/dist/src/execution/cancelled-model-call-batch.js +1 -1
  115. package/dist/src/execution/coordination-dispatch-shared.d.ts +6 -4
  116. package/dist/src/execution/coordination-dispatch-shared.js +1 -1
  117. package/dist/src/execution/create-session-step.d.ts +4 -2
  118. package/dist/src/execution/create-session-step.js +1 -1
  119. package/dist/src/execution/durable-session-store.d.ts +10 -4
  120. package/dist/src/execution/durable-session-store.js +1 -1
  121. package/dist/src/execution/dynamic-workflow/tool.js +1 -1
  122. package/dist/src/execution/legacy-remote-agent/protocol.d.ts +8 -0
  123. package/dist/src/execution/legacy-remote-agent/protocol.js +1 -1
  124. package/dist/src/execution/legacy-session/completion-step.d.ts +2 -0
  125. package/dist/src/execution/legacy-session/completion-step.js +1 -1
  126. package/dist/src/execution/legacy-session/interrupt-step.js +1 -1
  127. package/dist/src/execution/legacy-session/prepare-step.d.ts +1 -0
  128. package/dist/src/execution/legacy-session/prepare-step.js +1 -1
  129. package/dist/src/execution/legacy-session/snapshot.d.ts +8 -4
  130. package/dist/src/execution/legacy-session/snapshot.js +1 -1
  131. package/dist/src/execution/legacy-session/turn-workflow.js +1 -1
  132. package/dist/src/execution/proxied-deliver-step.js +1 -1
  133. package/dist/src/execution/publish-session-events.d.ts +27 -7
  134. package/dist/src/execution/publish-session-events.js +1 -1
  135. package/dist/src/execution/reconcile-session-continuation-token.d.ts +2 -2
  136. package/dist/src/execution/runtime-context.js +1 -1
  137. package/dist/src/execution/session/active-turn.d.ts +97 -0
  138. package/dist/src/execution/session/active-turn.js +1 -0
  139. package/dist/src/execution/session/checkpoint-migrations.d.ts +23 -0
  140. package/dist/src/execution/session/checkpoint-migrations.js +1 -0
  141. package/dist/src/execution/session/entry.js +1 -1
  142. package/dist/src/execution/session/finalization.js +1 -1
  143. package/dist/src/execution/session/handoff-steps.d.ts +24 -5
  144. package/dist/src/execution/session/handoff-steps.js +1 -1
  145. package/dist/src/execution/session/handoff.d.ts +10 -6
  146. package/dist/src/execution/session/handoff.js +1 -1
  147. package/dist/src/execution/session/input-queue.d.ts +19 -13
  148. package/dist/src/execution/session/input-queue.js +1 -1
  149. package/dist/src/execution/session/next-input.d.ts +2 -10
  150. package/dist/src/execution/session/next-input.js +1 -1
  151. package/dist/src/execution/session/pending-turn-state.d.ts +2 -0
  152. package/dist/src/execution/session/pending-turn-state.js +1 -1
  153. package/dist/src/execution/session/program.d.ts +2 -0
  154. package/dist/src/execution/session/program.js +1 -1
  155. package/dist/src/execution/session/state-cursor.d.ts +22 -16
  156. package/dist/src/execution/session/state-cursor.js +1 -1
  157. package/dist/src/execution/session/state-delta.d.ts +8 -1
  158. package/dist/src/execution/session/state-delta.js +1 -1
  159. package/dist/src/execution/session/turn-event-handler.js +1 -1
  160. package/dist/src/execution/session/turn-step-result.js +1 -1
  161. package/dist/src/execution/session/turn-step-types.d.ts +20 -4
  162. package/dist/src/execution/session/turn-step.js +1 -1
  163. package/dist/src/execution/session/turn-waiting-step.js +1 -1
  164. package/dist/src/execution/session/turn.d.ts +22 -3
  165. package/dist/src/execution/session/turn.js +1 -1
  166. package/dist/src/execution/session.d.ts +5 -5
  167. package/dist/src/execution/session.js +2 -2
  168. package/dist/src/execution/settle-cancelled-turn-step.d.ts +5 -4
  169. package/dist/src/execution/settle-cancelled-turn-step.js +1 -1
  170. package/dist/src/execution/tasks/start.d.ts +2 -2
  171. package/dist/src/execution/tasks/task-id-input.d.ts +1 -1
  172. package/dist/src/execution/tasks/task-id-input.js +1 -1
  173. package/dist/src/execution/terminal-session-completion-step.d.ts +2 -0
  174. package/dist/src/execution/terminal-session-completion-step.js +1 -1
  175. package/dist/src/execution/terminal-session-failure-step.d.ts +2 -0
  176. package/dist/src/execution/terminal-session-failure-step.js +1 -1
  177. package/dist/src/execution/tools/agent-router-workflow.js +1 -1
  178. package/dist/src/execution/tools/connection-target.d.ts +5 -0
  179. package/dist/src/execution/tools/connection-target.js +1 -1
  180. package/dist/src/execution/tools/connection-tools.js +2 -2
  181. package/dist/src/execution/tools/workflow/start.d.ts +3 -3
  182. package/dist/src/harness/authorization.d.ts +15 -2
  183. package/dist/src/harness/authorization.js +1 -1
  184. package/dist/src/harness/cancelled-turn-emission.d.ts +2 -1
  185. package/dist/src/harness/cancelled-turn-emission.js +1 -1
  186. package/dist/src/harness/coordination.d.ts +5 -3
  187. package/dist/src/harness/emission.d.ts +5 -2
  188. package/dist/src/harness/emission.js +1 -1
  189. package/dist/src/harness/held-requests.d.ts +18 -0
  190. package/dist/src/harness/held-requests.js +1 -0
  191. package/dist/src/harness/hitl/approval-input-requests.d.ts +16 -0
  192. package/dist/src/harness/hitl/approval-input-requests.js +1 -1
  193. package/dist/src/harness/input-extraction.js +1 -1
  194. package/dist/src/harness/input-requests.d.ts +0 -4
  195. package/dist/src/harness/input-requests.js +1 -1
  196. package/dist/src/harness/model-call-error.js +1 -1
  197. package/dist/src/harness/proxy-input-requests.d.ts +4 -4
  198. package/dist/src/harness/session-limit-enforcement.js +1 -1
  199. package/dist/src/harness/stale-input-responses.js +1 -1
  200. package/dist/src/harness/tool-loop.js +2 -2
  201. package/dist/src/harness/turn-tag-state.d.ts +2 -0
  202. package/dist/src/harness/turn-tag-state.js +1 -1
  203. package/dist/src/harness/types.d.ts +23 -11
  204. package/dist/src/instrumentation/channel-delivery.d.ts +1 -0
  205. package/dist/src/instrumentation/channel-delivery.js +1 -1
  206. package/dist/src/instrumentation/lifecycle.d.ts +4 -0
  207. package/dist/src/instrumentation/memory.d.ts +2 -0
  208. package/dist/src/instrumentation/memory.js +1 -1
  209. package/dist/src/instrumentation/native-events.d.ts +1 -0
  210. package/dist/src/instrumentation/native-events.js +1 -1
  211. package/dist/src/instrumentation/runtime.d.ts +4 -3
  212. package/dist/src/instrumentation/runtime.js +1 -1
  213. package/dist/src/instrumentation/session-init.js +1 -1
  214. package/dist/src/internal/application/package.js +1 -1
  215. package/dist/src/internal/authored-module-loader.d.ts +14 -6
  216. package/dist/src/internal/authored-module-loader.js +1 -1
  217. package/dist/src/internal/authored-package-boundary.d.ts +1 -1
  218. package/dist/src/internal/authored-package-boundary.js +1 -1
  219. package/dist/src/internal/bundler/extension-mount-plugin.js +1 -1
  220. package/dist/src/internal/helpers/frontmatter.d.ts +24 -0
  221. package/dist/src/internal/helpers/frontmatter.js +1 -0
  222. package/dist/src/internal/helpers/markdown.js +1 -3
  223. package/dist/src/internal/nitro/host/create-application-nitro.js +1 -1
  224. package/dist/src/internal/nitro/host/nitro-bundler-config.js +1 -1
  225. package/dist/src/internal/node-esm-compat-banner.js +1 -1
  226. package/dist/src/internal/workflow-bundle/dynamic-remote-agent-transform.js +1 -1
  227. package/dist/src/internal/workflow-bundle/dynamic-tool-ast-references.d.ts +27 -1
  228. package/dist/src/internal/workflow-bundle/dynamic-tool-ast-references.js +1 -1
  229. package/dist/src/internal/workflow-bundle/dynamic-tool-transform.js +2 -2
  230. package/dist/src/protocol/message.d.ts +41 -3
  231. package/dist/src/protocol/message.js +2 -2
  232. package/dist/src/public/channels/slack/action-status.d.ts +2 -2
  233. package/dist/src/public/channels/slack/action-status.js +1 -1
  234. package/dist/src/public/channels/slack/approval-cards.d.ts +15 -0
  235. package/dist/src/public/channels/slack/approval-cards.js +2 -0
  236. package/dist/src/public/channels/slack/auth.d.ts +2 -0
  237. package/dist/src/public/channels/slack/auth.js +1 -1
  238. package/dist/src/public/channels/slack/connections.d.ts +15 -11
  239. package/dist/src/public/channels/slack/connections.js +1 -1
  240. package/dist/src/public/channels/slack/defaults.d.ts +1 -15
  241. package/dist/src/public/channels/slack/defaults.js +3 -4
  242. package/dist/src/public/channels/slack/hitl.js +1 -1
  243. package/dist/src/public/channels/slack/inbound.d.ts +10 -2
  244. package/dist/src/public/channels/slack/inbound.js +1 -1
  245. package/dist/src/public/channels/slack/index.d.ts +2 -0
  246. package/dist/src/public/channels/slack/index.js +1 -1
  247. package/dist/src/public/channels/slack/input-response.js +1 -1
  248. package/dist/src/public/channels/slack/interaction-cards.js +1 -1
  249. package/dist/src/public/channels/slack/interactions.js +1 -1
  250. package/dist/src/public/channels/slack/limits.d.ts +5 -3
  251. package/dist/src/public/channels/slack/private-approval-delivery.js +1 -1
  252. package/dist/src/public/channels/slack/renderers.d.ts +1 -1
  253. package/dist/src/public/channels/slack/renderers.js +1 -1
  254. package/dist/src/public/channels/slack/reply-delivery.d.ts +72 -0
  255. package/dist/src/public/channels/slack/reply-delivery.js +1 -0
  256. package/dist/src/public/channels/slack/sign-in-cancel.d.ts +20 -0
  257. package/dist/src/public/channels/slack/sign-in-cancel.js +1 -0
  258. package/dist/src/public/channels/slack/slackChannel.d.ts +15 -0
  259. package/dist/src/public/channels/slack/slackChannel.js +1 -1
  260. package/dist/src/public/channels/slack/task-card.js +1 -1
  261. package/dist/src/public/channels/teams/defaults.d.ts +1 -1
  262. package/dist/src/public/channels/teams/defaults.js +2 -2
  263. package/dist/src/public/definitions/channel.d.ts +1 -0
  264. package/dist/src/public/definitions/channel.js +1 -1
  265. package/dist/src/public/definitions/state.d.ts +2 -0
  266. package/dist/src/public/definitions/state.js +1 -1
  267. package/dist/src/public/next/index.js +1 -1
  268. package/dist/src/public/next/server.d.ts +2 -0
  269. package/dist/src/public/next/server.js +1 -2
  270. package/dist/src/public/nuxt/module.d.ts +6 -0
  271. package/dist/src/public/nuxt/module.js +1 -1
  272. package/dist/src/react/index.d.ts +3 -0
  273. package/dist/src/react/index.js +1 -1
  274. package/dist/src/react/use-eve-agent.d.ts +7 -5
  275. package/dist/src/react/use-eve-agent.js +1 -1
  276. package/dist/src/runtime/connections/openapi-spec.d.ts +1 -4
  277. package/dist/src/runtime/connections/openapi-spec.js +1 -1
  278. package/dist/src/runtime/connections/scoped-authorization.d.ts +2 -0
  279. package/dist/src/runtime/connections/scoped-authorization.js +1 -1
  280. package/dist/src/setup/boxes/deploy-project.js +1 -1
  281. package/dist/src/setup/integrations/web/setup.js +6 -2
  282. package/dist/src/setup/scaffold/create/project.js +1 -1
  283. package/dist/src/setup/scaffold/create/web-template.d.ts +5 -5
  284. package/dist/src/setup/scaffold/create/web-template.js +61 -35
  285. package/dist/src/setup/vercel-project-framework.js +1 -1
  286. package/dist/src/shared/display-name.d.ts +15 -0
  287. package/dist/src/shared/display-name.js +1 -0
  288. package/dist/src/shared/framework-eve-server.d.ts +43 -0
  289. package/dist/src/shared/framework-eve-server.js +2 -0
  290. package/dist/src/shared/token-usage.d.ts +2 -0
  291. package/dist/src/shared/token-usage.js +1 -1
  292. package/dist/src/shared/trace-root.d.ts +8 -0
  293. package/dist/src/shared/trace-root.js +1 -0
  294. package/dist/src/subagents/callback-route.js +1 -1
  295. package/dist/src/subagents/hitl-proxy.d.ts +3 -3
  296. package/dist/src/subagents/hitl-proxy.js +1 -1
  297. package/dist/src/subagents/invocation.d.ts +3 -1
  298. package/dist/src/subagents/parent-notification.d.ts +7 -7
  299. package/dist/src/subagents/parent-notification.js +1 -1
  300. package/dist/src/subagents/tool.js +1 -1
  301. package/dist/src/svelte/index.d.ts +3 -0
  302. package/dist/src/svelte/index.js +2 -2
  303. package/dist/src/svelte/use-eve-agent.d.ts +7 -4
  304. package/dist/src/svelte/use-eve-agent.js +1 -1
  305. package/dist/src/tools/provided/ask-question-workflow.js +1 -1
  306. package/dist/src/tools/provided/load-skill.js +1 -1
  307. package/dist/src/tools/provided/sleep-workflow.js +1 -1
  308. package/dist/src/tracing/agent-action-instrumentation.js +1 -1
  309. package/dist/src/tracing/agent-approval-instrumentation.js +1 -1
  310. package/dist/src/tracing/agent-memory-instrumentation.js +1 -1
  311. package/dist/src/tracing/agent-otel-attributes.d.ts +6 -0
  312. package/dist/src/tracing/agent-otel-attributes.js +1 -1
  313. package/dist/src/tracing/agent-otel-provider.js +2 -2
  314. package/dist/src/tracing/agent-otel-runtime-context.d.ts +1 -1
  315. package/dist/src/tracing/agent-otel-runtime-context.js +1 -1
  316. package/dist/src/tracing/agent-otel-session-context.js +1 -1
  317. package/dist/src/tracing/agent-span-contract.js +1 -1
  318. package/dist/src/tracing/agent-tool-instrumentation.js +1 -1
  319. package/dist/src/tracing/agent-trace-context-codec.d.ts +4 -0
  320. package/dist/src/tracing/agent-trace-context-codec.js +1 -1
  321. package/dist/src/tracing/agent-trace-span-processor.js +1 -1
  322. package/dist/src/tracing/agent-trace-state.d.ts +3 -0
  323. package/dist/src/tracing/conversation-context.d.ts +10 -0
  324. package/dist/src/tracing/conversation-context.js +1 -1
  325. package/dist/src/tracing/otel-registration.js +1 -1
  326. package/dist/src/vue/index.d.ts +3 -0
  327. package/dist/src/vue/index.js +2 -2
  328. package/dist/src/vue/use-eve-agent.d.ts +7 -3
  329. package/dist/src/vue/use-eve-agent.js +1 -1
  330. package/docs/channels/slack.mdx +60 -13
  331. package/docs/concepts/built-in-tools.md +3 -2
  332. package/docs/concepts/execution-model-and-durability.mdx +3 -1
  333. package/docs/concepts/sessions-runs-and-streaming.md +4 -4
  334. package/docs/connections/overview.mdx +9 -3
  335. package/docs/evals/reporters.mdx +4 -0
  336. package/docs/extensions.md +15 -3
  337. package/docs/guides/client/streaming.mdx +7 -6
  338. package/docs/guides/deployment/vercel.mdx +2 -1
  339. package/docs/guides/dev-tui.md +17 -17
  340. package/docs/guides/dynamic-capabilities.md +1 -1
  341. package/docs/guides/frontend/nuxt.mdx +24 -4
  342. package/docs/guides/frontend/overview.mdx +44 -38
  343. package/docs/guides/frontend/use-eve-agent-svelte.mdx +4 -10
  344. package/docs/guides/frontend/use-eve-agent-vue.mdx +4 -10
  345. package/docs/guides/instrumentation/otel.mdx +24 -6
  346. package/docs/guides/remote-agents.md +26 -8
  347. package/docs/reference/cli.md +4 -4
  348. package/docs/tools/human-in-the-loop.md +4 -4
  349. package/docs/tools/overview.mdx +1 -1
  350. package/docs/tools/tasks.md +8 -8
  351. package/package.json +2 -2
  352. package/dist/src/cli/dev/tui/steering-stream.d.ts +0 -15
  353. package/dist/src/cli/dev/tui/steering-stream.js +0 -1
  354. package/dist/src/cli/dev/tui/subagent-pump.d.ts +0 -134
  355. package/dist/src/cli/dev/tui/subagent-pump.js +0 -1
  356. package/dist/src/compiled/gray-matter/index.d.ts +0 -62
  357. package/dist/src/compiled/gray-matter/index.js +0 -48
  358. package/dist/src/internal/helpers/gray-matter.d.ts +0 -25
  359. package/dist/src/internal/helpers/gray-matter.js +0 -1
  360. package/dist/src/public/nuxt/dev-server.d.ts +0 -25
  361. package/dist/src/public/nuxt/dev-server.js +0 -1
@@ -684,28 +684,22 @@ function isTurnFailureEvent(event) {
684
684
  //#endregion
685
685
  //#region src/client/session-utils.ts
686
686
  function summarizeTurnEvents(events) {
687
+ const segment = new TurnSegment();
687
688
  let boundary;
688
689
  let failure;
689
690
  let message;
690
- const inputRequests = [];
691
- const pendingInputRequests = /* @__PURE__ */ new Set();
692
- const pendingAuthorizations = /* @__PURE__ */ new Map();
693
691
  for (const event of events) {
694
- updatePendingInputRequests(pendingInputRequests, event);
695
- if (isTurnSegmentBoundary(event, pendingInputRequests)) boundary = event;
692
+ if (segment.observe(event)) boundary = event;
696
693
  if (isTurnFailureEvent(event)) failure = event;
697
694
  if (isFinalMessageCompleted(event)) message = event.data.message ?? void 0;
698
695
  if (event.type === "turn.waiting") message = void 0;
699
- if (event.type === "input.requested") inputRequests.push(...event.data.requests);
700
- if (event.type === "authorization.required") pendingAuthorizations.set(event.data.name, event.data);
701
- if (event.type === "authorization.completed") pendingAuthorizations.delete(event.data.name);
702
696
  }
703
697
  return {
704
698
  boundary,
705
699
  failure,
706
- inputRequests,
700
+ inputRequests: segment.inputRequests,
707
701
  message,
708
- pendingAuthorizations: [...pendingAuthorizations.values()],
702
+ pendingAuthorizations: segment.pendingAuthorizations,
709
703
  status: summarizeBoundaryStatus(boundary)
710
704
  };
711
705
  }
@@ -714,20 +708,50 @@ function summarizeBoundaryStatus(boundary) {
714
708
  if (boundary?.type === "session.failed") return "failed";
715
709
  return "completed";
716
710
  }
717
- function isTurnSegmentBoundary(event, pendingInputRequests) {
718
- if (event.type === "turn.waiting") return pendingInputRequests.size > 0;
719
- return isCurrentTurnBoundaryEvent(event);
720
- }
721
- function updatePendingInputRequests(pending, event) {
722
- if (event.type === "input.requested") for (const request of event.data.requests) pending.add(request.requestId);
723
- else if (event.type === "input.resolved") for (const resolution of event.data.resolutions) pending.delete(resolution.requestId);
711
+ function endsTurnSegment(event, open) {
712
+ if (event.type === "turn.waiting") return open.requests || event.data.on === "input" && !open.callbacks;
713
+ return isCurrentTurnBoundaryEvent(event) && (event.type !== "session.waiting" || !open.callbacks);
724
714
  }
715
+ var TurnSegment = class {
716
+ #authorizations = /* @__PURE__ */ new Map();
717
+ #followCallbacks;
718
+ #requests = /* @__PURE__ */ new Map();
719
+ constructor(options = {}) {
720
+ this.#followCallbacks = options.followCallbacks === true;
721
+ }
722
+ get inputRequests() {
723
+ return [...this.#requests.values()];
724
+ }
725
+ get pendingAuthorizations() {
726
+ return [...this.#authorizations.values()];
727
+ }
728
+ observe(event) {
729
+ switch (event.type) {
730
+ case "input.requested":
731
+ for (const request of event.data.requests) this.#requests.set(request.requestId, request);
732
+ break;
733
+ case "approval.settled":
734
+ this.#requests.delete(event.data.requestId);
735
+ break;
736
+ case "input.resolved":
737
+ for (const resolution of event.data.resolutions) this.#requests.delete(resolution.requestId);
738
+ break;
739
+ case "authorization.required":
740
+ this.#authorizations.set(authorizationKey(event.data), event.data);
741
+ break;
742
+ case "authorization.completed": this.#authorizations.delete(authorizationKey(event.data));
743
+ }
744
+ return endsTurnSegment(event, {
745
+ callbacks: this.#followCallbacks && [...this.#authorizations.values()].some((authorization) => authorization.webhookUrl !== void 0),
746
+ requests: this.#requests.size > 0
747
+ });
748
+ }
749
+ };
725
750
  function isFinalMessageCompleted(event) {
726
751
  return event.type === "message.completed" && event.data.finishReason !== "tool-calls";
727
752
  }
728
- function updatePendingAuthorizations(pending, event) {
729
- if (event.type === "authorization.required" && event.data.webhookUrl !== void 0) pending.add(event.data.name);
730
- else if (event.type === "authorization.completed") pending.delete(event.data.name);
753
+ function authorizationKey(data) {
754
+ return data.attemptId === void 0 ? `name:${data.name}` : `attempt:${data.attemptId}`;
731
755
  }
732
756
 
733
757
  //#endregion
@@ -1890,8 +1914,7 @@ var ClientSession = class ClientSession {
1890
1914
  let eventCount = 0;
1891
1915
  let started = deliveryId === void 0;
1892
1916
  let reachedBoundary = false;
1893
- const pendingAuthorizations = /* @__PURE__ */ new Set();
1894
- const pendingInputRequests = /* @__PURE__ */ new Set();
1917
+ const segment = new TurnSegment({ followCallbacks: true });
1895
1918
  try {
1896
1919
  for await (const event of source ?? this.#readStream({
1897
1920
  headers: input.headers,
@@ -1909,9 +1932,7 @@ var ClientSession = class ClientSession {
1909
1932
  if (!terminal && event.meta?.deliveryIds !== void 0 && !matches) continue;
1910
1933
  started = true;
1911
1934
  }
1912
- updatePendingAuthorizations(pendingAuthorizations, event);
1913
- updatePendingInputRequests(pendingInputRequests, event);
1914
- reachedBoundary = isTurnSegmentBoundary(event, pendingInputRequests) && (event.type !== "session.waiting" || pendingAuthorizations.size === 0);
1935
+ reachedBoundary = segment.observe(event);
1915
1936
  yield event;
1916
1937
  if (reachedBoundary) break;
1917
1938
  }
@@ -2176,117 +2197,6 @@ function withRedirectPolicy(init, redirect) {
2176
2197
  };
2177
2198
  }
2178
2199
 
2179
- //#endregion
2180
- //#region src/client/session-event-stream.ts
2181
- var SessionEventStream = class {
2182
- #controller = new AbortController();
2183
- #readers = /* @__PURE__ */ new Set();
2184
- #caughtUp = Promise.withResolvers();
2185
- caughtUp = this.#caughtUp.promise;
2186
- #ended = false;
2187
- #error;
2188
- #headers;
2189
- #reconnectPolicy;
2190
- constructor(session, options) {
2191
- this.setOptions(options);
2192
- this.caughtUp.catch(() => {});
2193
- if (!options.catchUp) this.#caughtUp.resolve();
2194
- (async () => {
2195
- try {
2196
- for await (const event of followClientSession(session, {
2197
- signal: this.#controller.signal,
2198
- resolveHeaders: () => this.#headers,
2199
- resolveReconnectPolicy: () => this.#reconnectPolicy,
2200
- startIndex: options.startIndex,
2201
- onCaughtUp: options.catchUp ? () => this.#caughtUp.resolve() : void 0
2202
- })) {
2203
- if (this.#controller.signal.aborted) return;
2204
- options.onEvent(event);
2205
- for (const reader of this.#readers) reader.push(event);
2206
- if (event.type === "session.completed" || event.type === "session.failed") break;
2207
- }
2208
- this.#caughtUp.resolve();
2209
- this.#finish();
2210
- } catch (error) {
2211
- this.#caughtUp.reject(error);
2212
- this.#finish(error);
2213
- if (!this.#controller.signal.aborted) options.onError(error);
2214
- }
2215
- })();
2216
- }
2217
- subscribe(signal) {
2218
- const reader = new SessionEventReader(() => this.#readers.delete(reader), signal);
2219
- if (this.#ended) reader.end(this.#error);
2220
- else this.#readers.add(reader);
2221
- return reader;
2222
- }
2223
- get ended() {
2224
- return this.#ended;
2225
- }
2226
- setOptions(options) {
2227
- if ("headers" in options) this.#headers = options.headers;
2228
- if ("streamReconnectPolicy" in options) this.#reconnectPolicy = options.streamReconnectPolicy;
2229
- }
2230
- close() {
2231
- const error = new DOMException("Session stream was detached.", "AbortError");
2232
- this.#controller.abort(error);
2233
- this.#caughtUp.reject(error);
2234
- this.#finish(error);
2235
- }
2236
- #finish(error) {
2237
- if (this.#ended) return;
2238
- this.#ended = true;
2239
- this.#error = error;
2240
- for (const reader of this.#readers) reader.end(error);
2241
- }
2242
- };
2243
- var SessionEventReader = class {
2244
- #events = [];
2245
- #wake = Promise.withResolvers();
2246
- #ended = false;
2247
- #error;
2248
- #dispose;
2249
- constructor(unsubscribe, signal) {
2250
- const abort = () => this.end(signal?.reason);
2251
- signal?.addEventListener("abort", abort, { once: true });
2252
- this.#dispose = () => {
2253
- signal?.removeEventListener("abort", abort);
2254
- unsubscribe();
2255
- };
2256
- if (signal?.aborted) abort();
2257
- }
2258
- push(event) {
2259
- if (this.#ended) return;
2260
- this.#events.push(event);
2261
- this.#wake.resolve();
2262
- }
2263
- end(error) {
2264
- if (this.#ended) return;
2265
- this.#ended = true;
2266
- this.#error = error;
2267
- this.#wake.resolve();
2268
- }
2269
- [Symbol.dispose]() {
2270
- this.end();
2271
- this.#events = [];
2272
- this.#dispose();
2273
- }
2274
- discard() {
2275
- this.#events = [];
2276
- }
2277
- async *[Symbol.asyncIterator]() {
2278
- for (;;) {
2279
- while (this.#events.length > 0) yield this.#events.shift();
2280
- if (this.#ended) {
2281
- if (this.#error !== void 0) throw this.#error;
2282
- return;
2283
- }
2284
- this.#wake = Promise.withResolvers();
2285
- await this.#wake.promise;
2286
- }
2287
- }
2288
- };
2289
-
2290
2200
  //#endregion
2291
2201
  //#region src/client/eve-agent-projection.ts
2292
2202
  var EveAgentProjection = class {
@@ -2295,18 +2205,21 @@ var EveAgentProjection = class {
2295
2205
  #data;
2296
2206
  constructor(reducer, events) {
2297
2207
  this.#reducer = reducer;
2298
- this.#events = events;
2208
+ this.#events = [...events];
2299
2209
  this.#data = this.#reduce();
2300
2210
  }
2301
2211
  get data() {
2302
2212
  return this.#data;
2303
2213
  }
2214
+ get reducer() {
2215
+ return this.#reducer;
2216
+ }
2304
2217
  reset() {
2305
2218
  this.#events = [];
2306
2219
  this.#data = this.#reducer.initial();
2307
2220
  }
2308
2221
  append(event) {
2309
- this.#events = [...this.#events, event];
2222
+ this.#events.push(event);
2310
2223
  this.#data = this.#reducer.reduce(this.#data, event);
2311
2224
  }
2312
2225
  remove(predicate) {
@@ -2315,7 +2228,8 @@ var EveAgentProjection = class {
2315
2228
  }
2316
2229
  replace(predicate, replacement) {
2317
2230
  const index = this.#events.findIndex(predicate);
2318
- this.#events = index === -1 ? [...this.#events, replacement] : this.#events.map((event, i) => i === index ? replacement : event);
2231
+ if (index === -1) this.#events.push(replacement);
2232
+ else this.#events[index] = replacement;
2319
2233
  this.#data = this.#reduce();
2320
2234
  }
2321
2235
  #reduce() {
@@ -2325,18 +2239,68 @@ var EveAgentProjection = class {
2325
2239
  }
2326
2240
  };
2327
2241
 
2242
+ //#endregion
2243
+ //#region src/client/conversation-state.ts
2244
+ function openConversationInputs(state) {
2245
+ return Object.values(state.inputs).filter((input) => input.status === "open");
2246
+ }
2247
+ function conversationAuthorizations(state) {
2248
+ return state.messages.flatMap((message) => message.role === "assistant" ? message.parts.filter((part) => part.type === "authorization") : []);
2249
+ }
2250
+ function hasPendingAuthorizations(state) {
2251
+ return conversationAuthorizations(state).some((part) => part.state === "required" && part.awaitsCallback === true);
2252
+ }
2253
+ function agentToolTask(state, agent) {
2254
+ const task = agent.taskId === void 0 ? void 0 : state.tasks[agent.taskId];
2255
+ return task?.kind === "agent" ? task : void 0;
2256
+ }
2257
+ function isAgentSessionCaughtUp(state, agent) {
2258
+ if (agent.observation.status !== "following" && agent.observation.status !== "idle") return false;
2259
+ const task = agentToolTask(state, agent);
2260
+ if (task === void 0) return false;
2261
+ const calls = Object.values(task.calls);
2262
+ if (calls.some((call) => call.status === "working")) return false;
2263
+ const child = agent.observation.conversation;
2264
+ if (child.activeTurnId !== void 0) return false;
2265
+ if (Object.values(child.inputs).some((input) => input.status !== "settled")) return false;
2266
+ if (hasPendingAuthorizations(child)) return false;
2267
+ return child.messages.filter((message) => message.role === "user").length >= calls.filter((call) => call.status === "completed").length;
2268
+ }
2269
+
2328
2270
  //#endregion
2329
2271
  //#region src/client/eve-agent-store-helpers.ts
2330
- function isSettledSessionTail(events) {
2272
+ function activeTurnForOptimisticFollowUp(events) {
2273
+ const lastTurn = events.findLast((event) => event.type === "turn.started" || event.type === "turn.completed" || event.type === "turn.failed" || event.type === "turn.cancelled" || isCurrentTurnBoundaryEvent(event));
2274
+ return lastTurn?.type === "turn.started" ? lastTurn.data.turnId : void 0;
2275
+ }
2276
+ function isResponseBoundary(event, conversation) {
2277
+ return endsTurnSegment(event, {
2278
+ callbacks: hasPendingAuthorizations(conversation),
2279
+ requests: Object.values(conversation.inputs).some((input) => input.status !== "settled")
2280
+ });
2281
+ }
2282
+ function settledStatus(error, conversation) {
2283
+ if (error !== void 0) return "error";
2284
+ return conversation.activeTurnId === void 0 ? "ready" : "streaming";
2285
+ }
2286
+ function isSettledSessionTail(events, conversation) {
2331
2287
  const tail = events.at(-1);
2332
- if (tail === void 0) return false;
2333
- const pendingAuthorizations = /* @__PURE__ */ new Set();
2334
- const pendingInputRequests = /* @__PURE__ */ new Set();
2335
- for (const event of events) {
2336
- updatePendingAuthorizations(pendingAuthorizations, event);
2337
- updatePendingInputRequests(pendingInputRequests, event);
2288
+ return tail !== void 0 && isResponseBoundary(tail, conversation);
2289
+ }
2290
+ function assertAnswerable(input, conversation) {
2291
+ for (const { requestId } of input.inputResponses ?? []) {
2292
+ const status = conversation.inputs[requestId]?.status;
2293
+ if (status !== void 0 && status !== "open") throw new Error(`Input request ${requestId} was already answered.`);
2338
2294
  }
2339
- return isTurnSegmentBoundary(tail, pendingInputRequests) && (tail.type !== "session.waiting" || pendingAuthorizations.size === 0);
2295
+ }
2296
+ function assertInFlightFollowUp(input) {
2297
+ if (input.inputResponses !== void 0) return;
2298
+ if (input.message === void 0 || input.turnPolicy !== "steer") throw new Error("eve session is already processing a turn. Send a message with turnPolicy: \"steer\" to guide it at the next boundary, or answer an open input request.");
2299
+ }
2300
+ function validateFollowUp(input) {
2301
+ assertExclusiveTurnInput(input);
2302
+ assertInFlightFollowUp(input);
2303
+ return input;
2340
2304
  }
2341
2305
  function assertExclusiveTurnInput(input) {
2342
2306
  if (input.message !== void 0 === (input.inputResponses !== void 0)) throw new Error("A turn requires exactly one of message or inputResponses.");
@@ -2385,16 +2349,25 @@ function createActiveTurn(cancel) {
2385
2349
  };
2386
2350
  return turn;
2387
2351
  }
2352
+ function countFollowUpDeliveries(turn, reconciliation) {
2353
+ let followed = 0;
2354
+ for (const id of reconciliation.ids) if (turn.followUpSubmissionIds.delete(id)) followed += 1;
2355
+ if (followed === 0) return;
2356
+ if (reconciliation.alreadyProjected) turn.receivedFollowUps += followed;
2357
+ else {
2358
+ const previous = turn.receivedFollowUpEvents.get(reconciliation.event) ?? 0;
2359
+ turn.receivedFollowUpEvents.set(reconciliation.event, previous + followed);
2360
+ }
2361
+ }
2388
2362
  async function followSteeredTurns(turn, events, isActive) {
2389
2363
  while (turn.followUpDispatches.size > 0) await Promise.allSettled(turn.followUpDispatches);
2390
2364
  if (turn.receivedFollowUps >= turn.acceptedFollowUps) return;
2391
- const pendingInputRequests = /* @__PURE__ */ new Set();
2365
+ const segment = new TurnSegment({ followCallbacks: true });
2392
2366
  for await (const event of events) {
2393
2367
  if (!isActive()) return;
2394
2368
  turn.receivedFollowUps += turn.receivedFollowUpEvents.get(event) ?? 0;
2395
2369
  turn.receivedFollowUpEvents.delete(event);
2396
- updatePendingInputRequests(pendingInputRequests, event);
2397
- if (isTurnSegmentBoundary(event, pendingInputRequests)) {
2370
+ if (segment.observe(event)) {
2398
2371
  while (turn.followUpDispatches.size > 0) await Promise.allSettled(turn.followUpDispatches);
2399
2372
  if (turn.receivedFollowUps >= turn.acceptedFollowUps) return;
2400
2373
  }
@@ -2417,43 +2390,52 @@ async function waitWithSignal(promise, signal) {
2417
2390
  //#region src/client/optimistic-message-submissions.ts
2418
2391
  var OptimisticMessageSubmissions = class {
2419
2392
  #optimistic;
2420
- #projection;
2393
+ #projections;
2421
2394
  #pending = [];
2422
- constructor(projection, optimistic) {
2423
- this.#projection = projection;
2395
+ constructor(projections, optimistic) {
2396
+ this.#projections = projections;
2424
2397
  this.#optimistic = optimistic;
2425
2398
  }
2426
2399
  reset() {
2427
2400
  this.#pending = [];
2428
2401
  }
2429
- submit(input, eventStartIndex) {
2402
+ submit(input, eventStartIndex, turnId) {
2430
2403
  if (input.message === void 0) return void 0;
2431
2404
  const pending = {
2432
2405
  createdAt: Date.now(),
2433
2406
  eventStartIndex,
2434
2407
  id: createSubmissionId(),
2435
2408
  message: summarizeUserContent(input.message),
2409
+ turnId,
2436
2410
  requiresDeliveryId: true
2437
2411
  };
2438
2412
  this.#pending = [...this.#pending, pending];
2439
- if (this.#optimistic) this.#projection.append({
2413
+ if (this.#optimistic) for (const projection of this.#projections) projection.append({
2440
2414
  data: {
2441
2415
  createdAt: pending.createdAt,
2442
2416
  message: pending.message,
2443
- submissionId: pending.id
2417
+ submissionId: pending.id,
2418
+ turnId
2444
2419
  },
2445
2420
  type: "client.message.submitted"
2446
2421
  });
2447
2422
  return pending.id;
2448
2423
  }
2424
+ resubmit(submissionId, input) {
2425
+ const pending = this.#pending.find((candidate) => candidate.id === submissionId);
2426
+ const message = input.message === void 0 ? void 0 : summarizeUserContent(input.message);
2427
+ if (pending?.message === message) return submissionId;
2428
+ if (pending !== void 0) this.#withdraw([pending.id]);
2429
+ return this.submit(input, pending?.eventStartIndex ?? 0, pending?.turnId);
2430
+ }
2449
2431
  apply(event) {
2450
2432
  if (event.type !== "message.received") {
2451
- this.#projection.append(event);
2433
+ for (const projection of this.#projections) projection.append(event);
2452
2434
  return;
2453
2435
  }
2454
2436
  const matching = this.#matching(event);
2455
2437
  if (matching.length === 0) {
2456
- this.#projection.append(event);
2438
+ for (const projection of this.#projections) projection.append(event);
2457
2439
  return;
2458
2440
  }
2459
2441
  return this.#reconcile(matching, event, false);
@@ -2477,12 +2459,13 @@ var OptimisticMessageSubmissions = class {
2477
2459
  const pending = submissionId === void 0 ? this.#pending[0] : this.#pending.find((candidate) => candidate.id === submissionId);
2478
2460
  if (pending === void 0) return;
2479
2461
  this.#pending = this.#pending.filter((candidate) => candidate.id !== pending.id);
2480
- this.#projection.replace((event) => event.type === "client.message.submitted" && event.data.submissionId === pending.id, {
2462
+ for (const projection of this.#projections) projection.replace((event) => event.type === "client.message.submitted" && event.data.submissionId === pending.id, {
2481
2463
  data: {
2482
2464
  createdAt: pending.createdAt,
2483
2465
  error: { message: error.message },
2484
2466
  message: pending.message,
2485
- submissionId: pending.id
2467
+ submissionId: pending.id,
2468
+ turnId: pending.turnId
2486
2469
  },
2487
2470
  type: "client.message.failed"
2488
2471
  });
@@ -2495,1188 +2478,1840 @@ var OptimisticMessageSubmissions = class {
2495
2478
  }
2496
2479
  #reconcile(submissions, event, alreadyProjected) {
2497
2480
  const ids = submissions.map((pending) => pending.id);
2498
- const idSet = new Set(ids);
2499
- this.#pending = this.#pending.filter((pending) => !idSet.has(pending.id));
2500
- if (alreadyProjected) this.#projection.remove((candidate) => candidate.type === "client.message.submitted" && idSet.has(candidate.data.submissionId));
2501
- else {
2502
- this.#projection.replace((candidate) => candidate.type === "client.message.submitted" && candidate.data.submissionId === ids[0], event);
2503
- this.#projection.remove((candidate) => candidate.type === "client.message.submitted" && idSet.has(candidate.data.submissionId));
2504
- }
2481
+ this.#withdraw(ids);
2482
+ if (!alreadyProjected) for (const projection of this.#projections) projection.append(event);
2505
2483
  return {
2506
2484
  alreadyProjected,
2507
2485
  event,
2508
2486
  ids
2509
2487
  };
2510
2488
  }
2489
+ #withdraw(ids) {
2490
+ const idSet = new Set(ids);
2491
+ this.#pending = this.#pending.filter((pending) => !idSet.has(pending.id));
2492
+ for (const projection of this.#projections) projection.remove((candidate) => candidate.type === "client.message.submitted" && idSet.has(candidate.data.submissionId));
2493
+ }
2511
2494
  };
2512
2495
 
2513
2496
  //#endregion
2514
- //#region src/protocol/event-dedupe.ts
2515
- function createEventDeduper() {
2516
- const seen = /* @__PURE__ */ new Set();
2517
- return {
2518
- admit(event) {
2519
- const id = event.meta?.id;
2520
- if (id === void 0) return true;
2521
- if (seen.has(id)) return false;
2522
- seen.add(id);
2523
- return true;
2524
- },
2525
- get size() {
2526
- return seen.size;
2497
+ //#region src/client/agent-stream-follower.ts
2498
+ const agentStreamReconnectPolicy = {
2499
+ streamIdleReconnectPolicy: { maxAttempts: Infinity },
2500
+ streamOpenReconnectPolicy: { maxAttempts: Infinity }
2501
+ };
2502
+ var AgentStreamFollower = class {
2503
+ #options;
2504
+ #started = /* @__PURE__ */ new Map();
2505
+ #controllers = /* @__PURE__ */ new Map();
2506
+ #failed = /* @__PURE__ */ new Set();
2507
+ #disposed = false;
2508
+ constructor(options) {
2509
+ this.#options = options;
2510
+ }
2511
+ acceptParentEvent(event) {
2512
+ if (event.type === "agent.started") this.#started.set(event.data.sessionId, event);
2513
+ }
2514
+ reconcile() {
2515
+ if (this.#disposed) return;
2516
+ const state = this.#options.getState();
2517
+ for (const agent of Object.values(state.agents)) {
2518
+ if (agentToolTask(state, agent) === void 0) continue;
2519
+ const controller = this.#controllers.get(agent.sessionId);
2520
+ const caughtUp = isAgentSessionCaughtUp(state, agent);
2521
+ if (controller !== void 0 && caughtUp) {
2522
+ this.#controllers.delete(agent.sessionId);
2523
+ controller.abort();
2524
+ this.#options.onIdle(agent.sessionId);
2525
+ } else if (controller === void 0 && !caughtUp && !this.#failed.has(agent.sessionId)) this.#follow(agent.sessionId);
2527
2526
  }
2528
- };
2529
- }
2530
-
2531
- //#endregion
2532
- //#region src/client/eve-agent-store.ts
2533
- const detachStore = Symbol("detachEveAgentStore");
2534
- const attachStore = Symbol("attachEveAgentStore");
2535
- var EveAgentStore = class {
2536
- #client;
2537
- #autoPrewarm;
2538
- #attached = false;
2539
- #stream;
2540
- #pendingAuthorizations = /* @__PURE__ */ new Set();
2541
- #pendingInputRequests = /* @__PURE__ */ new Set();
2542
- #externalSession;
2543
- #optimistic;
2544
- #projection;
2545
- #subscribers = /* @__PURE__ */ new Set();
2546
- #seenEvents = createEventDeduper();
2547
- #activeTurn;
2548
- #callbacks = {};
2549
- #error;
2550
- #events;
2551
- #messageSubmissions;
2552
- #prewarmGeneration = 0;
2553
- #prewarmPromise;
2554
- #prewarmController;
2555
- #resumePromise;
2556
- #session;
2557
- #snapshot;
2558
- #status = "ready";
2559
- constructor(init) {
2560
- this.#autoPrewarm = init.prewarm ?? false;
2561
- this.#externalSession = init.session !== void 0;
2562
- this.#client = this.#externalSession ? void 0 : new Client({
2563
- auth: init.auth,
2564
- headers: init.headers,
2565
- host: init.host ?? ""
2566
- });
2567
- const initialEvents = [];
2568
- for (const event of init.initialEvents ?? []) {
2569
- if (this.#seenEvents.admit(event)) initialEvents.push(event);
2570
- this.#trackPendingRequests(event);
2571
- }
2572
- this.#events = initialEvents;
2573
- this.#projection = new EveAgentProjection(init.reducer, this.#events);
2574
- this.#optimistic = init.optimistic ?? true;
2575
- this.#messageSubmissions = new OptimisticMessageSubmissions(this.#projection, this.#optimistic);
2576
- this.#session = init.session ?? (init.initialSession === void 0 ? void 0 : this.#client?.sessions.attach(init.initialSession.sessionId, { streamIndex: init.initialSession.streamIndex }));
2577
- this.#snapshot = this.#createSnapshot();
2578
- }
2579
- get snapshot() {
2580
- return this.#snapshot;
2581
2527
  }
2582
- setCallbacks(callbacks) {
2583
- this.#callbacks = callbacks;
2584
- }
2585
- subscribe(callback) {
2586
- this.#subscribers.add(callback);
2587
- return () => {
2588
- this.#subscribers.delete(callback);
2589
- };
2528
+ abortAll() {
2529
+ this.#disposed = true;
2530
+ for (const controller of this.#controllers.values()) controller.abort();
2531
+ this.#controllers.clear();
2590
2532
  }
2591
- prewarm() {
2592
- if (this.#prewarmPromise !== void 0) return this.#prewarmPromise;
2593
- if (this.#session !== void 0 || this.#externalSession) return Promise.resolve();
2594
- if (this.#activeTurn !== void 0) return this.#activeTurn.response.then((response) => {
2595
- if (response === void 0) throw this.#error ?? new DOMException("Session creation was aborted.", "AbortError");
2596
- });
2597
- const client = this.#client;
2598
- if (client === void 0) return Promise.reject(/* @__PURE__ */ new Error("This eve agent store does not own a session client."));
2599
- const generation = this.#prewarmGeneration;
2533
+ #follow(sessionId) {
2534
+ const started = this.#started.get(sessionId);
2535
+ if (started === void 0) return;
2600
2536
  const controller = new AbortController();
2601
- this.#prewarmController = controller;
2602
- const promise = (async () => {
2537
+ this.#controllers.set(sessionId, controller);
2538
+ this.#options.onFollowing(sessionId);
2539
+ const { cursors } = this.#options;
2540
+ (async () => {
2541
+ let cursor = cursors.get(sessionId) ?? 0;
2603
2542
  try {
2604
- const created = await client.sessions.create({ signal: controller.signal });
2605
- if (generation !== this.#prewarmGeneration) return;
2606
- this.#session = created.session;
2607
- this.#error = void 0;
2608
- if (this.#status === "error") this.#status = "ready";
2609
- this.#callbacks.onSessionChange?.(created.session.state);
2610
- this.#publish();
2611
- this.#ensureStream();
2612
- } catch (error) {
2613
- if (generation === this.#prewarmGeneration && this.#activeTurn === void 0 && this.#error === void 0) {
2614
- this.#error = toError(error);
2615
- this.#status = "error";
2616
- this.#callbacks.onError?.(this.#error);
2617
- this.#publish();
2543
+ for await (const event of this.#options.session.agent(started).stream({
2544
+ signal: controller.signal,
2545
+ startIndex: cursor,
2546
+ streamReconnectPolicy: agentStreamReconnectPolicy
2547
+ })) {
2548
+ if (controller.signal.aborted) return;
2549
+ cursors.set(sessionId, ++cursor);
2550
+ this.#options.onEvent(sessionId, event);
2551
+ this.reconcile();
2618
2552
  }
2619
- throw error;
2620
- }
2553
+ } catch {}
2554
+ if (controller.signal.aborted || this.#controllers.get(sessionId) !== controller) return;
2555
+ this.#controllers.delete(sessionId);
2556
+ this.#failed.add(sessionId);
2557
+ this.#options.onUnavailable(sessionId);
2621
2558
  })();
2622
- this.#prewarmPromise = promise;
2623
- const clear = () => {
2624
- if (this.#prewarmPromise === promise) {
2625
- this.#prewarmPromise = void 0;
2626
- this.#prewarmController = void 0;
2627
- }
2628
- };
2629
- promise.then(clear, clear);
2630
- return promise;
2631
- }
2632
- async send(input) {
2633
- return await this.#submit(input, this.#callbacks.prepareSend);
2634
2559
  }
2635
- async #submit(input, prepareSend) {
2636
- if (this.#activeTurn !== void 0) {
2637
- if (this.#status === "resuming") throw new Error("eve session is resuming.");
2638
- return await this.#sendFollowUp(this.#activeTurn, input, prepareSend);
2639
- }
2640
- const turn = createActiveTurn((turn) => turn.acceptedFollowUps > 0 && this.#session !== void 0 ? this.#session.cancel() : turn.response.then((response) => response === void 0 ? { status: "no_active_turn" } : response.cancel()));
2641
- this.#activeTurn = turn;
2642
- this.#error = void 0;
2643
- this.#status = "submitted";
2644
- this.#publish();
2645
- let reader;
2646
- try {
2647
- const preparedInput = await (prepareSend === void 0 ? input : waitWithSignal(Promise.resolve(prepareSend(input)), createAbortSignal(input.signal, turn.abortController.signal)));
2648
- assertExclusiveTurnInput(preparedInput);
2649
- if (!this.#isActiveTurn(turn)) return;
2650
- const submissionId = this.#messageSubmissions.submit(preparedInput, this.#events.length);
2651
- this.#projectInputResponses(preparedInput);
2652
- this.#publish();
2653
- const turnInput = {
2654
- ...preparedInput,
2655
- signal: createAbortSignal(preparedInput.signal, turn.abortController.signal)
2656
- };
2657
- const dispatched = await this.#dispatchTurn(turnInput);
2658
- const response = dispatched.response;
2659
- reader = dispatched.reader;
2660
- if (!this.#isActiveTurn(turn)) return;
2661
- turn.resolveResponse(response);
2662
- if (this.#handleReconciliation(this.#messageSubmissions.correlate(submissionId, getMessageResponseDeliveryId(response), this.#events))) this.#publish();
2663
- for await (const event of consumeMessageResponse(response, reader)) {
2664
- if (!this.#isActiveTurn(turn)) return;
2665
- turn.receivedFollowUps += turn.receivedFollowUpEvents.get(event) ?? 0;
2666
- turn.receivedFollowUpEvents.delete(event);
2667
- }
2668
- if (!this.#isActiveTurn(turn)) return;
2669
- await followSteeredTurns(turn, reader, () => this.#isActiveTurn(turn));
2670
- if (!this.#isActiveTurn(turn)) return;
2671
- this.#status = this.#error === void 0 ? "ready" : "error";
2672
- } catch (error) {
2673
- if (!this.#isActiveTurn(turn)) return;
2674
- if (isAbortError(error)) {
2675
- this.#status = "ready";
2676
- this.#messageSubmissions.fail(toError(error));
2677
- } else {
2678
- const reported = this.#error !== void 0;
2679
- this.#error ??= toError(error);
2680
- this.#status = "error";
2681
- this.#messageSubmissions.fail(this.#error);
2682
- if (!reported) this.#callbacks.onError?.(this.#error);
2683
- }
2684
- } finally {
2685
- reader?.[Symbol.dispose]();
2686
- this.#finishTurn(turn);
2687
- }
2560
+ };
2561
+
2562
+ //#endregion
2563
+ //#region src/client/authorization-message-parts.ts
2564
+ function createAuthorizationRequiredPart(event) {
2565
+ const displayName = event.data.authorization?.displayName ?? formatAuthorizationDisplayName(event.data.name);
2566
+ const part = {
2567
+ authorization: event.data.authorization,
2568
+ description: normalizeAuthorizationDescription(event.data.description, event.data.name, displayName),
2569
+ displayName,
2570
+ name: event.data.name,
2571
+ state: "required",
2572
+ stepIndex: event.data.stepIndex,
2573
+ turnId: event.data.turnId,
2574
+ type: "authorization"
2575
+ };
2576
+ if (event.data.attemptId !== void 0) part.attemptId = event.data.attemptId;
2577
+ if (event.data.webhookUrl !== void 0) part.awaitsCallback = true;
2578
+ return part;
2579
+ }
2580
+ function createAuthorizationCompletedPart(event, existing) {
2581
+ const displayName = event.data.authorization?.displayName ?? existing?.displayName ?? formatAuthorizationDisplayName(event.data.name);
2582
+ const part = {
2583
+ authorization: existing?.authorization || event.data.authorization ? {
2584
+ ...existing?.authorization,
2585
+ ...event.data.authorization
2586
+ } : void 0,
2587
+ description: existing?.description ?? buildCompletedAuthorizationDescription(displayName, event.data.outcome, event.data.reason),
2588
+ displayName,
2589
+ name: event.data.name,
2590
+ outcome: event.data.outcome,
2591
+ state: "completed",
2592
+ stepIndex: existing?.stepIndex ?? event.data.stepIndex,
2593
+ turnId: existing?.turnId ?? event.data.turnId,
2594
+ type: "authorization"
2595
+ };
2596
+ const attemptId = event.data.attemptId ?? existing?.attemptId;
2597
+ if (attemptId !== void 0) part.attemptId = attemptId;
2598
+ if (existing?.awaitsCallback) part.awaitsCallback = true;
2599
+ if (event.data.reason !== void 0) part.reason = event.data.reason;
2600
+ return part;
2601
+ }
2602
+ function buildCompletedAuthorizationDescription(displayName, outcome, reason) {
2603
+ if (outcome === "authorized") return `${displayName} connected.`;
2604
+ return `${displayName} authorization ${outcome}${reason !== void 0 ? ` (${reason})` : ""}.`;
2605
+ }
2606
+ function normalizeAuthorizationDescription(description, name, displayName) {
2607
+ if (description === `Authorization required for ${name}`) return `Authorization required for ${displayName}`;
2608
+ return description;
2609
+ }
2610
+ function formatAuthorizationDisplayName(name) {
2611
+ if (name.length === 0) return name;
2612
+ return `${name.charAt(0).toUpperCase()}${name.slice(1)}`;
2613
+ }
2614
+
2615
+ //#endregion
2616
+ //#region src/shared/action-request-name.ts
2617
+ function actionRequestName(action) {
2618
+ switch (action.kind) {
2619
+ case "load-skill": return "load_skill";
2620
+ case "subagent-call": return action.subagentName;
2621
+ case "remote-agent-call": return action.remoteAgentName;
2622
+ case "tool-call":
2623
+ case "workflow-tool-call": return action.toolName;
2688
2624
  }
2689
- resume() {
2690
- if (this.#resumePromise !== void 0) return this.#resumePromise;
2691
- const promise = this.#resume();
2692
- this.#resumePromise = promise;
2693
- const clear = () => {
2694
- if (this.#resumePromise === promise) this.#resumePromise = void 0;
2625
+ }
2626
+
2627
+ //#endregion
2628
+ //#region src/client/message-action-parts.ts
2629
+ function toMessageInputRequest(request) {
2630
+ return {
2631
+ allowFreeform: request.allowFreeform,
2632
+ display: request.display,
2633
+ kind: request.kind,
2634
+ options: request.options,
2635
+ prompt: request.prompt,
2636
+ requestId: request.requestId
2637
+ };
2638
+ }
2639
+ function createToolMetadata(descriptor, extra) {
2640
+ return { eve: {
2641
+ inputRequest: extra?.inputRequest,
2642
+ kind: descriptor.kind,
2643
+ name: descriptor.name
2644
+ } };
2645
+ }
2646
+ function mergeToolMetadata(current, next) {
2647
+ const kind = next.eve?.kind ?? current?.eve?.kind ?? "unknown";
2648
+ const name = next.eve?.name ?? current?.eve?.name ?? "unknown";
2649
+ return { eve: {
2650
+ ...current?.eve,
2651
+ ...next.eve,
2652
+ inputRequest: next.eve?.inputRequest ?? current?.eve?.inputRequest,
2653
+ inputResponse: next.eve?.inputResponse ?? current?.eve?.inputResponse,
2654
+ kind,
2655
+ name
2656
+ } };
2657
+ }
2658
+ function approvedApproval(part) {
2659
+ if (!part?.approval?.id) return;
2660
+ return {
2661
+ approved: true,
2662
+ id: part.approval.id,
2663
+ isAutomatic: part.approval.isAutomatic,
2664
+ reason: part.approval.reason
2665
+ };
2666
+ }
2667
+ function normalizeActionRequest(action) {
2668
+ const name = actionRequestName(action);
2669
+ switch (action.kind) {
2670
+ case "load-skill": return {
2671
+ kind: "load-skill",
2672
+ name,
2673
+ toolName: "eve:load-skill"
2674
+ };
2675
+ case "tool-call":
2676
+ case "workflow-tool-call": return {
2677
+ kind: "tool-call",
2678
+ name,
2679
+ toolName: name
2680
+ };
2681
+ case "subagent-call":
2682
+ case "remote-agent-call": return {
2683
+ kind: "subagent-call",
2684
+ name,
2685
+ toolName: `eve:subagent:${name}`
2695
2686
  };
2696
- promise.then(clear, clear);
2697
- return promise;
2698
- }
2699
- async #resume() {
2700
- if (this.#status === "resuming" || this.#status === "streaming" || this.#status === "submitted") throw new Error("eve session is already processing a turn.");
2701
- if (this.#session === void 0) throw new Error("An eve session is required before resuming.");
2702
- const session = this.#session;
2703
- const turn = createActiveTurn(() => session.cancel());
2704
- this.#activeTurn = turn;
2705
- turn.resolveResponse(void 0);
2706
- this.#error = void 0;
2707
- this.#status = "resuming";
2708
- this.#publish();
2709
- let reader;
2710
- try {
2711
- const stream = this.#ensureStream({
2712
- catchUp: true,
2713
- startIndex: this.#events.length === session.state.streamIndex ? session.state.streamIndex : 0
2714
- });
2715
- reader = stream.subscribe(turn.abortController.signal);
2716
- await stream.caughtUp;
2717
- if (!this.#isActiveTurn(turn)) return;
2718
- reader.discard();
2719
- const tail = this.#events.at(-1);
2720
- if (tail !== void 0) this.#applyTerminalStreamFailure(tail);
2721
- if (tail !== void 0 && this.#error === void 0 && !isSettledSessionTail(this.#events)) {
2722
- this.#status = "streaming";
2723
- this.#publish();
2724
- for await (const event of reader) {
2725
- if (!this.#isActiveTurn(turn)) return;
2726
- turn.receivedFollowUps += turn.receivedFollowUpEvents.get(event) ?? 0;
2727
- turn.receivedFollowUpEvents.delete(event);
2728
- if (this.#isSettledAt(event)) break;
2729
- }
2730
- }
2731
- await followSteeredTurns(turn, reader, () => this.#isActiveTurn(turn));
2732
- if (this.#isActiveTurn(turn)) this.#status = this.#error === void 0 ? "ready" : "error";
2733
- } catch (error) {
2734
- if (!this.#isActiveTurn(turn)) return;
2735
- if (isAbortError(error)) this.#status = "ready";
2736
- else {
2737
- this.#error = toError(error);
2738
- this.#status = "error";
2739
- this.#callbacks.onError?.(this.#error);
2740
- }
2741
- } finally {
2742
- reader?.[Symbol.dispose]();
2743
- this.#finishTurn(turn);
2744
- }
2745
- }
2746
- cancel() {
2747
- const turn = this.#activeTurn;
2748
- if (turn === void 0) return this.#status === "streaming" && this.#session !== void 0 ? this.#session.cancel() : Promise.resolve({ status: "no_active_turn" });
2749
- return turn.cancel();
2750
- }
2751
- [attachStore]() {
2752
- this.#attached = true;
2753
- if (this.#autoPrewarm && this.#session === void 0) this.prewarm().catch(() => {});
2754
2687
  }
2755
- [detachStore]() {
2756
- this.#attached = false;
2757
- this.#stream?.close();
2758
- this.#stream = void 0;
2759
- this.#activeTurn?.abortController.abort();
2760
- this.#resetPrewarm();
2761
- this.#resumePromise = void 0;
2688
+ }
2689
+ function normalizeActionResult(result) {
2690
+ switch (result.kind) {
2691
+ case "load-skill-result": return {
2692
+ kind: "load-skill",
2693
+ name: result.name ?? "load_skill",
2694
+ toolName: "eve:load-skill"
2695
+ };
2696
+ case "tool-result": return {
2697
+ kind: "tool-call",
2698
+ name: result.toolName,
2699
+ toolName: result.toolName
2700
+ };
2701
+ case "subagent-result": return {
2702
+ kind: "subagent-call",
2703
+ name: result.subagentName,
2704
+ toolName: `eve:subagent:${result.subagentName}`
2705
+ };
2762
2706
  }
2763
- reset() {
2764
- this.#stream?.close();
2765
- this.#stream = void 0;
2766
- this.#pendingAuthorizations.clear();
2767
- this.#pendingInputRequests.clear();
2768
- const turn = this.#activeTurn;
2769
- this.#activeTurn = void 0;
2770
- turn?.resolveResponse(void 0);
2771
- turn?.resolveCompletion();
2772
- turn?.abortController.abort();
2773
- this.#resetPrewarm();
2774
- this.#resumePromise = void 0;
2775
- if (!this.#externalSession) this.#session = void 0;
2776
- this.#events = [];
2777
- this.#seenEvents = createEventDeduper();
2778
- this.#messageSubmissions.reset();
2779
- this.#projection.reset();
2780
- this.#error = void 0;
2781
- this.#status = "ready";
2782
- this.#callbacks.onSessionChange?.(this.#session?.state);
2783
- this.#publish();
2784
- if (this.#autoPrewarm && this.#attached) this.prewarm().catch(() => {});
2707
+ }
2708
+ function stringifyUnknown(value) {
2709
+ if (typeof value === "string") return value;
2710
+ try {
2711
+ return JSON.stringify(value);
2712
+ } catch {
2713
+ return "Action failed.";
2785
2714
  }
2786
- async #sendFollowUp(turn, input, prepareSend) {
2787
- if (input.message === void 0 || input.turnPolicy !== "steer") throw new Error("eve session is already processing a turn. Send a message with turnPolicy: \"steer\" to guide it at the next boundary.");
2788
- const generation = this.#prewarmGeneration;
2789
- const signal = createAbortSignal(input.signal, turn.abortController.signal);
2790
- const preparedInput = await waitWithSignal(Promise.resolve(prepareSend?.(input)), signal) ?? input;
2791
- if (generation !== this.#prewarmGeneration) return;
2792
- assertExclusiveTurnInput(preparedInput);
2793
- if (preparedInput.message === void 0 || preparedInput.turnPolicy !== "steer") throw new Error("An in-flight follow-up requires a message with turnPolicy: \"steer\".");
2794
- if (!this.#isActiveTurn(turn)) return await this.#submit(preparedInput);
2795
- const submissionId = this.#messageSubmissions.submit(preparedInput, this.#events.length);
2796
- if (submissionId !== void 0) turn.followUpSubmissionIds.add(submissionId);
2797
- this.#publish();
2798
- this.#ensureStream({
2799
- headers: preparedInput.headers,
2800
- streamReconnectPolicy: preparedInput.streamReconnectPolicy
2801
- });
2802
- let dispatch;
2803
- dispatch = (async () => {
2804
- try {
2805
- const signal = createAbortSignal(preparedInput.signal, turn.abortController.signal);
2806
- await waitWithSignal(turn.response, signal);
2807
- if (!this.#isActiveTurn(turn) || this.#session === void 0) throw new Error("The active eve turn ended before the follow-up could be sent.");
2808
- const { message, ...options } = preparedInput;
2809
- const response = await this.#session.send(message, {
2810
- ...options,
2811
- signal
2812
- });
2813
- turn.acceptedFollowUps += 1;
2814
- if (this.#handleReconciliation(this.#messageSubmissions.correlate(submissionId, getMessageResponseDeliveryId(response), this.#events))) this.#publish();
2815
- } catch (error) {
2816
- if (this.#isActiveTurn(turn)) {
2817
- this.#messageSubmissions.fail(toError(error), submissionId);
2818
- this.#publish();
2819
- }
2820
- throw error;
2821
- } finally {
2822
- turn.followUpDispatches.delete(dispatch);
2823
- }
2824
- })();
2825
- turn.followUpDispatches.add(dispatch);
2826
- await dispatch;
2827
- await turn.completion;
2715
+ }
2716
+
2717
+ //#endregion
2718
+ //#region src/client/message-reducer-primitives.ts
2719
+ function projectReceivedParts(parts, message) {
2720
+ return parts?.map((part) => part.type === "text" ? {
2721
+ state: "done",
2722
+ text: part.text,
2723
+ type: "text"
2724
+ } : {
2725
+ filename: part.filename,
2726
+ mediaType: part.mediaType,
2727
+ size: part.size,
2728
+ type: "file",
2729
+ url: part.url
2730
+ }) ?? [{
2731
+ state: "done",
2732
+ text: message,
2733
+ type: "text"
2734
+ }];
2735
+ }
2736
+ function partKey(part) {
2737
+ switch (part.type) {
2738
+ case "text": return `text:${part.stepIndex ?? 0}`;
2739
+ case "reasoning": return `reasoning:${part.stepIndex ?? 0}`;
2740
+ case "file": return `file:${part.stepIndex ?? 0}:${part.filename ?? part.url ?? part.mediaType}`;
2741
+ case "step-start": return "step-start";
2742
+ case "authorization": return part.attemptId === void 0 ? `authorization:${part.turnId}:${part.stepIndex}:${part.name}` : `authorization:${part.attemptId}`;
2743
+ case "dynamic-tool": return `dynamic-tool:${part.toolCallId}`;
2828
2744
  }
2829
- async #dispatchTurn(input) {
2830
- const streamOptions = {
2831
- headers: input.headers,
2832
- streamReconnectPolicy: input.streamReconnectPolicy
2745
+ }
2746
+ function upsertMessage(data, next, beforeAssistantTurnId) {
2747
+ const index = data.messages.findIndex((message) => message.id === next.id);
2748
+ if (index !== -1) return {
2749
+ ...data,
2750
+ messages: [
2751
+ ...data.messages.slice(0, index),
2752
+ next,
2753
+ ...data.messages.slice(index + 1)
2754
+ ]
2755
+ };
2756
+ const before = beforeAssistantTurnId === void 0 ? -1 : data.messages.findIndex((message) => message.role === "assistant" && message.metadata?.turnId === beforeAssistantTurnId);
2757
+ if (before === -1) return {
2758
+ ...data,
2759
+ messages: [...data.messages, next]
2760
+ };
2761
+ return {
2762
+ ...data,
2763
+ messages: [
2764
+ ...data.messages.slice(0, before),
2765
+ next,
2766
+ ...data.messages.slice(before)
2767
+ ]
2768
+ };
2769
+ }
2770
+ function optimisticUserMessageId(submissionId) {
2771
+ return `optimistic:${submissionId}:user`;
2772
+ }
2773
+
2774
+ //#endregion
2775
+ //#region src/client/message-run-parts.ts
2776
+ function transition(message, input) {
2777
+ const index = message.parts.findLastIndex((part) => part.type === input.type && part.stepIndex === input.stepIndex);
2778
+ const previous = index === -1 ? void 0 : message.parts[index];
2779
+ if (input.kind === "append" && !input.delta) return message;
2780
+ const current = previous?.state === "streaming" ? previous : void 0;
2781
+ const part = {
2782
+ id: current?.id ?? input.id ?? `${message.id}:${input.type}:${message.parts.length}`,
2783
+ state: input.kind === "append" ? "streaming" : "done",
2784
+ stepIndex: input.stepIndex,
2785
+ text: input.kind === "append" ? (current?.text ?? "") + input.delta : input.text,
2786
+ type: input.type
2787
+ };
2788
+ const parts = current ? [
2789
+ ...message.parts.slice(0, index),
2790
+ part,
2791
+ ...message.parts.slice(index + 1)
2792
+ ] : [...message.parts, part];
2793
+ return {
2794
+ ...message,
2795
+ metadata: {
2796
+ ...message.metadata,
2797
+ status: input.type === "text" && part.state === "done" ? "complete" : "streaming"
2798
+ },
2799
+ parts
2800
+ };
2801
+ }
2802
+ const messageRun = { transition };
2803
+
2804
+ //#endregion
2805
+ //#region src/client/message-task-parts.ts
2806
+ function createSettledTaskPart(existing, event) {
2807
+ const settledPartBase = {
2808
+ approval: approvedApproval(existing),
2809
+ input: existing.input,
2810
+ stepIndex: existing.stepIndex,
2811
+ toolCallId: existing.toolCallId,
2812
+ toolMetadata: existing.toolMetadata,
2813
+ toolName: existing.toolName,
2814
+ type: "dynamic-tool"
2815
+ };
2816
+ switch (event.data.status) {
2817
+ case "completed": return {
2818
+ ...settledPartBase,
2819
+ output: event.data.output,
2820
+ state: "output-available"
2833
2821
  };
2834
- if (this.#prewarmPromise !== void 0) {
2835
- await waitWithSignal(this.#prewarmPromise.catch((error) => {
2836
- if (this.#session !== void 0) throw error;
2837
- }), input.signal);
2838
- input.signal?.throwIfAborted();
2822
+ case "failed": return {
2823
+ ...settledPartBase,
2824
+ errorText: event.data.error?.message ?? "Task failed.",
2825
+ state: "output-error"
2826
+ };
2827
+ case "cancelled": return {
2828
+ ...settledPartBase,
2829
+ errorText: "Task was cancelled.",
2830
+ state: "output-error"
2831
+ };
2832
+ }
2833
+ }
2834
+
2835
+ //#endregion
2836
+ //#region src/client/message-reducer.ts
2837
+ function receivedMessageEventId(event) {
2838
+ return event.meta.id ?? `${event.data.turnId}:${event.data.sequence}`;
2839
+ }
2840
+ function defaultMessageReducer() {
2841
+ return {
2842
+ initial() {
2843
+ return { messages: [] };
2844
+ },
2845
+ reduce(data, event) {
2846
+ return reduceMessageData(data, event);
2839
2847
  }
2840
- if (this.#session === void 0) {
2841
- if (this.#client === void 0) throw new Error("An external eve session is required before sending.");
2842
- if (input.message === void 0) throw new Error("Cannot answer an input request before the session starts.");
2843
- const created = await this.#client.sessions.create({
2844
- ...input,
2845
- message: input.message
2846
- });
2847
- input.signal?.throwIfAborted();
2848
- this.#session = created.session;
2849
- this.#callbacks.onSessionChange?.(created.session.state);
2850
- this.#publish();
2851
- return {
2852
- response: created.response,
2853
- reader: this.#ensureStream(streamOptions).subscribe(input.signal)
2848
+ };
2849
+ }
2850
+ function reduceMessageData(data, event) {
2851
+ switch (event.type) {
2852
+ case "client.message.submitted":
2853
+ case "client.message.failed": return upsertMessage(data, {
2854
+ id: optimisticUserMessageId(event.data.submissionId),
2855
+ metadata: {
2856
+ optimistic: true,
2857
+ status: event.type === "client.message.failed" ? "failed" : "submitted"
2858
+ },
2859
+ parts: [{
2860
+ type: "text",
2861
+ text: event.data.message
2862
+ }],
2863
+ role: "user"
2864
+ }, event.data.turnId);
2865
+ case "input.resolved": {
2866
+ let next = data;
2867
+ for (const resolution of event.data.resolutions) next = resolveInputRequest(next, resolution);
2868
+ return next;
2869
+ }
2870
+ case "message.received": return upsertMessage(data, {
2871
+ id: `${receivedMessageEventId(event)}:user`,
2872
+ metadata: {
2873
+ status: "complete",
2874
+ turnId: event.data.turnId
2875
+ },
2876
+ parts: projectReceivedParts(event.data.parts, event.data.message),
2877
+ role: "user"
2878
+ }, event.data.turnId);
2879
+ case "step.started": return updateAssistantMessage(data, event.data.turnId, (message) => ensureStepStartPart(message, event.data.stepIndex));
2880
+ case "step.completed":
2881
+ if (data.messages.find((message) => message.role === "assistant" && message.metadata?.turnId === event.data.turnId) === void 0) return data;
2882
+ return updateAssistantMessage(data, event.data.turnId, (message) => ({
2883
+ ...message,
2884
+ parts: closeStreamingRuns(message.parts, event.data.stepIndex)
2885
+ }));
2886
+ case "reasoning.appended": return updateAssistantMessage(data, event.data.turnId, (message) => messageRun.transition(ensureStepStartPart(message, event.data.stepIndex), {
2887
+ kind: "append",
2888
+ delta: event.data.reasoningDelta,
2889
+ id: event.meta?.id,
2890
+ stepIndex: event.data.stepIndex,
2891
+ type: "reasoning"
2892
+ }));
2893
+ case "reasoning.completed": return updateAssistantMessage(data, event.data.turnId, (message) => messageRun.transition(ensureStepStartPart(message, event.data.stepIndex), {
2894
+ kind: "complete",
2895
+ stepIndex: event.data.stepIndex,
2896
+ text: event.data.reasoning,
2897
+ id: event.meta?.id,
2898
+ type: "reasoning"
2899
+ }));
2900
+ case "action.input.appended": {
2901
+ const existing = findToolPart(data, event.data.callId);
2902
+ if (existing !== void 0 && existing.state !== "input-streaming") return data;
2903
+ const nextPart = {
2904
+ input: void 0,
2905
+ inputText: (existing?.state === "input-streaming" ? existing.inputText : "") + event.data.inputTextDelta,
2906
+ state: "input-streaming",
2907
+ stepIndex: event.data.stepIndex,
2908
+ toolCallId: event.data.callId,
2909
+ toolMetadata: existing?.toolMetadata ?? { eve: {
2910
+ kind: "unknown",
2911
+ name: event.data.toolName
2912
+ } },
2913
+ toolName: event.data.toolName,
2914
+ type: "dynamic-tool"
2854
2915
  };
2916
+ return upsertToolPart(data, event.data.turnId, event.data.stepIndex, nextPart);
2855
2917
  }
2856
- const reader = this.#ensureStream(streamOptions).subscribe(input.signal);
2857
- try {
2858
- if (input.inputResponses === void 0) {
2859
- const { message, ...options } = input;
2860
- return {
2861
- response: await this.#session.send(message, options),
2862
- reader
2863
- };
2918
+ case "actions.requested": {
2919
+ let next = data;
2920
+ for (const action of event.data.actions) {
2921
+ const existing = findToolPart(next, action.callId);
2922
+ if (existing !== void 0 && existing.state !== "input-streaming") continue;
2923
+ const descriptor = normalizeActionRequest(action);
2924
+ next = updateAssistantMessage(next, event.data.turnId, (message) => upsertPart(ensureStepStartPart(message, event.data.stepIndex), {
2925
+ input: "input" in action ? action.input : void 0,
2926
+ state: "input-available",
2927
+ stepIndex: event.data.stepIndex,
2928
+ toolCallId: action.callId,
2929
+ toolMetadata: createToolMetadata(descriptor),
2930
+ toolName: descriptor.toolName,
2931
+ type: "dynamic-tool"
2932
+ }));
2864
2933
  }
2865
- const { inputResponses, ...options } = input;
2866
- return {
2867
- response: await this.#session.respond(inputResponses, options),
2868
- reader
2869
- };
2870
- } catch (error) {
2871
- reader[Symbol.dispose]();
2872
- throw error;
2934
+ return next;
2873
2935
  }
2874
- }
2875
- #ensureStream(options = {}) {
2876
- if (this.#stream !== void 0 && !this.#stream.ended) {
2877
- this.#stream.setOptions(options);
2878
- return this.#stream;
2936
+ case "input.requested": {
2937
+ let next = data;
2938
+ for (const request of event.data.requests) {
2939
+ const existing = findToolPart(next, request.action.callId);
2940
+ if (existing?.approval?.id === request.requestId || existing !== void 0 && isSettledToolPart(existing)) continue;
2941
+ const descriptor = normalizeActionRequest(request.action);
2942
+ next = updateAssistantMessage(next, event.data.turnId, (message) => upsertPart(ensureStepStartPart(message, event.data.stepIndex), {
2943
+ approval: { id: request.requestId },
2944
+ input: request.action.input,
2945
+ state: "approval-requested",
2946
+ stepIndex: event.data.stepIndex,
2947
+ toolCallId: request.action.callId,
2948
+ toolMetadata: createToolMetadata(descriptor, { inputRequest: toMessageInputRequest(request) }),
2949
+ toolName: descriptor.toolName,
2950
+ type: "dynamic-tool"
2951
+ }));
2952
+ }
2953
+ return next;
2879
2954
  }
2880
- if (this.#session === void 0) throw new Error("A session is required before opening its stream.");
2881
- const session = this.#session;
2882
- const generation = this.#prewarmGeneration;
2883
- this.#stream = new SessionEventStream(session, {
2884
- ...options,
2885
- onEvent: (event) => {
2886
- if (generation === this.#prewarmGeneration) this.#acceptServerEvent(event);
2887
- },
2888
- onError: (error) => {
2889
- if (generation !== this.#prewarmGeneration) return;
2890
- this.#stream = void 0;
2891
- if (this.#activeTurn !== void 0) return;
2892
- this.#error = toError(error);
2893
- this.#status = "error";
2894
- this.#callbacks.onError?.(this.#error);
2895
- this.#publish();
2955
+ case "approval.candidate": return data;
2956
+ case "approval.settled": {
2957
+ const existing = findToolPartByApprovalId(data, event.data.requestId);
2958
+ if (existing === void 0) return data;
2959
+ if (event.data.outcome === "approved") {
2960
+ const approval = {
2961
+ approved: true,
2962
+ id: event.data.requestId,
2963
+ reason: void 0
2964
+ };
2965
+ return updateToolPart(data, existing.toolCallId, existing.state === "output-available" ? {
2966
+ ...existing,
2967
+ approval
2968
+ } : {
2969
+ ...toolPartIdentity(existing),
2970
+ approval,
2971
+ state: "approval-responded"
2972
+ });
2896
2973
  }
2897
- });
2898
- return this.#stream;
2899
- }
2900
- #resetPrewarm() {
2901
- this.#prewarmGeneration += 1;
2902
- this.#prewarmController?.abort();
2903
- this.#prewarmController = void 0;
2904
- this.#prewarmPromise = void 0;
2905
- }
2906
- #finishTurn(turn) {
2907
- if (!this.#isActiveTurn(turn)) return;
2908
- turn.resolveResponse(void 0);
2909
- this.#activeTurn = void 0;
2910
- try {
2911
- this.#callbacks.onSessionChange?.(this.#session?.state);
2912
- this.#publish();
2913
- this.#callbacks.onFinish?.(this.#snapshot);
2914
- } finally {
2915
- turn.resolveCompletion();
2974
+ if (existing.state === "output-available") return data;
2975
+ return updateToolPart(data, existing.toolCallId, {
2976
+ ...toolPartIdentity(existing),
2977
+ approval: {
2978
+ approved: false,
2979
+ id: event.data.requestId,
2980
+ reason: "Tool execution was cancelled."
2981
+ },
2982
+ state: "output-denied"
2983
+ });
2916
2984
  }
2917
- }
2918
- #isActiveTurn(turn) {
2919
- return this.#activeTurn === turn;
2920
- }
2921
- #projectInputResponses(input) {
2922
- if (input.inputResponses === void 0 || input.inputResponses.length === 0) return;
2923
- this.#projection.append({
2924
- data: {
2925
- createdAt: Date.now(),
2926
- responses: input.inputResponses
2927
- },
2928
- type: "client.input.responded"
2929
- });
2930
- }
2931
- #acceptServerEvent(event) {
2932
- if (!this.#seenEvents.admit(event)) return;
2933
- const wasStreaming = this.#status === "streaming";
2934
- this.#trackPendingRequests(event);
2935
- this.#events = [...this.#events, event];
2936
- this.#handleReconciliation(this.#messageSubmissions.apply(event));
2937
- this.#callbacks.onEvent?.(event);
2938
- this.#applyTerminalStreamFailure(event);
2939
- const settled = this.#isSettledAt(event);
2940
- if (this.#status !== "resuming" && this.#error === void 0) {
2941
- if ("data" in event && "turnId" in event.data) this.#status = "streaming";
2942
- if (this.#activeTurn === void 0 && settled) this.#status = "ready";
2985
+ case "action.result": {
2986
+ const descriptor = normalizeActionResult(event.data.result);
2987
+ const existing = findToolPart(data, event.data.result.callId);
2988
+ const denied = event.data.status === "rejected" || event.data.error?.code === "TOOL_EXECUTION_DENIED";
2989
+ const failed = event.data.status === "failed" && !denied;
2990
+ const approvalId = existing?.approval?.id ?? event.data.result.callId;
2991
+ const toolMetadata = mergeToolMetadata(existing?.toolMetadata, createToolMetadata(descriptor));
2992
+ const resultPartBase = {
2993
+ input: existing?.input,
2994
+ stepIndex: event.data.stepIndex,
2995
+ toolCallId: event.data.result.callId,
2996
+ toolMetadata,
2997
+ toolName: existing?.toolName ?? descriptor.toolName,
2998
+ type: "dynamic-tool"
2999
+ };
3000
+ let nextPart;
3001
+ if (denied) nextPart = {
3002
+ ...resultPartBase,
3003
+ approval: {
3004
+ approved: false,
3005
+ id: approvalId,
3006
+ reason: event.data.error?.message
3007
+ },
3008
+ state: "output-denied"
3009
+ };
3010
+ else if (failed) nextPart = {
3011
+ ...resultPartBase,
3012
+ approval: approvedApproval(existing),
3013
+ errorText: event.data.error?.message ?? stringifyUnknown(event.data.result.output),
3014
+ state: "output-error"
3015
+ };
3016
+ else nextPart = {
3017
+ ...resultPartBase,
3018
+ approval: approvedApproval(existing),
3019
+ output: event.data.result.output,
3020
+ state: "output-available"
3021
+ };
3022
+ return upsertToolPart(data, event.data.turnId, event.data.stepIndex, nextPart);
2943
3023
  }
2944
- this.#callbacks.onSessionChange?.(this.#session?.state);
2945
- if (this.#status !== "resuming") this.#publish();
2946
- if (this.#activeTurn === void 0 && wasStreaming && settled) this.#callbacks.onFinish?.(this.#snapshot);
2947
- }
2948
- #trackPendingRequests(event) {
2949
- updatePendingAuthorizations(this.#pendingAuthorizations, event);
2950
- updatePendingInputRequests(this.#pendingInputRequests, event);
2951
- }
2952
- #isSettledAt(event) {
2953
- return isTurnSegmentBoundary(event, this.#pendingInputRequests) && this.#pendingAuthorizations.size === 0;
2954
- }
2955
- #handleReconciliation(reconciliation) {
2956
- if (reconciliation === void 0) return false;
2957
- let followed = 0;
2958
- for (const id of reconciliation.ids) if (this.#activeTurn?.followUpSubmissionIds.delete(id)) followed += 1;
2959
- if (followed > 0 && this.#activeTurn !== void 0) {
2960
- if (reconciliation.alreadyProjected) this.#activeTurn.receivedFollowUps += followed;
2961
- else {
2962
- const previous = this.#activeTurn.receivedFollowUpEvents.get(reconciliation.event) ?? 0;
2963
- this.#activeTurn.receivedFollowUpEvents.set(reconciliation.event, previous + followed);
2964
- }
3024
+ case "action.partial": {
3025
+ const existing = findToolPart(data, event.data.result.callId);
3026
+ if (existing !== void 0 && isSettledToolPart(existing)) return data;
3027
+ const descriptor = normalizeActionResult(event.data.result);
3028
+ const nextPart = {
3029
+ approval: approvedApproval(existing),
3030
+ input: existing?.input,
3031
+ output: event.data.result.output,
3032
+ partial: true,
3033
+ state: "output-available",
3034
+ stepIndex: event.data.stepIndex,
3035
+ toolCallId: event.data.result.callId,
3036
+ toolMetadata: mergeToolMetadata(existing?.toolMetadata, createToolMetadata(descriptor)),
3037
+ toolName: existing?.toolName ?? descriptor.toolName,
3038
+ type: "dynamic-tool"
3039
+ };
3040
+ return upsertToolPart(data, event.data.turnId, event.data.stepIndex, nextPart);
2965
3041
  }
2966
- return true;
2967
- }
2968
- #applyTerminalStreamFailure(event) {
2969
- const error = toTerminalStreamFailureError(event);
2970
- if (error === void 0) return;
2971
- this.#status = "error";
2972
- this.#messageSubmissions.failAll(error);
2973
- if (this.#error === void 0) {
2974
- this.#error = error;
2975
- this.#callbacks.onError?.(error);
3042
+ case "task.settled": {
3043
+ const existing = findToolPart(data, event.data.callId);
3044
+ if (existing === void 0) return data;
3045
+ return replaceToolPart(data, createSettledTaskPart(existing, event));
2976
3046
  }
3047
+ case "authorization.required": return updateAssistantMessage(data, event.data.turnId, (message) => upsertPart(ensureStepStartPart(message, event.data.stepIndex), createAuthorizationRequiredPart(event)));
3048
+ case "authorization.completed": return completeAuthorization(data, event);
3049
+ case "message.appended": return updateAssistantMessage(data, event.data.turnId, (message) => messageRun.transition(ensureStepStartPart(message, event.data.stepIndex), {
3050
+ kind: "append",
3051
+ delta: event.data.messageDelta,
3052
+ id: event.meta?.id,
3053
+ stepIndex: event.data.stepIndex,
3054
+ type: "text"
3055
+ }));
3056
+ case "message.completed": return updateAssistantMessage(data, event.data.turnId, (message) => messageRun.transition(ensureStepStartPart(message, event.data.stepIndex), {
3057
+ kind: "complete",
3058
+ stepIndex: event.data.stepIndex,
3059
+ text: event.data.message,
3060
+ id: event.meta?.id,
3061
+ type: "text"
3062
+ }));
3063
+ case "result.completed": return updateAssistantMessage(data, event.data.turnId, (message) => ({
3064
+ ...message,
3065
+ metadata: {
3066
+ ...message.metadata,
3067
+ result: event.data.result
3068
+ }
3069
+ }));
3070
+ case "turn.completed": return updateAssistantMessage(data, event.data.turnId, (message) => ({
3071
+ ...message,
3072
+ metadata: {
3073
+ ...message.metadata,
3074
+ status: "complete"
3075
+ },
3076
+ parts: removeStreamingToolParts(closeStreamingRuns(message.parts))
3077
+ }));
3078
+ case "turn.cancelled": return updateAssistantMessage(data, event.data.turnId, (message) => ({
3079
+ ...message,
3080
+ metadata: {
3081
+ ...message.metadata,
3082
+ status: "complete"
3083
+ },
3084
+ parts: removeStreamingToolParts(closeStreamingRuns(message.parts))
3085
+ }));
3086
+ case "turn.failed":
3087
+ if (data.messages.find((message) => message.role === "assistant" && message.metadata?.turnId === event.data.turnId) === void 0) return data;
3088
+ return updateAssistantMessage(data, event.data.turnId, (message) => ({
3089
+ ...message,
3090
+ metadata: {
3091
+ ...message.metadata,
3092
+ status: "complete"
3093
+ },
3094
+ parts: removeStreamingToolParts(closeStreamingRuns(message.parts))
3095
+ }));
3096
+ case "session.failed": return data;
3097
+ default: return data;
2977
3098
  }
2978
- #createSnapshot() {
2979
- return {
2980
- data: this.#projection.data,
2981
- error: this.#error,
2982
- events: this.#events,
2983
- session: this.#session?.state,
2984
- status: this.#status
2985
- };
2986
- }
2987
- #publish() {
2988
- this.#snapshot = this.#createSnapshot();
2989
- for (const subscriber of this.#subscribers) subscriber();
2990
- }
2991
- };
2992
- function detachEveAgentStore(store) {
2993
- store[detachStore]();
2994
3099
  }
2995
- function attachEveAgentStore(store) {
2996
- store[attachStore]();
3100
+ function closeStreamingRuns(parts, stepIndex) {
3101
+ return parts.map((part) => (part.type === "text" || part.type === "reasoning") && part.state === "streaming" && (stepIndex === void 0 || part.stepIndex === stepIndex) ? {
3102
+ ...part,
3103
+ state: "done"
3104
+ } : part);
2997
3105
  }
2998
-
2999
- //#endregion
3000
- //#region src/client/agent-host.ts
3001
- const AGENT_NAME_PATTERN = /^[a-z0-9][a-z0-9_-]*$/;
3002
- const EVE_NAMED_AGENT_ROUTE_PREFIX = "/eve";
3003
- function resolveEveAgentHost(input) {
3004
- if (input.agent === void 0) return input.host ?? "";
3005
- if (input.host !== void 0) throw new Error("useEveAgent cannot combine agent and host. Use one target option.");
3006
- assertValidAgentName(input.agent);
3007
- return `${EVE_NAMED_AGENT_ROUTE_PREFIX}/${input.agent}`;
3106
+ function removeStreamingToolParts(parts) {
3107
+ return parts.filter((part) => part.type !== "dynamic-tool" || part.state !== "input-streaming");
3008
3108
  }
3009
- function assertValidAgentName(name) {
3010
- if (!AGENT_NAME_PATTERN.test(name)) throw new Error(`eve agent name ${JSON.stringify(name)} is invalid. Use lowercase letters, numbers, underscores, or hyphens, starting with a letter or number.`);
3109
+ function respondToInputRequest(data, response) {
3110
+ const existing = findToolPartByApprovalId(data, response.requestId);
3111
+ if (!existing) return data;
3112
+ const approval = { id: response.requestId };
3113
+ if (response.text !== void 0) approval.reason = response.text;
3114
+ const toolMetadata = mergeToolMetadata(existing.toolMetadata, { eve: {
3115
+ inputResponse: response,
3116
+ kind: existing.toolMetadata?.eve?.kind ?? "unknown",
3117
+ name: existing.toolMetadata?.eve?.name ?? existing.toolName
3118
+ } });
3119
+ return updateToolPart(data, existing.toolCallId, existing.state === "output-available" ? {
3120
+ ...existing,
3121
+ approval: {
3122
+ ...approval,
3123
+ approved: true
3124
+ },
3125
+ toolMetadata
3126
+ } : {
3127
+ ...toolPartIdentity(existing),
3128
+ approval,
3129
+ state: "approval-responded",
3130
+ toolMetadata
3131
+ });
3011
3132
  }
3012
-
3013
- //#endregion
3014
- //#region src/client/authorization-message-parts.ts
3015
- function createAuthorizationRequiredPart(event) {
3016
- const displayName = event.data.authorization?.displayName ?? formatAuthorizationDisplayName(event.data.name);
3133
+ function resolveInputRequest(data, resolution) {
3134
+ if (resolution.response !== void 0) return findToolPartByApprovalId(data, resolution.requestId)?.approval?.approved === void 0 ? respondToInputRequest(data, resolution.response) : data;
3135
+ const existing = findToolPartByApprovalId(data, resolution.requestId);
3136
+ if (!existing) return data;
3137
+ return updateToolPart(data, existing.toolCallId, {
3138
+ ...toolPartIdentity(existing),
3139
+ output: { status: resolution.outcome },
3140
+ state: "output-available"
3141
+ });
3142
+ }
3143
+ function toolPartIdentity(part) {
3017
3144
  return {
3018
- authorization: event.data.authorization,
3019
- description: normalizeAuthorizationDescription(event.data.description, event.data.name, displayName),
3020
- displayName,
3021
- name: event.data.name,
3022
- state: "required",
3023
- stepIndex: event.data.stepIndex,
3024
- turnId: event.data.turnId,
3025
- type: "authorization"
3145
+ input: part.input,
3146
+ stepIndex: part.stepIndex,
3147
+ toolCallId: part.toolCallId,
3148
+ toolMetadata: part.toolMetadata,
3149
+ toolName: part.toolName,
3150
+ type: part.type
3026
3151
  };
3027
3152
  }
3028
- function createAuthorizationCompletedPart(event, existing) {
3029
- const displayName = event.data.authorization?.displayName ?? existing?.displayName ?? formatAuthorizationDisplayName(event.data.name);
3153
+ function updateAssistantMessage(data, turnId, update) {
3154
+ const message = data.messages.find((message) => message.role === "assistant" && message.metadata?.turnId === turnId) ?? createAssistantMessage(turnId);
3155
+ return upsertMessage(data, update(message));
3156
+ }
3157
+ function createAssistantMessage(turnId) {
3030
3158
  return {
3031
- authorization: existing?.authorization || event.data.authorization ? {
3032
- ...existing?.authorization,
3033
- ...event.data.authorization
3034
- } : void 0,
3035
- description: existing?.description ?? buildCompletedAuthorizationDescription(displayName, event.data.outcome, event.data.reason),
3036
- displayName,
3037
- name: event.data.name,
3038
- outcome: event.data.outcome,
3039
- reason: event.data.reason,
3040
- state: "completed",
3041
- stepIndex: existing?.stepIndex ?? event.data.stepIndex,
3042
- turnId: existing?.turnId ?? event.data.turnId,
3043
- type: "authorization"
3159
+ id: `${turnId}:assistant`,
3160
+ metadata: {
3161
+ status: "streaming",
3162
+ turnId
3163
+ },
3164
+ parts: [],
3165
+ role: "assistant"
3044
3166
  };
3045
3167
  }
3046
- function buildCompletedAuthorizationDescription(displayName, outcome, reason) {
3047
- if (outcome === "authorized") return `${displayName} connected.`;
3048
- return `${displayName} authorization ${outcome}${reason !== void 0 ? ` (${reason})` : ""}.`;
3168
+ function ensureStepStartPart(message, stepIndex) {
3169
+ const stepStartCount = message.parts.filter((part) => part.type === "step-start").length;
3170
+ if (stepStartCount > stepIndex) return message;
3171
+ const missingCount = stepIndex - stepStartCount + 1;
3172
+ return {
3173
+ ...message,
3174
+ parts: [...message.parts, ...Array.from({ length: missingCount }, () => ({ type: "step-start" }))]
3175
+ };
3049
3176
  }
3050
- function normalizeAuthorizationDescription(description, name, displayName) {
3051
- if (description === `Authorization required for ${name}`) return `Authorization required for ${displayName}`;
3052
- return description;
3177
+ function upsertPart(message, next) {
3178
+ const index = message.parts.findIndex((part) => partKey(part) === partKey(next));
3179
+ const parts = index === -1 ? [...message.parts, next] : [
3180
+ ...message.parts.slice(0, index),
3181
+ next,
3182
+ ...message.parts.slice(index + 1)
3183
+ ];
3184
+ return {
3185
+ ...message,
3186
+ metadata: {
3187
+ ...message.metadata,
3188
+ status: next.type === "text" && next.state === "done" ? "complete" : "streaming"
3189
+ },
3190
+ parts
3191
+ };
3053
3192
  }
3054
- function formatAuthorizationDisplayName(name) {
3055
- if (name.length === 0) return name;
3056
- return `${name.charAt(0).toUpperCase()}${name.slice(1)}`;
3193
+ function upsertToolPart(data, turnId, stepIndex, part) {
3194
+ const updated = updateToolPart(data, part.toolCallId, part);
3195
+ return updated !== data ? updated : updateAssistantMessage(data, turnId, (message) => upsertPart(ensureStepStartPart(message, stepIndex), part));
3057
3196
  }
3058
-
3059
- //#endregion
3060
- //#region src/shared/action-request-name.ts
3061
- function actionRequestName(action) {
3062
- switch (action.kind) {
3063
- case "load-skill": return "load_skill";
3064
- case "subagent-call": return action.subagentName;
3065
- case "remote-agent-call": return action.remoteAgentName;
3066
- case "tool-call":
3067
- case "workflow-tool-call": return action.toolName;
3197
+ function updateToolPart(data, toolCallId, next) {
3198
+ const message = data.messages.find((candidate) => candidate.role === "assistant" && candidate.parts.some((part) => part.type === "dynamic-tool" && part.toolCallId === toolCallId));
3199
+ if (!message) return data;
3200
+ return upsertMessage(data, upsertPart(message, next));
3201
+ }
3202
+ function replaceToolPart(data, next) {
3203
+ const message = data.messages.find((candidate) => candidate.parts.some((part) => part.type === "dynamic-tool" && part.toolCallId === next.toolCallId));
3204
+ if (message === void 0) return data;
3205
+ return upsertMessage(data, {
3206
+ ...message,
3207
+ parts: message.parts.map((part) => partKey(part) === partKey(next) ? next : part)
3208
+ });
3209
+ }
3210
+ function completeAuthorization(data, event) {
3211
+ const existing = findPendingAuthorizationPart(data, event.data.name, event.data.attemptId);
3212
+ const next = createAuthorizationCompletedPart(event, existing);
3213
+ return updateAssistantMessage(data, existing?.turnId ?? event.data.turnId, (message) => upsertPart(ensureStepStartPart(message, next.stepIndex), next));
3214
+ }
3215
+ function findToolPart(data, toolCallId) {
3216
+ for (const message of data.messages) for (const part of message.parts) if (part.type === "dynamic-tool" && part.toolCallId === toolCallId) return part;
3217
+ }
3218
+ function isSettledToolPart(part) {
3219
+ return part.state === "output-denied" || part.state === "output-error" || part.state === "output-available" && part.partial !== true;
3220
+ }
3221
+ function findPendingAuthorizationPart(data, name, attemptId) {
3222
+ for (let messageIndex = data.messages.length - 1; messageIndex >= 0; messageIndex -= 1) {
3223
+ const message = data.messages[messageIndex];
3224
+ if (message?.role !== "assistant") continue;
3225
+ for (let partIndex = message.parts.length - 1; partIndex >= 0; partIndex -= 1) {
3226
+ const part = message.parts[partIndex];
3227
+ if (part?.type === "authorization" && part.state === "required" && (attemptId === void 0 ? part.attemptId === void 0 && part.name === name : part.attemptId === attemptId)) return part;
3228
+ }
3068
3229
  }
3069
3230
  }
3070
-
3071
- //#endregion
3072
- //#region src/client/message-action-parts.ts
3073
- function toMessageInputRequest(request) {
3074
- return {
3075
- allowFreeform: request.allowFreeform,
3076
- display: request.display,
3077
- kind: request.kind,
3078
- options: request.options,
3079
- prompt: request.prompt,
3080
- requestId: request.requestId
3081
- };
3231
+ function findToolPartByApprovalId(data, approvalId) {
3232
+ for (const message of data.messages) for (const part of message.parts) if (part.type === "dynamic-tool" && part.approval?.id === approvalId) return part;
3082
3233
  }
3083
- function createToolMetadata(descriptor, extra) {
3084
- return { eve: {
3085
- inputRequest: extra?.inputRequest,
3086
- kind: descriptor.kind,
3087
- name: descriptor.name
3088
- } };
3234
+
3235
+ //#endregion
3236
+ //#region src/client/conversation-reducer.ts
3237
+ function initialConversationState() {
3238
+ return {
3239
+ messages: [],
3240
+ turns: {},
3241
+ inputs: {},
3242
+ tasks: {},
3243
+ agents: {}
3244
+ };
3089
3245
  }
3090
- function mergeToolMetadata(current, next) {
3091
- const kind = next.eve?.kind ?? current?.eve?.kind ?? "unknown";
3092
- const name = next.eve?.name ?? current?.eve?.name ?? "unknown";
3093
- return { eve: {
3094
- ...current?.eve,
3095
- ...next.eve,
3096
- inputRequest: next.eve?.inputRequest ?? current?.eve?.inputRequest,
3097
- inputResponse: next.eve?.inputResponse ?? current?.eve?.inputResponse,
3098
- kind,
3099
- name
3100
- } };
3246
+ function updateTurn(state, turnId, update) {
3247
+ const turn = state.turns[turnId];
3248
+ if (turn === void 0) return state;
3249
+ const next = update(turn);
3250
+ return next === turn ? state : {
3251
+ ...state,
3252
+ turns: {
3253
+ ...state.turns,
3254
+ [turnId]: next
3255
+ }
3256
+ };
3101
3257
  }
3102
- function approvedApproval(part) {
3103
- if (!part?.approval?.id) return;
3258
+ function updateTask(state, taskId, update) {
3259
+ const task = state.tasks[taskId];
3260
+ if (task === void 0) return state;
3261
+ const next = update(task);
3262
+ return next === task ? state : {
3263
+ ...state,
3264
+ tasks: {
3265
+ ...state.tasks,
3266
+ [taskId]: next
3267
+ }
3268
+ };
3269
+ }
3270
+ function updateObservation(state, sessionId, update) {
3271
+ const agent = state.agents[sessionId];
3272
+ if (agent === void 0) return state;
3273
+ const observation = update(agent.observation);
3274
+ if (observation === agent.observation) return state;
3104
3275
  return {
3105
- approved: true,
3106
- id: part.approval.id,
3107
- isAutomatic: part.approval.isAutomatic,
3108
- reason: part.approval.reason
3276
+ ...state,
3277
+ agents: {
3278
+ ...state.agents,
3279
+ [sessionId]: {
3280
+ ...agent,
3281
+ observation
3282
+ }
3283
+ }
3109
3284
  };
3110
3285
  }
3111
- function normalizeActionRequest(action) {
3112
- const name = actionRequestName(action);
3113
- switch (action.kind) {
3114
- case "load-skill": return {
3115
- kind: "load-skill",
3116
- name,
3117
- toolName: "eve:load-skill"
3118
- };
3119
- case "tool-call":
3120
- case "workflow-tool-call": return {
3121
- kind: "tool-call",
3122
- name,
3123
- toolName: name
3124
- };
3125
- case "subagent-call":
3126
- case "remote-agent-call": return {
3127
- kind: "subagent-call",
3128
- name,
3129
- toolName: `eve:subagent:${name}`
3130
- };
3131
- }
3286
+ function observedConversation(observation) {
3287
+ return observation.status === "not-followed" ? void 0 : observation.conversation;
3132
3288
  }
3133
- function normalizeActionResult(result) {
3134
- switch (result.kind) {
3135
- case "load-skill-result": return {
3136
- kind: "load-skill",
3137
- name: result.name ?? "load_skill",
3138
- toolName: "eve:load-skill"
3139
- };
3140
- case "tool-result": return {
3141
- kind: "tool-call",
3142
- name: result.toolName,
3143
- toolName: result.toolName
3289
+ function reduceConversationLifecycle(state, event) {
3290
+ switch (event.type) {
3291
+ case "turn.started": return {
3292
+ ...state,
3293
+ activeTurnId: event.data.turnId,
3294
+ turns: {
3295
+ ...state.turns,
3296
+ [event.data.turnId]: {
3297
+ turnId: event.data.turnId,
3298
+ status: "active"
3299
+ }
3300
+ }
3144
3301
  };
3145
- case "subagent-result": return {
3146
- kind: "subagent-call",
3147
- name: result.subagentName,
3148
- toolName: `eve:subagent:${result.subagentName}`
3302
+ case "turn.waiting": return updateTurn(state, event.data.turnId, (turn) => turn.status === "active" && !turn.waiting ? {
3303
+ ...turn,
3304
+ waiting: true
3305
+ } : turn);
3306
+ case "step.started": return updateTurn(state, event.data.turnId, (turn) => turn.waiting ? {
3307
+ turnId: turn.turnId,
3308
+ status: turn.status
3309
+ } : turn);
3310
+ case "turn.completed":
3311
+ case "turn.cancelled":
3312
+ case "turn.failed": {
3313
+ const { turnId } = event.data;
3314
+ return {
3315
+ ...state,
3316
+ activeTurnId: state.activeTurnId === turnId ? void 0 : state.activeTurnId,
3317
+ turns: {
3318
+ ...state.turns,
3319
+ [turnId]: {
3320
+ turnId,
3321
+ status: event.type === "turn.completed" ? "completed" : event.type === "turn.failed" ? "failed" : "cancelled"
3322
+ }
3323
+ }
3324
+ };
3325
+ }
3326
+ case "session.waiting":
3327
+ case "session.completed":
3328
+ case "session.failed": return state.activeTurnId === void 0 ? state : {
3329
+ ...state,
3330
+ activeTurnId: void 0
3149
3331
  };
3332
+ case "task.started": {
3333
+ const { callId, kind, name, taskId, turnId } = event.data;
3334
+ const task = state.tasks[taskId] ?? {
3335
+ taskId,
3336
+ name,
3337
+ kind,
3338
+ calls: {}
3339
+ };
3340
+ if (task.calls[callId] !== void 0) return state;
3341
+ return {
3342
+ ...state,
3343
+ tasks: {
3344
+ ...state.tasks,
3345
+ [taskId]: {
3346
+ ...task,
3347
+ calls: {
3348
+ ...task.calls,
3349
+ [callId]: {
3350
+ callId,
3351
+ turnId,
3352
+ status: "working"
3353
+ }
3354
+ }
3355
+ }
3356
+ }
3357
+ };
3358
+ }
3359
+ case "task.settled": {
3360
+ const { callId, error, output, status, taskId } = event.data;
3361
+ return updateTask(state, taskId, (task) => {
3362
+ const call = task.calls[callId];
3363
+ if (call === void 0 || call.status !== "working") return task;
3364
+ const settled = {
3365
+ callId,
3366
+ turnId: call.turnId,
3367
+ status
3368
+ };
3369
+ return {
3370
+ ...task,
3371
+ calls: {
3372
+ ...task.calls,
3373
+ [callId]: status === "completed" && output !== void 0 ? {
3374
+ ...settled,
3375
+ output
3376
+ } : status === "failed" && error !== void 0 ? {
3377
+ ...settled,
3378
+ error
3379
+ } : settled
3380
+ }
3381
+ };
3382
+ });
3383
+ }
3384
+ case "agent.started": {
3385
+ const { callId, name, sessionId, taskId, turnId } = event.data;
3386
+ if (state.agents[sessionId] !== void 0) return state;
3387
+ const agent = {
3388
+ sessionId,
3389
+ name,
3390
+ callId,
3391
+ turnId,
3392
+ observation: { status: "not-followed" }
3393
+ };
3394
+ if (taskId !== void 0) agent.taskId = taskId;
3395
+ return {
3396
+ ...state,
3397
+ agents: {
3398
+ ...state.agents,
3399
+ [sessionId]: agent
3400
+ }
3401
+ };
3402
+ }
3403
+ case "input.requested": {
3404
+ const inputs = { ...state.inputs };
3405
+ for (const request of event.data.requests) {
3406
+ if (inputs[request.requestId] !== void 0) continue;
3407
+ const input = {
3408
+ request,
3409
+ turnId: event.data.turnId,
3410
+ stepIndex: event.data.stepIndex,
3411
+ status: "open"
3412
+ };
3413
+ if (event.data.taskId !== void 0) input.taskId = event.data.taskId;
3414
+ inputs[request.requestId] = input;
3415
+ }
3416
+ return {
3417
+ ...state,
3418
+ inputs
3419
+ };
3420
+ }
3421
+ case "client.input.responded": {
3422
+ const inputs = { ...state.inputs };
3423
+ for (const response of event.data.responses) {
3424
+ const current = inputs[response.requestId];
3425
+ if (current?.status !== "open") continue;
3426
+ inputs[response.requestId] = {
3427
+ ...current,
3428
+ response,
3429
+ status: "responded"
3430
+ };
3431
+ }
3432
+ return {
3433
+ ...state,
3434
+ inputs
3435
+ };
3436
+ }
3437
+ case "approval.candidate": {
3438
+ const current = state.inputs[event.data.requestId];
3439
+ if (current === void 0 || current.status === "settled") return state;
3440
+ if (event.data.outcome === "pending") return state;
3441
+ return {
3442
+ ...state,
3443
+ inputs: {
3444
+ ...state.inputs,
3445
+ [event.data.requestId]: {
3446
+ ...current,
3447
+ status: "open",
3448
+ response: void 0
3449
+ }
3450
+ }
3451
+ };
3452
+ }
3453
+ case "approval.settled": {
3454
+ const current = state.inputs[event.data.requestId];
3455
+ if (current === void 0 || current.status === "settled") return state;
3456
+ return {
3457
+ ...state,
3458
+ inputs: {
3459
+ ...state.inputs,
3460
+ [event.data.requestId]: {
3461
+ ...current,
3462
+ status: "settled",
3463
+ outcome: event.data.outcome
3464
+ }
3465
+ }
3466
+ };
3467
+ }
3468
+ case "input.resolved": {
3469
+ const inputs = { ...state.inputs };
3470
+ for (const resolution of event.data.resolutions) {
3471
+ const current = inputs[resolution.requestId];
3472
+ if (current === void 0 || current.status === "settled") continue;
3473
+ inputs[resolution.requestId] = {
3474
+ ...current,
3475
+ status: "settled",
3476
+ outcome: resolution.outcome,
3477
+ response: resolution.response ?? current.response
3478
+ };
3479
+ }
3480
+ return {
3481
+ ...state,
3482
+ inputs
3483
+ };
3484
+ }
3485
+ default: return state;
3150
3486
  }
3151
3487
  }
3152
- function stringifyUnknown(value) {
3153
- if (typeof value === "string") return value;
3154
- try {
3155
- return JSON.stringify(value);
3156
- } catch {
3157
- return "Action failed.";
3488
+ const messageReducer = defaultMessageReducer();
3489
+ function reduceConversation(state, event) {
3490
+ switch (event.type) {
3491
+ case "client.agent.following": return updateObservation(state, event.data.sessionId, (observation) => observation.status === "following" ? observation : {
3492
+ status: "following",
3493
+ conversation: observedConversation(observation) ?? initialConversationState()
3494
+ });
3495
+ case "client.agent.observed": return updateObservation(state, event.data.sessionId, (observation) => observation.status === "following" ? {
3496
+ status: "following",
3497
+ conversation: reduceConversation(observation.conversation, event.data.event)
3498
+ } : observation);
3499
+ case "client.agent.idle": return updateObservation(state, event.data.sessionId, (observation) => observation.status === "following" ? {
3500
+ status: "idle",
3501
+ conversation: observation.conversation
3502
+ } : observation);
3503
+ case "client.agent.unavailable": return updateObservation(state, event.data.sessionId, (observation) => {
3504
+ const conversation = observedConversation(observation);
3505
+ return conversation === void 0 ? { status: "unavailable" } : {
3506
+ status: "unavailable",
3507
+ conversation
3508
+ };
3509
+ });
3510
+ default: {
3511
+ const projected = messageReducer.reduce(state, event);
3512
+ return reduceConversationLifecycle({
3513
+ ...state,
3514
+ ...projected
3515
+ }, event);
3516
+ }
3158
3517
  }
3159
3518
  }
3519
+ const canonicalConversationReducer = {
3520
+ initial: initialConversationState,
3521
+ reduce: reduceConversation
3522
+ };
3523
+ const conversationReducer = canonicalConversationReducer;
3160
3524
 
3161
3525
  //#endregion
3162
- //#region src/client/message-reducer-primitives.ts
3163
- function projectReceivedParts(parts, message) {
3164
- return parts?.map((part) => part.type === "text" ? {
3165
- state: "done",
3166
- text: part.text,
3167
- type: "text"
3168
- } : {
3169
- filename: part.filename,
3170
- mediaType: part.mediaType,
3171
- size: part.size,
3172
- type: "file",
3173
- url: part.url
3174
- }) ?? [{
3175
- state: "done",
3176
- text: message,
3177
- type: "text"
3178
- }];
3526
+ //#region src/protocol/event-dedupe.ts
3527
+ function createEventDeduper() {
3528
+ const seen = /* @__PURE__ */ new Set();
3529
+ return {
3530
+ admit(event) {
3531
+ const id = event.meta?.id;
3532
+ if (id === void 0) return true;
3533
+ if (seen.has(id)) return false;
3534
+ seen.add(id);
3535
+ return true;
3536
+ },
3537
+ get size() {
3538
+ return seen.size;
3539
+ }
3540
+ };
3179
3541
  }
3180
- function partKey(part) {
3181
- switch (part.type) {
3182
- case "text": return `text:${part.stepIndex ?? 0}`;
3183
- case "reasoning": return `reasoning:${part.stepIndex ?? 0}`;
3184
- case "file": return `file:${part.stepIndex ?? 0}:${part.filename ?? part.url ?? part.mediaType}`;
3185
- case "step-start": return "step-start";
3186
- case "authorization": return `authorization:${part.turnId}:${part.stepIndex}:${part.name}`;
3187
- case "dynamic-tool": return `dynamic-tool:${part.toolCallId}`;
3542
+
3543
+ //#endregion
3544
+ //#region src/client/session-event-stream.ts
3545
+ var SessionEventStream = class {
3546
+ #controller = new AbortController();
3547
+ #readers = /* @__PURE__ */ new Set();
3548
+ #caughtUp = Promise.withResolvers();
3549
+ caughtUp = this.#caughtUp.promise;
3550
+ #ended = false;
3551
+ #error;
3552
+ #headers;
3553
+ #reconnectPolicy;
3554
+ constructor(session, options) {
3555
+ this.setOptions(options);
3556
+ this.caughtUp.catch(() => {});
3557
+ if (!options.catchUp) this.#caughtUp.resolve();
3558
+ (async () => {
3559
+ try {
3560
+ for await (const event of followClientSession(session, {
3561
+ signal: this.#controller.signal,
3562
+ resolveHeaders: () => this.#headers,
3563
+ resolveReconnectPolicy: () => this.#reconnectPolicy,
3564
+ startIndex: options.startIndex,
3565
+ onCaughtUp: options.catchUp ? () => this.#caughtUp.resolve() : void 0
3566
+ })) {
3567
+ if (this.#controller.signal.aborted) return;
3568
+ options.onEvent(event);
3569
+ for (const reader of this.#readers) reader.push(event);
3570
+ if (event.type === "session.completed" || event.type === "session.failed") break;
3571
+ }
3572
+ this.#caughtUp.resolve();
3573
+ this.#finish();
3574
+ } catch (error) {
3575
+ this.#caughtUp.reject(error);
3576
+ this.#finish(error);
3577
+ if (!this.#controller.signal.aborted) options.onError(error);
3578
+ }
3579
+ })();
3580
+ }
3581
+ subscribe(signal) {
3582
+ const reader = new SessionEventReader(() => this.#readers.delete(reader), signal);
3583
+ if (this.#ended) reader.end(this.#error);
3584
+ else this.#readers.add(reader);
3585
+ return reader;
3586
+ }
3587
+ get ended() {
3588
+ return this.#ended;
3589
+ }
3590
+ setOptions(options) {
3591
+ if ("headers" in options) this.#headers = options.headers;
3592
+ if ("streamReconnectPolicy" in options) this.#reconnectPolicy = options.streamReconnectPolicy;
3593
+ }
3594
+ close() {
3595
+ const error = new DOMException("Session stream was detached.", "AbortError");
3596
+ this.#controller.abort(error);
3597
+ this.#caughtUp.reject(error);
3598
+ this.#finish(error);
3599
+ }
3600
+ #finish(error) {
3601
+ if (this.#ended) return;
3602
+ this.#ended = true;
3603
+ this.#error = error;
3604
+ for (const reader of this.#readers) reader.end(error);
3605
+ }
3606
+ };
3607
+ var SessionEventReader = class {
3608
+ #events = [];
3609
+ #wake = Promise.withResolvers();
3610
+ #ended = false;
3611
+ #error;
3612
+ #dispose;
3613
+ constructor(unsubscribe, signal) {
3614
+ const abort = () => this.end(signal?.reason);
3615
+ signal?.addEventListener("abort", abort, { once: true });
3616
+ this.#dispose = () => {
3617
+ signal?.removeEventListener("abort", abort);
3618
+ unsubscribe();
3619
+ };
3620
+ if (signal?.aborted) abort();
3621
+ }
3622
+ push(event) {
3623
+ if (this.#ended) return;
3624
+ this.#events.push(event);
3625
+ this.#wake.resolve();
3626
+ }
3627
+ end(error) {
3628
+ if (this.#ended) return;
3629
+ this.#ended = true;
3630
+ this.#error = error;
3631
+ this.#wake.resolve();
3632
+ }
3633
+ [Symbol.dispose]() {
3634
+ this.end();
3635
+ this.#events = [];
3636
+ this.#dispose();
3188
3637
  }
3189
- }
3190
- function upsertMessage(data, next) {
3191
- const index = data.messages.findIndex((message) => message.id === next.id);
3192
- if (index === -1) return { messages: [...data.messages, next] };
3193
- return { messages: [
3194
- ...data.messages.slice(0, index),
3195
- next,
3196
- ...data.messages.slice(index + 1)
3197
- ] };
3198
- }
3199
- function removeStreamingToolPartsForTurn(data, turnId) {
3200
- const index = data.messages.findIndex((message) => message.role === "assistant" && message.metadata?.turnId === turnId);
3201
- const message = data.messages[index];
3202
- if (message === void 0) return data;
3203
- return upsertMessage(data, {
3204
- ...message,
3205
- parts: message.parts.filter((part) => part.type !== "dynamic-tool" || part.state !== "input-streaming")
3206
- });
3207
- }
3208
- function optimisticUserMessageId(submissionId) {
3209
- return `optimistic:${submissionId}:user`;
3210
- }
3638
+ discard() {
3639
+ this.#events = [];
3640
+ }
3641
+ async *[Symbol.asyncIterator]() {
3642
+ for (;;) {
3643
+ while (this.#events.length > 0) yield this.#events.shift();
3644
+ if (this.#ended) {
3645
+ if (this.#error !== void 0) throw this.#error;
3646
+ return;
3647
+ }
3648
+ this.#wake = Promise.withResolvers();
3649
+ await this.#wake.promise;
3650
+ }
3651
+ }
3652
+ };
3211
3653
 
3212
3654
  //#endregion
3213
- //#region src/client/message-run-parts.ts
3214
- function append(message, append) {
3215
- const current = latestStreamingRun(message, append.type, append.stepIndex);
3216
- return upsert(message, {
3217
- state: "streaming",
3218
- stepIndex: append.stepIndex,
3219
- text: (current?.text ?? "") + append.delta,
3220
- type: append.type
3221
- });
3222
- }
3223
- function latestStreamingRun(message, type, stepIndex) {
3224
- for (let index = message.parts.length - 1; index >= 0; index -= 1) {
3225
- const part = message.parts[index];
3226
- if (part?.type === type && part.stepIndex === stepIndex) return part.state === "streaming" ? part : void 0;
3655
+ //#region src/client/conversation-client.ts
3656
+ var ConversationClient = class {
3657
+ projection;
3658
+ #conversation;
3659
+ #cursors = /* @__PURE__ */ new Map();
3660
+ #seenEvents = createEventDeduper();
3661
+ #follower;
3662
+ #stream;
3663
+ #onChange;
3664
+ #onConversationChange;
3665
+ constructor(projection, onChange, onConversationChange) {
3666
+ this.projection = projection;
3667
+ this.#conversation = projection.reducer === conversationReducer ? projection : new EveAgentProjection(canonicalConversationReducer, []);
3668
+ this.#onChange = onChange;
3669
+ this.#onConversationChange = onConversationChange;
3227
3670
  }
3228
- }
3229
- function upsert(message, next) {
3230
- let lastIndex = -1;
3231
- for (let index = message.parts.length - 1; index >= 0; index -= 1) {
3232
- const part = message.parts[index];
3233
- if (part?.type === next.type && part.stepIndex === next.stepIndex) {
3234
- lastIndex = index;
3235
- break;
3671
+ get data() {
3672
+ return this.projection.data;
3673
+ }
3674
+ get conversation() {
3675
+ return this.#conversation.data;
3676
+ }
3677
+ get projections() {
3678
+ return this.#conversation === this.projection ? [this.projection] : [this.#conversation, this.projection];
3679
+ }
3680
+ get following() {
3681
+ return this.#follower !== void 0;
3682
+ }
3683
+ append(event) {
3684
+ const previous = this.data;
3685
+ const previousConversation = this.conversation;
3686
+ this.#appendRoot(event);
3687
+ if (previous !== this.data) this.#onChange(this.data, previous);
3688
+ else if (previousConversation !== this.conversation) this.#onConversationChange?.(this.conversation, previousConversation);
3689
+ }
3690
+ projectResponses(responses) {
3691
+ if (!responses?.length) return void 0;
3692
+ const event = {
3693
+ data: {
3694
+ createdAt: Date.now(),
3695
+ responses
3696
+ },
3697
+ type: "client.input.responded"
3698
+ };
3699
+ this.append(event);
3700
+ return () => this.#retract(event);
3701
+ }
3702
+ replaceResponses(retract, input) {
3703
+ retract?.();
3704
+ assertAnswerable(input, this.conversation);
3705
+ return this.projectResponses(input.inputResponses);
3706
+ }
3707
+ #retract(event) {
3708
+ const previous = this.data;
3709
+ const previousConversation = this.conversation;
3710
+ for (const projection of this.projections) projection.remove((entry) => entry === event);
3711
+ if (previous !== this.data) this.#onChange(this.data, previous);
3712
+ else if (previousConversation !== this.conversation) this.#onConversationChange?.(this.conversation, previousConversation);
3713
+ }
3714
+ observe(event, options = {}) {
3715
+ if (!this.#seenEvents.admit(event)) return false;
3716
+ options.onAccepted?.(event);
3717
+ const previous = this.data;
3718
+ const previousConversation = this.conversation;
3719
+ if (options.project) options.project(event);
3720
+ else this.#appendRoot(event);
3721
+ if (options.notify !== false) {
3722
+ if (previous !== this.data) this.#onChange(this.data, previous);
3723
+ else if (previousConversation !== this.conversation) this.#onConversationChange?.(this.conversation, previousConversation);
3236
3724
  }
3725
+ this.#follower?.acceptParentEvent(event);
3726
+ this.#follower?.reconcile();
3727
+ return true;
3728
+ }
3729
+ hydrate(event) {
3730
+ if (!this.#seenEvents.admit(event)) return false;
3731
+ this.#appendRoot(event);
3732
+ return true;
3733
+ }
3734
+ follow(session, events = []) {
3735
+ this.#follower?.abortAll();
3736
+ const follower = new AgentStreamFollower({
3737
+ session,
3738
+ cursors: this.#cursors,
3739
+ getState: () => this.conversation,
3740
+ onFollowing: (sessionId) => this.#appendChild({
3741
+ type: "client.agent.following",
3742
+ data: { sessionId }
3743
+ }),
3744
+ onEvent: (sessionId, event) => this.#appendChild({
3745
+ type: "client.agent.observed",
3746
+ data: {
3747
+ sessionId,
3748
+ event
3749
+ }
3750
+ }),
3751
+ onIdle: (sessionId) => this.#appendChild({
3752
+ type: "client.agent.idle",
3753
+ data: { sessionId }
3754
+ }),
3755
+ onUnavailable: (sessionId) => this.#appendChild({
3756
+ type: "client.agent.unavailable",
3757
+ data: { sessionId }
3758
+ })
3759
+ });
3760
+ this.#follower = follower;
3761
+ for (const event of events) follower.acceptParentEvent(event);
3762
+ follower.reconcile();
3763
+ }
3764
+ #appendRoot(event) {
3765
+ for (const projection of this.projections) projection.append(event);
3766
+ }
3767
+ #appendChild(event) {
3768
+ const previous = this.data;
3769
+ const previousConversation = this.conversation;
3770
+ this.#conversation.append(event);
3771
+ if (previous !== this.data) this.#onChange(this.data, previous);
3772
+ else if (previousConversation !== this.conversation) this.#onConversationChange?.(this.conversation, previousConversation);
3773
+ }
3774
+ stream(session, options) {
3775
+ if (this.#stream !== void 0 && !this.#stream.ended) {
3776
+ this.#stream.setOptions(options);
3777
+ return this.#stream;
3778
+ }
3779
+ this.#stream = new SessionEventStream(session, options);
3780
+ return this.#stream;
3781
+ }
3782
+ stop() {
3783
+ this.#follower?.abortAll();
3784
+ this.#follower = void 0;
3785
+ this.#stream?.close();
3786
+ this.#stream = void 0;
3787
+ }
3788
+ reset() {
3789
+ this.stop();
3790
+ this.#cursors.clear();
3791
+ this.#seenEvents = createEventDeduper();
3792
+ for (const projection of this.projections) projection.reset();
3237
3793
  }
3238
- const parts = lastIndex !== -1 && message.parts[lastIndex].state === "streaming" ? [
3239
- ...message.parts.slice(0, lastIndex),
3240
- next,
3241
- ...message.parts.slice(lastIndex + 1)
3242
- ] : [...message.parts, next];
3243
- return {
3244
- ...message,
3245
- metadata: {
3246
- ...message.metadata,
3247
- status: next.type === "text" && next.state === "done" ? "complete" : "streaming"
3248
- },
3249
- parts
3250
- };
3251
- }
3252
- const messageRun = {
3253
- append,
3254
- upsert
3255
3794
  };
3256
3795
 
3257
3796
  //#endregion
3258
- //#region src/client/message-task-parts.ts
3259
- function createSettledTaskPart(existing, event) {
3260
- const settledPartBase = {
3261
- approval: approvedApproval(existing),
3262
- input: existing.input,
3263
- stepIndex: existing.stepIndex,
3264
- toolCallId: existing.toolCallId,
3265
- toolMetadata: existing.toolMetadata,
3266
- toolName: existing.toolName,
3267
- type: "dynamic-tool"
3268
- };
3269
- switch (event.data.status) {
3270
- case "completed": return {
3271
- ...settledPartBase,
3272
- output: event.data.output,
3273
- state: "output-available"
3274
- };
3275
- case "failed": return {
3276
- ...settledPartBase,
3277
- errorText: event.data.error?.message ?? "Task failed.",
3278
- state: "output-error"
3797
+ //#region src/client/session-turn-dispatch.ts
3798
+ async function dispatchSessionTurn(input) {
3799
+ const { client, session, turn, beforeSend } = input;
3800
+ if (session === void 0) {
3801
+ if (client === void 0) throw new Error("An external eve session is required before sending.");
3802
+ if (turn.message === void 0) throw new Error("Cannot answer an input request before the session starts.");
3803
+ const created = await client.sessions.create({
3804
+ ...turn,
3805
+ message: turn.message
3806
+ });
3807
+ turn.signal?.throwIfAborted();
3808
+ return {
3809
+ ...created,
3810
+ created: true
3279
3811
  };
3280
- case "cancelled": return {
3281
- ...settledPartBase,
3282
- errorText: "Task was cancelled.",
3283
- state: "output-error"
3812
+ }
3813
+ beforeSend?.();
3814
+ if (turn.inputResponses === void 0) {
3815
+ const { message, ...options } = turn;
3816
+ return {
3817
+ session,
3818
+ response: await session.send(message, options),
3819
+ created: false
3284
3820
  };
3285
3821
  }
3286
- }
3287
-
3288
- //#endregion
3289
- //#region src/client/message-reducer.ts
3290
- function receivedMessageEventId(event) {
3291
- return event.meta.id ?? `${event.data.turnId}:${event.data.sequence}`;
3292
- }
3293
- function defaultMessageReducer() {
3822
+ const { inputResponses, ...options } = turn;
3294
3823
  return {
3295
- initial() {
3296
- return { messages: [] };
3297
- },
3298
- reduce(data, event) {
3299
- return reduceMessageData(data, event);
3300
- }
3824
+ session,
3825
+ response: await session.respond(inputResponses, options),
3826
+ created: false
3301
3827
  };
3302
3828
  }
3303
- function reduceMessageData(data, event) {
3304
- switch (event.type) {
3305
- case "client.message.submitted": return upsertMessage(data, {
3306
- id: optimisticUserMessageId(event.data.submissionId),
3307
- metadata: {
3308
- optimistic: true,
3309
- status: "submitted"
3310
- },
3311
- parts: [{
3312
- type: "text",
3313
- text: event.data.message
3314
- }],
3315
- role: "user"
3316
- });
3317
- case "client.message.failed": return upsertMessage(data, {
3318
- id: optimisticUserMessageId(event.data.submissionId),
3319
- metadata: {
3320
- optimistic: true,
3321
- status: "failed"
3322
- },
3323
- parts: [{
3324
- type: "text",
3325
- text: event.data.message
3326
- }],
3327
- role: "user"
3829
+
3830
+ //#endregion
3831
+ //#region src/client/eve-agent-store.ts
3832
+ const detachStore = Symbol("detachEveAgentStore");
3833
+ const attachStore = Symbol("attachEveAgentStore");
3834
+ var EveAgentStore = class {
3835
+ #client;
3836
+ #autoPrewarm;
3837
+ #attached = false;
3838
+ #conversationClient;
3839
+ #followChildStreams;
3840
+ #externalSession;
3841
+ #subscribers = /* @__PURE__ */ new Set();
3842
+ #activeTurn;
3843
+ #callbacks = {};
3844
+ #error;
3845
+ #events;
3846
+ #messageSubmissions;
3847
+ #prewarmGeneration = 0;
3848
+ #prewarmPromise;
3849
+ #prewarmController;
3850
+ #resumePromise;
3851
+ #session;
3852
+ #snapshot;
3853
+ #status = "ready";
3854
+ constructor(init) {
3855
+ this.#autoPrewarm = init.prewarm ?? false;
3856
+ this.#followChildStreams = init.followSubagents ?? false;
3857
+ this.#externalSession = init.session !== void 0;
3858
+ this.#client = this.#externalSession ? void 0 : init.client ?? new Client({
3859
+ auth: init.auth,
3860
+ headers: init.headers,
3861
+ host: init.host ?? ""
3328
3862
  });
3329
- case "input.resolved": {
3330
- let next = data;
3331
- for (const resolution of event.data.resolutions) next = resolveInputRequest(next, resolution);
3332
- return next;
3333
- }
3334
- case "message.received": return upsertMessage(data, {
3335
- id: `${receivedMessageEventId(event)}:user`,
3336
- metadata: {
3337
- status: "complete",
3338
- turnId: event.data.turnId
3339
- },
3340
- parts: projectReceivedParts(event.data.parts, event.data.message),
3341
- role: "user"
3863
+ this.#conversationClient = new ConversationClient(new EveAgentProjection(init.reducer, []), () => this.#publish(), () => this.#publish());
3864
+ this.#events = (init.initialEvents ?? []).filter((event) => this.#conversationClient.hydrate(event));
3865
+ this.#messageSubmissions = new OptimisticMessageSubmissions(this.#conversationClient.projections, init.optimistic ?? true);
3866
+ this.#session = init.session ?? (init.initialSession === void 0 ? void 0 : this.#client?.sessions.attach(init.initialSession.sessionId, { streamIndex: init.initialSession.streamIndex }));
3867
+ this.#snapshot = this.#createSnapshot();
3868
+ }
3869
+ get snapshot() {
3870
+ return this.#snapshot;
3871
+ }
3872
+ setCallbacks(callbacks) {
3873
+ this.#callbacks = callbacks;
3874
+ }
3875
+ subscribe(callback) {
3876
+ this.#subscribers.add(callback);
3877
+ return () => void this.#subscribers.delete(callback);
3878
+ }
3879
+ prewarm() {
3880
+ if (this.#prewarmPromise !== void 0) return this.#prewarmPromise;
3881
+ if (this.#session !== void 0 || this.#externalSession) return Promise.resolve();
3882
+ if (this.#activeTurn !== void 0) return this.#activeTurn.response.then((response) => {
3883
+ if (response === void 0) throw this.#error ?? new DOMException("Session creation was aborted.", "AbortError");
3342
3884
  });
3343
- case "step.started": return updateAssistantMessage(data, event.data.turnId, (message) => ensureStepStartPart(message, event.data.stepIndex));
3344
- case "reasoning.appended": return updateAssistantMessage(data, event.data.turnId, (message) => messageRun.append(ensureStepStartPart(message, event.data.stepIndex), {
3345
- delta: event.data.reasoningDelta,
3346
- stepIndex: event.data.stepIndex,
3347
- type: "reasoning"
3348
- }));
3349
- case "reasoning.completed": return updateAssistantMessage(data, event.data.turnId, (message) => messageRun.upsert(ensureStepStartPart(message, event.data.stepIndex), {
3350
- state: "done",
3351
- stepIndex: event.data.stepIndex,
3352
- text: event.data.reasoning,
3353
- type: "reasoning"
3354
- }));
3355
- case "action.input.appended": {
3356
- const existing = findToolPart(data, event.data.callId);
3357
- if (existing !== void 0 && existing.state !== "input-streaming") return data;
3358
- const nextPart = {
3359
- input: void 0,
3360
- inputText: (existing?.state === "input-streaming" ? existing.inputText : "") + event.data.inputTextDelta,
3361
- state: "input-streaming",
3362
- stepIndex: event.data.stepIndex,
3363
- toolCallId: event.data.callId,
3364
- toolMetadata: existing?.toolMetadata ?? { eve: {
3365
- kind: "unknown",
3366
- name: event.data.toolName
3367
- } },
3368
- toolName: event.data.toolName,
3369
- type: "dynamic-tool"
3370
- };
3371
- if (existing !== void 0) return updateToolPart(data, event.data.callId, nextPart);
3372
- return updateAssistantMessage(data, event.data.turnId, (message) => upsertPart(ensureStepStartPart(message, event.data.stepIndex), nextPart));
3373
- }
3374
- case "actions.requested": {
3375
- let next = data;
3376
- for (const action of event.data.actions) {
3377
- const descriptor = normalizeActionRequest(action);
3378
- next = updateAssistantMessage(next, event.data.turnId, (message) => upsertPart(ensureStepStartPart(message, event.data.stepIndex), {
3379
- input: "input" in action ? action.input : void 0,
3380
- state: "input-available",
3381
- stepIndex: event.data.stepIndex,
3382
- toolCallId: action.callId,
3383
- toolMetadata: createToolMetadata(descriptor),
3384
- toolName: descriptor.toolName,
3385
- type: "dynamic-tool"
3386
- }));
3885
+ const client = this.#client;
3886
+ if (client === void 0) return Promise.reject(/* @__PURE__ */ new Error("This eve agent store does not own a session client."));
3887
+ const generation = this.#prewarmGeneration;
3888
+ const controller = new AbortController();
3889
+ this.#prewarmController = controller;
3890
+ const promise = (async () => {
3891
+ try {
3892
+ const created = await client.sessions.create({ signal: controller.signal });
3893
+ if (generation !== this.#prewarmGeneration) return;
3894
+ this.#error = void 0;
3895
+ if (this.#status === "error") this.#status = "ready";
3896
+ this.#adoptSession(created.session);
3897
+ this.#ensureStream();
3898
+ } catch (error) {
3899
+ if (generation === this.#prewarmGeneration && this.#activeTurn === void 0 && this.#error === void 0) this.#fail(error);
3900
+ throw error;
3901
+ }
3902
+ })();
3903
+ this.#prewarmPromise = promise;
3904
+ const clear = () => {
3905
+ if (this.#prewarmPromise === promise) {
3906
+ this.#prewarmPromise = void 0;
3907
+ this.#prewarmController = void 0;
3387
3908
  }
3388
- return next;
3909
+ };
3910
+ promise.then(clear, clear);
3911
+ return promise;
3912
+ }
3913
+ async send(input) {
3914
+ return await this.#submit(input, this.#callbacks.prepareSend);
3915
+ }
3916
+ async #submit(input, prepareSend) {
3917
+ assertAnswerable(input, this.#conversationClient.conversation);
3918
+ if (this.#activeTurn !== void 0) {
3919
+ if (this.#status === "resuming") throw new Error("eve session is resuming.");
3920
+ return await this.#sendFollowUp(this.#activeTurn, input, prepareSend);
3389
3921
  }
3390
- case "input.requested": {
3391
- let next = data;
3392
- for (const request of event.data.requests) {
3393
- const descriptor = normalizeActionRequest(request.action);
3394
- next = updateAssistantMessage(next, event.data.turnId, (message) => upsertPart(ensureStepStartPart(message, event.data.stepIndex), {
3395
- approval: { id: request.requestId },
3396
- input: request.action.input,
3397
- state: "approval-requested",
3398
- stepIndex: event.data.stepIndex,
3399
- toolCallId: request.action.callId,
3400
- toolMetadata: createToolMetadata(descriptor, { inputRequest: toMessageInputRequest(request) }),
3401
- toolName: descriptor.toolName,
3402
- type: "dynamic-tool"
3403
- }));
3922
+ const turn = createActiveTurn((turn) => turn.acceptedFollowUps > 0 && this.#session !== void 0 ? this.#session.cancel() : turn.response.then((response) => response === void 0 ? { status: "no_active_turn" } : response.cancel()));
3923
+ this.#activeTurn = turn;
3924
+ this.#error = void 0;
3925
+ this.#status = "submitted";
3926
+ let reader;
3927
+ let submissionId;
3928
+ let retractResponses;
3929
+ try {
3930
+ assertExclusiveTurnInput(input);
3931
+ submissionId = this.#messageSubmissions.submit(input, this.#events.length);
3932
+ retractResponses = this.#conversationClient.projectResponses(input.inputResponses);
3933
+ this.#publish();
3934
+ const preparedInput = await (prepareSend === void 0 ? input : waitWithSignal(Promise.resolve(prepareSend(input)), createAbortSignal(input.signal, turn.abortController.signal)));
3935
+ assertExclusiveTurnInput(preparedInput);
3936
+ if (!this.#isActiveTurn(turn)) return;
3937
+ if (preparedInput !== input) {
3938
+ submissionId = this.#messageSubmissions.resubmit(submissionId, preparedInput);
3939
+ retractResponses = this.#conversationClient.replaceResponses(retractResponses, preparedInput);
3940
+ this.#publish();
3404
3941
  }
3405
- return next;
3942
+ const turnInput = {
3943
+ ...preparedInput,
3944
+ signal: createAbortSignal(preparedInput.signal, turn.abortController.signal)
3945
+ };
3946
+ const dispatched = await this.#dispatchTurn(turnInput);
3947
+ retractResponses = void 0;
3948
+ const response = dispatched.response;
3949
+ reader = dispatched.reader;
3950
+ if (!this.#isActiveTurn(turn)) return;
3951
+ turn.resolveResponse(response);
3952
+ this.#correlate(submissionId, response);
3953
+ for await (const event of consumeMessageResponse(response, reader)) {
3954
+ if (!this.#isActiveTurn(turn)) return;
3955
+ turn.receivedFollowUps += turn.receivedFollowUpEvents.get(event) ?? 0;
3956
+ turn.receivedFollowUpEvents.delete(event);
3957
+ }
3958
+ if (!this.#isActiveTurn(turn)) return;
3959
+ await followSteeredTurns(turn, reader, () => this.#isActiveTurn(turn));
3960
+ if (!this.#isActiveTurn(turn)) return;
3961
+ this.#status = settledStatus(this.#error, this.#conversationClient.conversation);
3962
+ } catch (error) {
3963
+ if (!this.#isActiveTurn(turn)) return;
3964
+ retractResponses?.();
3965
+ if (isAbortError(error)) {
3966
+ this.#status = "ready";
3967
+ this.#messageSubmissions.fail(toError(error), submissionId);
3968
+ } else {
3969
+ const reported = this.#error !== void 0;
3970
+ this.#error ??= toError(error);
3971
+ this.#status = "error";
3972
+ this.#messageSubmissions.fail(this.#error, submissionId);
3973
+ if (!reported) this.#callbacks.onError?.(this.#error);
3974
+ }
3975
+ } finally {
3976
+ reader?.[Symbol.dispose]();
3977
+ this.#finishTurn(turn);
3406
3978
  }
3407
- case "approval.candidate": return data;
3408
- case "approval.settled": {
3409
- const existing = findToolPartByApprovalId(data, event.data.requestId);
3410
- if (existing === void 0) return data;
3411
- if (event.data.outcome === "approved") return updateToolPart(data, existing.toolCallId, {
3412
- approval: {
3413
- approved: true,
3414
- id: event.data.requestId,
3415
- reason: void 0
3416
- },
3417
- input: existing.input,
3418
- state: "approval-responded",
3419
- stepIndex: existing.stepIndex,
3420
- toolCallId: existing.toolCallId,
3421
- toolMetadata: existing.toolMetadata,
3422
- toolName: existing.toolName,
3423
- type: "dynamic-tool"
3424
- });
3425
- return updateToolPart(data, existing.toolCallId, {
3426
- approval: {
3427
- approved: false,
3428
- id: event.data.requestId,
3429
- reason: "Tool execution was cancelled."
3430
- },
3431
- input: existing.input,
3432
- state: "output-denied",
3433
- stepIndex: existing.stepIndex,
3434
- toolCallId: existing.toolCallId,
3435
- toolMetadata: existing.toolMetadata,
3436
- toolName: existing.toolName,
3437
- type: "dynamic-tool"
3979
+ }
3980
+ resume() {
3981
+ if (this.#resumePromise !== void 0) return this.#resumePromise;
3982
+ const promise = this.#resume();
3983
+ this.#resumePromise = promise;
3984
+ const clear = () => {
3985
+ if (this.#resumePromise === promise) this.#resumePromise = void 0;
3986
+ };
3987
+ promise.then(clear, clear);
3988
+ return promise;
3989
+ }
3990
+ async #resume() {
3991
+ if (this.#status !== "ready" && this.#status !== "error") throw new Error("eve session is already processing a turn.");
3992
+ if (this.#session === void 0) throw new Error("An eve session is required before resuming.");
3993
+ const session = this.#session;
3994
+ const turn = createActiveTurn(() => session.cancel());
3995
+ this.#activeTurn = turn;
3996
+ turn.resolveResponse(void 0);
3997
+ this.#error = void 0;
3998
+ this.#status = "resuming";
3999
+ this.#publish();
4000
+ let reader;
4001
+ try {
4002
+ const stream = this.#ensureStream({
4003
+ catchUp: true,
4004
+ startIndex: this.#events.length === session.state.streamIndex ? session.state.streamIndex : 0
3438
4005
  });
4006
+ reader = stream.subscribe(turn.abortController.signal);
4007
+ await stream.caughtUp;
4008
+ if (!this.#isActiveTurn(turn)) return;
4009
+ reader.discard();
4010
+ const tail = this.#events.at(-1);
4011
+ if (tail !== void 0) this.#applyTerminalStreamFailure(tail);
4012
+ if (tail && !this.#error && !isSettledSessionTail(this.#events, this.#conversationClient.conversation)) {
4013
+ this.#status = "streaming";
4014
+ this.#publish();
4015
+ for await (const event of reader) {
4016
+ if (!this.#isActiveTurn(turn)) return;
4017
+ turn.receivedFollowUps += turn.receivedFollowUpEvents.get(event) ?? 0;
4018
+ turn.receivedFollowUpEvents.delete(event);
4019
+ if (isResponseBoundary(event, this.#conversationClient.conversation)) break;
4020
+ }
4021
+ }
4022
+ await followSteeredTurns(turn, reader, () => this.#isActiveTurn(turn));
4023
+ if (this.#isActiveTurn(turn)) this.#status = settledStatus(this.#error, this.#conversationClient.conversation);
4024
+ } catch (error) {
4025
+ if (!this.#isActiveTurn(turn)) return;
4026
+ if (isAbortError(error)) this.#status = "ready";
4027
+ else {
4028
+ this.#error = toError(error);
4029
+ this.#status = "error";
4030
+ this.#callbacks.onError?.(this.#error);
4031
+ }
4032
+ } finally {
4033
+ reader?.[Symbol.dispose]();
4034
+ this.#finishTurn(turn);
3439
4035
  }
3440
- case "action.result": {
3441
- const descriptor = normalizeActionResult(event.data.result);
3442
- const existing = findToolPart(data, event.data.result.callId);
3443
- const denied = event.data.error?.code === "TOOL_EXECUTION_DENIED";
3444
- const failed = event.data.status === "failed" && !denied;
3445
- const approvalId = existing?.approval?.id ?? event.data.result.callId;
3446
- const toolMetadata = mergeToolMetadata(existing?.toolMetadata, createToolMetadata(descriptor));
3447
- const resultPartBase = {
3448
- input: existing?.input,
3449
- stepIndex: event.data.stepIndex,
3450
- toolCallId: event.data.result.callId,
3451
- toolMetadata,
3452
- toolName: existing?.toolName ?? descriptor.toolName,
3453
- type: "dynamic-tool"
3454
- };
3455
- let nextPart;
3456
- if (denied) nextPart = {
3457
- ...resultPartBase,
3458
- approval: {
3459
- approved: false,
3460
- id: approvalId,
3461
- reason: event.data.error?.message
3462
- },
3463
- state: "output-denied"
3464
- };
3465
- else if (failed) nextPart = {
3466
- ...resultPartBase,
3467
- approval: approvedApproval(existing),
3468
- errorText: event.data.error?.message ?? stringifyUnknown(event.data.result.output),
3469
- state: "output-error"
3470
- };
3471
- else nextPart = {
3472
- ...resultPartBase,
3473
- approval: approvedApproval(existing),
3474
- output: event.data.result.output,
3475
- state: "output-available"
3476
- };
3477
- if (existing !== void 0) return updateToolPart(data, event.data.result.callId, nextPart);
3478
- return updateAssistantMessage(data, event.data.turnId, (message) => upsertPart(ensureStepStartPart(message, event.data.stepIndex), nextPart));
4036
+ }
4037
+ cancel() {
4038
+ const turn = this.#activeTurn;
4039
+ if (turn === void 0) return this.#status === "streaming" && this.#session !== void 0 ? this.#session.cancel() : Promise.resolve({ status: "no_active_turn" });
4040
+ return turn.cancel();
4041
+ }
4042
+ async compact() {
4043
+ return await this.#session?.compact() ?? { status: "no_active_session" };
4044
+ }
4045
+ async clear() {
4046
+ return await this.#session?.clear() ?? { status: "no_active_session" };
4047
+ }
4048
+ async retire() {
4049
+ if (this.#externalSession) throw new Error("retire() needs a store-owned session. Call reset() on the session you supplied, then create a new store for the next session.");
4050
+ const result = await this.#session?.reset() ?? { status: "no_active_session" };
4051
+ this.reset();
4052
+ return result;
4053
+ }
4054
+ [attachStore]() {
4055
+ this.#attached = true;
4056
+ if (this.#followChildStreams && !this.#conversationClient.following) this.#followSubagents();
4057
+ if (this.#autoPrewarm && this.#session === void 0) this.prewarm().catch(() => {});
4058
+ }
4059
+ [detachStore]() {
4060
+ this.#attached = false;
4061
+ this.#conversationClient.stop();
4062
+ this.#activeTurn?.abortController.abort();
4063
+ this.#resetPrewarm();
4064
+ this.#resumePromise = void 0;
4065
+ }
4066
+ reset() {
4067
+ this.#conversationClient.stop();
4068
+ const turn = this.#activeTurn;
4069
+ this.#activeTurn = void 0;
4070
+ turn?.resolveResponse(void 0);
4071
+ turn?.resolveCompletion();
4072
+ turn?.abortController.abort();
4073
+ this.#resetPrewarm();
4074
+ this.#resumePromise = void 0;
4075
+ if (!this.#externalSession) this.#session = void 0;
4076
+ this.#events = [];
4077
+ this.#conversationClient.reset();
4078
+ this.#messageSubmissions.reset();
4079
+ if (this.#followChildStreams && this.#attached) this.#followSubagents();
4080
+ this.#error = void 0;
4081
+ this.#status = "ready";
4082
+ this.#callbacks.onSessionChange?.(this.#session?.state);
4083
+ this.#publish();
4084
+ if (this.#autoPrewarm && this.#attached) this.prewarm().catch(() => {});
4085
+ }
4086
+ async #sendFollowUp(turn, input, prepareSend) {
4087
+ assertInFlightFollowUp(input);
4088
+ const generation = this.#prewarmGeneration;
4089
+ const signal = createAbortSignal(input.signal, turn.abortController.signal);
4090
+ let retractResponses = this.#conversationClient.projectResponses(input.inputResponses);
4091
+ const preparedInput = await waitWithSignal(Promise.resolve(prepareSend?.(input)), signal).then((prepared) => {
4092
+ const next = validateFollowUp(prepared ?? input);
4093
+ if (next === input) return next;
4094
+ retractResponses = this.#conversationClient.replaceResponses(retractResponses, next);
4095
+ return next;
4096
+ }).catch((error) => {
4097
+ retractResponses?.();
4098
+ throw error;
4099
+ });
4100
+ if (generation !== this.#prewarmGeneration) return;
4101
+ if (!this.#isActiveTurn(turn)) {
4102
+ retractResponses?.();
4103
+ return await this.#submit(preparedInput);
4104
+ }
4105
+ const submissionId = this.#messageSubmissions.submit(preparedInput, this.#events.length, activeTurnForOptimisticFollowUp(this.#events));
4106
+ if (submissionId !== void 0) turn.followUpSubmissionIds.add(submissionId);
4107
+ this.#publish();
4108
+ let dispatch;
4109
+ dispatch = (async () => {
4110
+ try {
4111
+ const signal = createAbortSignal(preparedInput.signal, turn.abortController.signal);
4112
+ await waitWithSignal(turn.response, signal);
4113
+ if (!this.#isActiveTurn(turn) || this.#session === void 0) throw new Error("The active eve turn ended before the follow-up could be sent.");
4114
+ this.#ensureStream({
4115
+ headers: preparedInput.headers,
4116
+ streamReconnectPolicy: preparedInput.streamReconnectPolicy
4117
+ });
4118
+ const response = (await dispatchSessionTurn({
4119
+ session: this.#session,
4120
+ turn: {
4121
+ ...preparedInput,
4122
+ signal
4123
+ }
4124
+ })).response;
4125
+ retractResponses = void 0;
4126
+ if (preparedInput.message === void 0) return;
4127
+ turn.acceptedFollowUps += 1;
4128
+ this.#correlate(submissionId, response);
4129
+ } catch (error) {
4130
+ if (this.#isActiveTurn(turn)) {
4131
+ this.#messageSubmissions.fail(toError(error), submissionId);
4132
+ retractResponses?.();
4133
+ this.#publish();
4134
+ }
4135
+ throw error;
4136
+ } finally {
4137
+ turn.followUpDispatches.delete(dispatch);
4138
+ }
4139
+ })();
4140
+ turn.followUpDispatches.add(dispatch);
4141
+ await dispatch;
4142
+ await turn.completion;
4143
+ }
4144
+ async #dispatchTurn(input) {
4145
+ const streamOptions = {
4146
+ headers: input.headers,
4147
+ streamReconnectPolicy: input.streamReconnectPolicy
4148
+ };
4149
+ if (this.#prewarmPromise !== void 0) {
4150
+ await waitWithSignal(this.#prewarmPromise.catch((error) => {
4151
+ if (this.#session !== void 0) throw error;
4152
+ }), input.signal);
4153
+ input.signal?.throwIfAborted();
3479
4154
  }
3480
- case "action.partial": {
3481
- const existing = findToolPart(data, event.data.result.callId);
3482
- if (existing !== void 0 && isSettledToolPart(existing)) return data;
3483
- const descriptor = normalizeActionResult(event.data.result);
3484
- const nextPart = {
3485
- approval: approvedApproval(existing),
3486
- input: existing?.input,
3487
- output: event.data.result.output,
3488
- partial: true,
3489
- state: "output-available",
3490
- stepIndex: event.data.stepIndex,
3491
- toolCallId: event.data.result.callId,
3492
- toolMetadata: mergeToolMetadata(existing?.toolMetadata, createToolMetadata(descriptor)),
3493
- toolName: existing?.toolName ?? descriptor.toolName,
3494
- type: "dynamic-tool"
4155
+ const session = this.#session;
4156
+ let reader;
4157
+ try {
4158
+ const dispatched = await dispatchSessionTurn({
4159
+ client: this.#client,
4160
+ session,
4161
+ turn: input,
4162
+ beforeSend: () => {
4163
+ reader = this.#ensureStream(streamOptions).subscribe(input.signal);
4164
+ }
4165
+ });
4166
+ if (dispatched.created) {
4167
+ this.#adoptSession(dispatched.session);
4168
+ reader = this.#ensureStream(streamOptions).subscribe(input.signal);
4169
+ }
4170
+ return {
4171
+ response: dispatched.response,
4172
+ reader
3495
4173
  };
3496
- if (existing !== void 0) return updateToolPart(data, event.data.result.callId, nextPart);
3497
- return updateAssistantMessage(data, event.data.turnId, (message) => upsertPart(ensureStepStartPart(message, event.data.stepIndex), nextPart));
3498
- }
3499
- case "task.settled": {
3500
- const existing = findToolPart(data, event.data.callId);
3501
- if (existing === void 0) return data;
3502
- return replaceToolPart(data, createSettledTaskPart(existing, event));
4174
+ } catch (error) {
4175
+ reader?.[Symbol.dispose]();
4176
+ throw error;
3503
4177
  }
3504
- case "authorization.required": return updateAssistantMessage(data, event.data.turnId, (message) => upsertPart(ensureStepStartPart(message, event.data.stepIndex), createAuthorizationRequiredPart(event)));
3505
- case "authorization.completed": return completeAuthorization(data, event);
3506
- case "message.appended": return updateAssistantMessage(data, event.data.turnId, (message) => messageRun.append(ensureStepStartPart(message, event.data.stepIndex), {
3507
- delta: event.data.messageDelta,
3508
- stepIndex: event.data.stepIndex,
3509
- type: "text"
3510
- }));
3511
- case "message.completed": return updateAssistantMessage(data, event.data.turnId, (message) => {
3512
- return messageRun.upsert(ensureStepStartPart(message, event.data.stepIndex), {
3513
- state: "done",
3514
- stepIndex: event.data.stepIndex,
3515
- text: event.data.message,
3516
- type: "text"
3517
- });
4178
+ }
4179
+ #ensureStream(options = {}) {
4180
+ if (this.#session === void 0) throw new Error("A session is required before opening its stream.");
4181
+ const generation = this.#prewarmGeneration;
4182
+ if (this.#followChildStreams && !this.#conversationClient.following) this.#followSubagents();
4183
+ return this.#conversationClient.stream(this.#session, {
4184
+ ...options,
4185
+ onEvent: (event) => {
4186
+ if (generation === this.#prewarmGeneration) this.#acceptServerEvent(event);
4187
+ },
4188
+ onError: (error) => {
4189
+ if (generation !== this.#prewarmGeneration || this.#activeTurn !== void 0) return;
4190
+ this.#fail(error);
4191
+ }
3518
4192
  });
3519
- case "result.completed": return updateAssistantMetadata(data, event.data.turnId, { result: event.data.result });
3520
- case "turn.completed": return updateAssistantMessage(data, event.data.turnId, (message) => ({
3521
- ...message,
3522
- metadata: {
3523
- ...message.metadata,
3524
- status: "complete"
4193
+ }
4194
+ #adoptSession(session) {
4195
+ this.#session = session;
4196
+ if (this.#followChildStreams && this.#attached) this.#followSubagents();
4197
+ this.#callbacks.onSessionChange?.(session.state);
4198
+ this.#publish();
4199
+ }
4200
+ #fail(error) {
4201
+ this.#error = toError(error);
4202
+ this.#status = "error";
4203
+ this.#callbacks.onError?.(this.#error);
4204
+ this.#publish();
4205
+ }
4206
+ #followSubagents() {
4207
+ if (this.#session) this.#conversationClient.follow(this.#session, this.#events);
4208
+ }
4209
+ #resetPrewarm() {
4210
+ this.#prewarmGeneration += 1;
4211
+ this.#prewarmController?.abort();
4212
+ this.#prewarmController = void 0;
4213
+ this.#prewarmPromise = void 0;
4214
+ }
4215
+ #finishTurn(turn) {
4216
+ if (!this.#isActiveTurn(turn)) return;
4217
+ turn.resolveResponse(void 0);
4218
+ this.#activeTurn = void 0;
4219
+ try {
4220
+ this.#callbacks.onSessionChange?.(this.#session?.state);
4221
+ this.#publish();
4222
+ this.#callbacks.onFinish?.(this.#snapshot);
4223
+ } finally {
4224
+ turn.resolveCompletion();
4225
+ }
4226
+ }
4227
+ #isActiveTurn(turn) {
4228
+ return this.#activeTurn === turn;
4229
+ }
4230
+ #acceptServerEvent(event) {
4231
+ const wasStreaming = this.#status === "streaming";
4232
+ if (!this.#conversationClient.observe(event, {
4233
+ onAccepted: () => {
4234
+ this.#events = [...this.#events, event];
3525
4235
  },
3526
- parts: removeStreamingToolParts(message.parts)
3527
- }));
3528
- case "turn.cancelled": return updateAssistantMessage(data, event.data.turnId, (message) => ({
3529
- ...message,
3530
- metadata: {
3531
- ...message.metadata,
3532
- status: "complete"
4236
+ project: (accepted) => {
4237
+ this.#handleReconciliation(this.#messageSubmissions.apply(accepted));
3533
4238
  },
3534
- parts: removeStreamingToolParts(message.parts.map((part) => (part.type === "text" || part.type === "reasoning") && part.state === "streaming" ? {
3535
- ...part,
3536
- state: "done"
3537
- } : part))
3538
- }));
3539
- case "turn.failed": return removeStreamingToolPartsForTurn(data, event.data.turnId);
3540
- case "session.failed": return data;
3541
- default: return data;
4239
+ notify: false
4240
+ })) return false;
4241
+ this.#callbacks.onEvent?.(event);
4242
+ this.#applyTerminalStreamFailure(event);
4243
+ const { conversation } = this.#conversationClient;
4244
+ const settled = isSettledSessionTail(this.#events, conversation) && conversation.activeTurnId === void 0;
4245
+ if (this.#status !== "resuming" && this.#error === void 0) {
4246
+ if ("data" in event && event.data !== void 0 && "turnId" in event.data) this.#status = "streaming";
4247
+ if (this.#activeTurn === void 0 && settled) this.#status = "ready";
4248
+ }
4249
+ this.#callbacks.onSessionChange?.(this.#session?.state);
4250
+ if (this.#status !== "resuming") this.#publish();
4251
+ if (this.#activeTurn === void 0 && wasStreaming && settled) this.#callbacks.onFinish?.(this.#snapshot);
4252
+ return true;
3542
4253
  }
3543
- }
3544
- function removeStreamingToolParts(parts) {
3545
- return parts.filter((part) => part.type !== "dynamic-tool" || part.state !== "input-streaming");
3546
- }
3547
- function respondToInputRequest(data, response) {
3548
- const existing = findToolPartByApprovalId(data, response.requestId);
3549
- if (!existing) return data;
3550
- const approval = { id: response.requestId };
3551
- if (response.text !== void 0) approval.reason = response.text;
3552
- return updateToolPart(data, existing.toolCallId, {
3553
- approval,
3554
- input: existing.input,
3555
- state: "approval-responded",
3556
- stepIndex: existing.stepIndex,
3557
- toolCallId: existing.toolCallId,
3558
- toolMetadata: mergeToolMetadata(existing.toolMetadata, { eve: {
3559
- inputResponse: response,
3560
- kind: existing.toolMetadata?.eve?.kind ?? "unknown",
3561
- name: existing.toolMetadata?.eve?.name ?? existing.toolName
3562
- } }),
3563
- toolName: existing.toolName,
3564
- type: "dynamic-tool"
3565
- });
3566
- }
3567
- function resolveInputRequest(data, resolution) {
3568
- if (resolution.response !== void 0) return respondToInputRequest(data, resolution.response);
3569
- const existing = findToolPartByApprovalId(data, resolution.requestId);
3570
- if (!existing) return data;
3571
- return updateToolPart(data, existing.toolCallId, {
3572
- input: existing.input,
3573
- output: { status: resolution.outcome },
3574
- state: "output-available",
3575
- stepIndex: existing.stepIndex,
3576
- toolCallId: existing.toolCallId,
3577
- toolMetadata: existing.toolMetadata,
3578
- toolName: existing.toolName,
3579
- type: "dynamic-tool"
3580
- });
3581
- }
3582
- function updateAssistantMessage(data, turnId, update) {
3583
- const message = data.messages.find((message) => message.role === "assistant" && message.metadata?.turnId === turnId) ?? createAssistantMessage(turnId);
3584
- return upsertMessage(data, update(message));
3585
- }
3586
- function updateAssistantMetadata(data, turnId, metadata) {
3587
- return updateAssistantMessage(data, turnId, (message) => ({
3588
- ...message,
3589
- metadata: {
3590
- ...message.metadata,
3591
- ...metadata
4254
+ #correlate(submissionId, response) {
4255
+ const deliveryId = getMessageResponseDeliveryId(response);
4256
+ const reconciled = this.#messageSubmissions.correlate(submissionId, deliveryId, this.#events);
4257
+ if (this.#handleReconciliation(reconciled)) this.#publish();
4258
+ }
4259
+ #handleReconciliation(reconciliation) {
4260
+ if (reconciliation === void 0) return false;
4261
+ if (this.#activeTurn !== void 0) countFollowUpDeliveries(this.#activeTurn, reconciliation);
4262
+ return true;
4263
+ }
4264
+ #applyTerminalStreamFailure(event) {
4265
+ const error = toTerminalStreamFailureError(event);
4266
+ if (error === void 0) return;
4267
+ this.#status = "error";
4268
+ this.#messageSubmissions.failAll(error);
4269
+ if (this.#error === void 0) {
4270
+ this.#error = error;
4271
+ this.#callbacks.onError?.(error);
3592
4272
  }
3593
- }));
3594
- }
3595
- function createAssistantMessage(turnId) {
3596
- return {
3597
- id: `${turnId}:assistant`,
3598
- metadata: {
3599
- status: "streaming",
3600
- turnId
3601
- },
3602
- parts: [],
3603
- role: "assistant"
3604
- };
3605
- }
3606
- function ensureStepStartPart(message, stepIndex) {
3607
- const stepStartCount = message.parts.filter((part) => part.type === "step-start").length;
3608
- if (stepStartCount > stepIndex) return message;
3609
- const missingCount = stepIndex - stepStartCount + 1;
3610
- return {
3611
- ...message,
3612
- parts: [...message.parts, ...Array.from({ length: missingCount }, () => ({ type: "step-start" }))]
3613
- };
3614
- }
3615
- function upsertPart(message, next) {
3616
- const index = message.parts.findIndex((part) => partKey(part) === partKey(next));
3617
- const parts = index === -1 ? [...message.parts, next] : [
3618
- ...message.parts.slice(0, index),
3619
- next,
3620
- ...message.parts.slice(index + 1)
3621
- ];
3622
- return {
3623
- ...message,
3624
- metadata: {
3625
- ...message.metadata,
3626
- status: next.type === "text" && next.state === "done" ? "complete" : "streaming"
3627
- },
3628
- parts
3629
- };
3630
- }
3631
- function updateToolPart(data, toolCallId, next) {
3632
- const message = data.messages.find((candidate) => candidate.role === "assistant" && candidate.parts.some((part) => part.type === "dynamic-tool" && part.toolCallId === toolCallId));
3633
- if (!message) return data;
3634
- return upsertMessage(data, upsertPart(message, next));
3635
- }
3636
- function replaceToolPart(data, next) {
3637
- const message = data.messages.find((candidate) => candidate.parts.some((part) => part.type === "dynamic-tool" && part.toolCallId === next.toolCallId));
3638
- if (message === void 0) return data;
3639
- return upsertMessage(data, {
3640
- ...message,
3641
- parts: message.parts.map((part) => partKey(part) === partKey(next) ? next : part)
3642
- });
3643
- }
3644
- function completeAuthorization(data, event) {
3645
- const existing = findLatestPendingAuthorizationPart(data, event.data.name);
3646
- const next = createAuthorizationCompletedPart(event, existing);
3647
- if (existing !== void 0) return updateAuthorizationPart(data, existing, next);
3648
- return updateAssistantMessage(data, event.data.turnId, (message) => upsertPart(ensureStepStartPart(message, event.data.stepIndex), next));
3649
- }
3650
- function updateAuthorizationPart(data, existing, next) {
3651
- const message = data.messages.find((candidate) => candidate.role === "assistant" && candidate.parts.some((part) => part === existing));
3652
- if (!message) return data;
3653
- return upsertMessage(data, upsertPart(message, next));
3654
- }
3655
- function findToolPart(data, toolCallId) {
3656
- for (const message of data.messages) for (const part of message.parts) if (part.type === "dynamic-tool" && part.toolCallId === toolCallId) return part;
4273
+ }
4274
+ #createSnapshot() {
4275
+ return {
4276
+ data: this.#conversationClient.data,
4277
+ conversation: this.#conversationClient.conversation,
4278
+ error: this.#error,
4279
+ events: this.#events,
4280
+ session: this.#session?.state,
4281
+ status: this.#status
4282
+ };
4283
+ }
4284
+ #publish() {
4285
+ this.#snapshot = this.#createSnapshot();
4286
+ for (const subscriber of this.#subscribers) subscriber();
4287
+ }
4288
+ };
4289
+ function detachEveAgentStore(store) {
4290
+ store[detachStore]();
3657
4291
  }
3658
- function isSettledToolPart(part) {
3659
- return part.state === "output-denied" || part.state === "output-error" || part.state === "output-available" && part.partial !== true;
4292
+ function attachEveAgentStore(store) {
4293
+ store[attachStore]();
3660
4294
  }
3661
- function findLatestPendingAuthorizationPart(data, name) {
3662
- for (let messageIndex = data.messages.length - 1; messageIndex >= 0; messageIndex -= 1) {
3663
- const message = data.messages[messageIndex];
3664
- if (message?.role !== "assistant") continue;
3665
- for (let partIndex = message.parts.length - 1; partIndex >= 0; partIndex -= 1) {
3666
- const part = message.parts[partIndex];
3667
- if (part?.type === "authorization" && part.state === "required" && part.name === name) return part;
3668
- }
3669
- }
4295
+
4296
+ //#endregion
4297
+ //#region src/client/agent-host.ts
4298
+ const AGENT_NAME_PATTERN = /^[a-z0-9][a-z0-9_-]*$/;
4299
+ const EVE_NAMED_AGENT_ROUTE_PREFIX = "/eve";
4300
+ function resolveEveAgentHost(input) {
4301
+ if (input.agent === void 0) return input.host ?? "";
4302
+ if (input.host !== void 0) throw new Error("useEveAgent cannot combine agent and host. Use one target option.");
4303
+ assertValidAgentName(input.agent);
4304
+ return `${EVE_NAMED_AGENT_ROUTE_PREFIX}/${input.agent}`;
3670
4305
  }
3671
- function findToolPartByApprovalId(data, approvalId) {
3672
- for (const message of data.messages) for (const part of message.parts) if (part.type === "dynamic-tool" && part.approval?.id === approvalId) return part;
4306
+ function assertValidAgentName(name) {
4307
+ if (!AGENT_NAME_PATTERN.test(name)) throw new Error(`eve agent name ${JSON.stringify(name)} is invalid. Use lowercase letters, numbers, underscores, or hyphens, starting with a letter or number.`);
3673
4308
  }
3674
4309
 
3675
4310
  //#endregion
3676
4311
  //#region src/vue/use-eve-agent.ts
3677
4312
  function useEveAgent(options = {}) {
3678
4313
  if (options.resume && options.initialSession === void 0 && options.session === void 0) throw new Error("useEveAgent({ resume: true }) requires initialSession or session.");
3679
- const reducer = options.reducer ?? defaultMessageReducer();
4314
+ const reducer = options.reducer ?? conversationReducer;
3680
4315
  const store = new EveAgentStore({
3681
4316
  auth: options.auth,
3682
4317
  headers: options.headers,
@@ -3687,6 +4322,7 @@ function useEveAgent(options = {}) {
3687
4322
  initialEvents: options.initialEvents,
3688
4323
  initialSession: options.initialSession,
3689
4324
  optimistic: options.optimistic,
4325
+ followSubagents: options.followSubagents,
3690
4326
  prewarm: options.prewarm,
3691
4327
  reducer,
3692
4328
  session: options.session
@@ -3713,6 +4349,7 @@ function useEveAgent(options = {}) {
3713
4349
  return {
3714
4350
  cancel: () => store.cancel(),
3715
4351
  data: computed(() => snapshot.value.data),
4352
+ conversation: computed(() => snapshot.value.conversation),
3716
4353
  error: computed(() => snapshot.value.error),
3717
4354
  events: computed(() => snapshot.value.events),
3718
4355
  prewarm: () => store.prewarm(),
@@ -3732,4 +4369,4 @@ function useEveAgent(options = {}) {
3732
4369
  }
3733
4370
 
3734
4371
  //#endregion
3735
- export { defaultMessageReducer as n, useEveAgent as t };
4372
+ export { openConversationInputs as i, conversationReducer as n, defaultMessageReducer as r, useEveAgent as t };