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
@@ -0,0 +1,72 @@
1
+ import type { DeliverPayload } from "#channel/types.js";
2
+ import type { SlackChannelInternalEvents, SlackChannelState, SlackContext } from "#public/channels/slack/slackChannel.js";
3
+ type MessageCompletedHandler = NonNullable<SlackChannelInternalEvents["message.completed"]>;
4
+ /**
5
+ * A completed reply for {@link postCompletedSlackReply}: Markdown alone, or
6
+ * Markdown with the Block Kit blocks to try first. `markdown` is the full
7
+ * reply eve falls back to; `text` is the notification text for the blocks,
8
+ * defaulting to `markdown`.
9
+ */
10
+ export type SlackCompletedReply = string | {
11
+ readonly markdown: string;
12
+ readonly blocks?: readonly unknown[];
13
+ readonly text?: string;
14
+ };
15
+ /**
16
+ * Posts a completed reply to the bound Slack thread with eve's delivery
17
+ * fallbacks, using only the content you pass. eve's default renderer posts
18
+ * its replies through it; an authored renderer opts in by calling it instead
19
+ * of `channel.thread.post`.
20
+ *
21
+ * eve tries, in order:
22
+ *
23
+ * 1. Your `blocks`, when given, with `text` as the notification text.
24
+ * 2. `markdown` as one native Markdown message, when it fits in
25
+ * {@link SLACK_MARKDOWN_TEXT_MAX_LENGTH} characters. eve moves on from
26
+ * the blocks only when Slack refuses them as too large or malformed
27
+ * (`msg_too_long`, `msg_blocks_too_long`, `msg_blocks_too_many`,
28
+ * `invalid_blocks`, or `invalid_blocks_format`).
29
+ * 3. `markdown` uploaded unchanged as an `eve-response.md` snippet with a
30
+ * short note, when it is longer or Slack refuses the Markdown message.
31
+ * This requires the `files:write` bot scope. In a session without a
32
+ * thread yet, the note posts first and anchors the thread.
33
+ *
34
+ * Any other error, and a failed upload, is thrown so your renderer sees it.
35
+ * eve logs each fallback it takes with Slack's error code, never the reply.
36
+ *
37
+ * @example
38
+ * ```ts
39
+ * import { postCompletedSlackReply } from "eve/channels/slack";
40
+ *
41
+ * await postCompletedSlackReply(channel, {
42
+ * blocks: [{ type: "markdown", text: reply }, sourcesBlock],
43
+ * markdown: reply,
44
+ * });
45
+ * ```
46
+ */
47
+ export declare function postCompletedSlackReply(channel: SlackContext, reply: SlackCompletedReply): Promise<void>;
48
+ /**
49
+ * {@link postCompletedSlackReply} with fields for its fallback log, such as
50
+ * the turn id eve's default renderer knows.
51
+ */
52
+ export declare function deliverCompletedSlackReply(channel: SlackContext, reply: SlackCompletedReply, logFields: {
53
+ readonly turnId?: string;
54
+ }): Promise<void>;
55
+ /**
56
+ * Wraps a channel's composed `message.completed` chain, authored renderers
57
+ * included, so a final reply that fails is never lost without a trace.
58
+ *
59
+ * When the chain throws on a final reply, eve logs the error at error level,
60
+ * posts a content-free notice with its error id, and tells the model on the
61
+ * next delivery that its reply was not seen. eve never sends the reply from
62
+ * here: the chain owns the content, including any change a renderer made
63
+ * before `next`, and {@link postCompletedSlackReply} owns the fallbacks.
64
+ * Steps that end in tool calls and empty replies pass through.
65
+ */
66
+ export declare function withFinalReplyDelivery(render: MessageCompletedHandler | undefined): MessageCompletedHandler;
67
+ /**
68
+ * Tells the model, ahead of the next message, that its previous reply never
69
+ * reached Slack, so it does not assume the user read that reply.
70
+ */
71
+ export declare function withUndeliveredReplyNote<T extends DeliverPayload>(state: SlackChannelState, payload: T): T;
72
+ export {};
@@ -0,0 +1 @@
1
+ import{createLogger,logError}from"#internal/logging.js";import{SLACK_MARKDOWN_TEXT_MAX_LENGTH,truncateMessageText}from"#public/channels/slack/limits.js";const log=createLogger(`slack.reply`),LONG_RESPONSE_NOTICE=`Here's a snippet with the full response.`,FALLBACK_LOG=`Slack refused the final reply; delivering it with a fallback`,REFUSED_PAYLOAD_ERRORS=new Set([`invalid_blocks`,`invalid_blocks_format`,`msg_blocks_too_long`,`msg_blocks_too_many`,`msg_too_long`]);async function postCompletedSlackReply(e,t){await deliverCompletedSlackReply(e,t,{})}async function deliverCompletedSlackReply(e,t,n){let{blocks:r,markdown:i,text:a}=typeof t==`string`?{markdown:t}:t,o;if(r!==void 0)try{await e.thread.post({blocks:r,text:a??truncateMessageText(i)});return}catch(e){if(o=refusedPayloadError(e),o===void 0)throw e}if(i.length<=SLACK_MARKDOWN_TEXT_MAX_LENGTH){o!==void 0&&log.warn(FALLBACK_LOG,{fallback:`inline`,slackError:o,...n});try{await e.thread.post(i);return}catch(e){if(o=refusedPayloadError(e),o===void 0)throw e}}o!==void 0&&log.warn(FALLBACK_LOG,{fallback:`snippet`,slackError:o,...n}),await uploadReplySnippet(e,i)}async function uploadReplySnippet(e,t){let n={data:new Blob([t],{type:`text/markdown`}),filename:`eve-response.md`,mimeType:`text/markdown`},r=e.slack.threadTs.length>0;if(!r&&(!(await e.thread.post(LONG_RESPONSE_NOTICE)).id||e.slack.threadTs.length===0))throw Error(`Slack did not return a thread timestamp for the long response notice.`);await e.slack.uploadFiles([n],{initialComment:r?LONG_RESPONSE_NOTICE:void 0,snippetType:`markdown`})}function refusedPayloadError(e){let t=e;for(let e=0;e<5&&typeof t==`object`&&t;e++){let e=t,n=e.response?.error??e.data?.error;if(typeof n==`string`&&REFUSED_PAYLOAD_ERRORS.has(n))return n;t=e.cause}}function withFinalReplyDelivery(e){return async(t,n,r)=>{if(t.finishReason===`tool-calls`||!t.message){await e?.(t,n,r);return}try{await e?.(t,n,r)}catch(e){await reportUndeliveredReply(n,t.turnId,e)}}}async function reportUndeliveredReply(e,t,n){let r=logError(log,`final reply was not delivered to Slack`,n,{turnId:t});e.state.undeliveredReplyErrorId=r;try{await e.thread.post(`I finished, but couldn't deliver my answer in Slack (error id \`${r}\`). Please ask me to resend it.`)}catch(e){logError(log,`undelivered reply notice failed`,e,{errorId:r,turnId:t})}}function withUndeliveredReplyNote(e,t){let n=e.undeliveredReplyErrorId;if(!n||t.message===void 0)return t;e.undeliveredReplyErrorId=null;let r=[`Your previous reply was not delivered to Slack (error id ${n}).`,`The user has not seen it. Do not assume they read it; send the answer again if they ask for it.`].join(` `);return{...t,context:[r,...t.context??[]]}}export{deliverCompletedSlackReply,postCompletedSlackReply,withFinalReplyDelivery,withUndeliveredReplyNote};
@@ -0,0 +1,20 @@
1
+ import type { ChannelFrom } from "#channel/channel-operations.js";
2
+ import type { SlackChannelState } from "#public/channels/slack/slackChannel.js";
3
+ /** `action_id` of the sign-in prompt's Cancel button; outside eve's `eve_input:` HITL prefix. */
4
+ export declare const SIGN_IN_CANCEL_ACTION_ID = "eve_sign_in:cancel";
5
+ /** The held turn a sign-in prompt's Cancel button cancels. */
6
+ export interface SignInCancelTarget {
7
+ readonly channelId: string;
8
+ readonly threadTs: string;
9
+ readonly turnId: string;
10
+ }
11
+ /** Reads a Cancel click's target from a sign-in prompt's button value. */
12
+ export declare function parseSignInCancelTarget(value: unknown): SignInCancelTarget | undefined;
13
+ /**
14
+ * Handles a click on a sign-in prompt's Cancel button in the background.
15
+ * Returns false for any other interaction.
16
+ */
17
+ export declare function dispatchSignInCancel(raw: Record<string, unknown>, ctx: {
18
+ readonly from: ChannelFrom<SlackChannelState>;
19
+ readonly waitUntil: (task: Promise<unknown>) => void;
20
+ }): boolean;
@@ -0,0 +1 @@
1
+ import{createLogger}from"#internal/logging.js";import{slackContinuationToken}from"#public/channels/slack/api.js";const log=createLogger(`slack.interactions`),SIGN_IN_CANCEL_ACTION_ID=`eve_sign_in:cancel`;function parseSignInCancelTarget(e){if(typeof e!=`string`)return;let t;try{t=JSON.parse(e)}catch{return}if(typeof t!=`object`||!t)return;let{channelId:n,threadTs:r,turnId:i}=t;if(typeof n==`string`&&typeof r==`string`&&typeof i==`string`)return{channelId:n,threadTs:r,turnId:i}}function dispatchSignInCancel(e,t){let n=readSignInCancel(e);return n!==void 0&&(t.waitUntil(cancelHeldSignIn(n,t)),!0)}function readSignInCancel(e){let t=parseSignInCancelTarget((Array.isArray(e.actions)?e.actions:[]).find(e=>isObjectRecord(e)&&e.action_id===`eve_sign_in:cancel`)?.value);if(t!==void 0)return{responseUrl:typeof e.response_url==`string`?e.response_url:void 0,target:t}}async function cancelHeldSignIn(e,t){let{channelId:n,threadTs:r,turnId:i}=e.target;try{await t.from(slackContinuationToken(n,r)).cancel({turnId:i})}catch(e){log.error(`sign-in cancel delivery failed`,{error:e});return}if(e.responseUrl!==void 0)try{await fetch(e.responseUrl,{body:JSON.stringify({delete_original:!0}),headers:{"content-type":`application/json`},method:`POST`})}catch(e){log.warn(`failed to remove the cancelled sign-in prompt`,{error:e})}}function isObjectRecord(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}export{SIGN_IN_CANCEL_ACTION_ID,dispatchSignInCancel,parseSignInCancelTarget};
@@ -90,6 +90,10 @@ type SlackSessionFailedHandler = (data: EventData<"session.failed">, channel: Sl
90
90
  * `JSON.stringify` / `JSON.parse`.
91
91
  */
92
92
  export interface SlackPendingApprovalCard {
93
+ /** Thread post announcing a direct-message approval; updated with the outcome. */
94
+ readonly announcementTs?: string;
95
+ /** Separate tool-input details post; deleted once none of its approvals are pending. */
96
+ readonly detailsMessageTs?: string;
93
97
  /** Channel containing the approval card; differs from the session channel for DM delivery. */
94
98
  readonly messageChannelId?: string;
95
99
  readonly messageBlocks: readonly unknown[];
@@ -143,12 +147,23 @@ export interface SlackChannelState {
143
147
  * turn id. The default `turn.waiting` handler names the working tasks.
144
148
  */
145
149
  taskCards?: Record<string, SlackTaskCardState> | null;
150
+ /**
151
+ * The turn with a task that settled since its last model step. The default
152
+ * `step.started` handler shows `Reviewing results...` for the step that reads
153
+ * the results.
154
+ */
155
+ pendingTaskResultsTurnId?: string | null;
146
156
  /**
147
157
  * Principal id to Slack user id, recorded as each message or input response
148
158
  * is delivered. Default handlers use it to address the principal named on
149
159
  * `authorization.required` and approval events.
150
160
  */
151
161
  slackUsersByPrincipal?: Record<string, string>;
162
+ /**
163
+ * Error id of a final reply that never reached Slack. The next delivered
164
+ * message tells the model the reply was not seen, then clears it.
165
+ */
166
+ undeliveredReplyErrorId?: string | null;
152
167
  }
153
168
  /**
154
169
  * Per-session metadata attached to tracing spans, projected by the
@@ -1 +1 @@
1
- import{markEventHandled}from"./utils.js";import{createLogger,logError}from"#internal/logging.js";import{normalizeChannelAudience}from"#shared/channel-audience.js";import{setChannelBuildMetadata}from"#channel/compiled-channel.js";import{defaultDeliverResult}from"#channel/adapter.js";import{POST,defineChannel}from"#public/definitions/channel.js";import{mergeUploadPolicy}from"#public/channels/upload-policy.js";import{resolveSlackTransportOptions}from"#public/channels/slack/transport.js";import{buildSlackBinding,buildSlackWorkspaceHandle,slackContinuationToken}from"#public/channels/slack/api.js";import{buildSlackAuthContext,slackUserIdFromAuthContext}from"#public/channels/slack/auth.js";import{defaultEvents,defaultInputRequestedHandler,defaultOnMessage,defaultReceived}from"#public/channels/slack/defaults.js";import{composeSlackRenderers}from"#public/channels/slack/renderers.js";import{loadThreadContextMessages}from"#public/channels/slack/thread.js";import{parseSlackWebhookBody}from"#compiled/@chat-adapter/slack/webhook.js";import{bindSlackSessionOperations,withSlackResponder}from"#public/channels/slack/session-operations.js";import{buildSlackTurnMessage,collectInboundFileParts,createSlackFetchFile}from"#public/channels/slack/attachments.js";import{renderDefaultSlackTaskCard,withTaskCards}from"#public/channels/slack/task-card.js";import{parseMessageEvent,parseSlackEventEnvelope,slackEventBotUserId,slackEventInstallationTeamId,slackEventReceivingBotUserId,slackMessageFromWebhookPayload}from"#public/channels/slack/inbound.js";import{formatSlackInboundMessage,formatSlackThreadContext}from"#public/channels/slack/model-context.js";import{isPrivateSlackConversation}from"#public/channels/slack/privacy.js";import{SLACK_CHANNEL_DEFAULT_ROUTE}from"#public/channels/slack/constants.js";import{defineSlackAppManifest}from"#public/channels/slack/app-manifest.js";import{handleInteractionPost}from"#public/channels/slack/interactions.js";import{verifySlackRequest as verifySlackRequest$1}from"#public/channels/slack/verify.js";const log=createLogger(`slack.channel`);function rebuildSlackContext(e,t,n,r){let{thread:i,slack:a}=buildSlackBinding({api:n,botToken:r?.botToken,channelId:e.channelId??``,threadTs:e.threadTs??``,installationTeamId:e.installationTeamId??void 0,teamId:e.teamId??void 0,onThreadTsChanged(n){e.threadTs=n,e.channelId&&t.continuation?.alias(slackContinuationToken(e.channelId,n))}});return{thread:i,slack:a,state:e}}function slackChannel(e={}){let t=resolveSlackTransportOptions(e.api),n=mergeUploadPolicy(e.uploadPolicy),r=createSlackFetchFile({api:t,botToken:e.credentials?.botToken}),i=e.onInputResponse??defaultOnInputResponse,a=composeSlackRenderers(e.renderers??[],{events:{...defaultEvents,"input.requested":defaultInputRequestedHandler(e.approvalChannel)},received:defaultReceived,taskCard:renderDefaultSlackTaskCard}),o=a.events[`turn.started`],s=withTaskCards({...a.events,async"turn.started"(e,t,n){let r=slackUserIdFromAuthContext(n.session.auth.current);r!==void 0&&(t.state.triggeringUserId=r),await o?.(e,t,n)}},a.taskCard),c=new Set,l=defineChannel({kindHint:`slack`,turnPolicy:e.turnPolicy,state:{channelId:null,threadTs:null,teamId:null,installationTeamId:null,triggeringUserId:null,triggeringMessageTs:null,pendingToolCallMessage:null,lastReasoningTypingAtMs:null,lastReasoningTypingStatus:null,pendingAuthMessageTs:{},pendingApprovalCards:{},slackUsersByPrincipal:{}},fetchFile:r,metadata(e){return{channelId:e.channelId,teamId:e.teamId,threadTs:e.threadTs,triggeringUserId:e.triggeringUserId??null}},audience:({state:e})=>e.audience??`unknown`,context(n,r){return rebuildSlackContext(n,r,t,e.credentials)},deliver(e,t){return recordSlackPrincipal(t.state,t.session.auth.current,e),defaultDeliverResult(e)},routes:[POST(e.route??SLACK_CHANNEL_DEFAULT_ROUTE,async(r,o)=>{let{waitUntil:s}=o,{from:l,resolveSession:u}=o,d=await verifyInbound(r,e.credentials);return d===null?new Response(`unauthorized`,{status:401}):shouldDropSlackHttpTimeoutRetry(r.headers)?new Response(`ok`):(r.headers.get(`content-type`)??``).includes(`application/x-www-form-urlencoded`)?handleInteractionPost(d,{from:l,resolveSession:u,waitUntil:s},{api:t,config:e,onInputResponse:i}):handleEventPost({api:t,body:d,from:l,resolveSession:u,waitUntil:s,config:e,received:a.received,uploadPolicy:n,handledEvents:c,headers:r.headers})})],receive(n,{from:r}){return receiveOnSlack(n,{from:r,api:t,credentials:e.credentials})},events:s}),u=e.credentials,d=defineSlackAppManifest({botName:e.botName});return setChannelBuildMetadata(l,e=>({externalCredentials:u?.vercelConnect,manifest:d.build(e)})),l}function defaultOnInputResponse(e){return{auth:e.defaultAuth}}async function receiveOnSlack(e,t){let n=e.target,r=n.channelId;if(!r||typeof r!=`string`)throw Error(`slackChannel().receive requires target.channelId.`);let i=typeof n.threadTs==`string`?n.threadTs:``,a=typeof n.installationTeamId==`string`?n.installationTeamId:t.installationTeamId,o=n.initialMessage;if(o&&i.length>0)throw Error("slackChannel().receive: `threadTs` and `initialMessage` are mutually exclusive.");let s=i;if(o){let{thread:e}=buildSlackBinding({api:t.api,botToken:t.credentials?.botToken,channelId:r,threadTs:``,installationTeamId:a,teamId:t.teamId}),n={card:o.card};o.fallbackText!==void 0&&(n.fallbackText=o.fallbackText),s=(await e.post(n)).id}let c=s||crypto.randomUUID(),l=n.audience===void 0?void 0:normalizeChannelAudience(n.audience),u={channelId:r,installationTeamId:a??null,threadTs:s||null,teamId:t.teamId??null,triggeringUserId:t.triggeringUserId??null};return l!==void 0&&(u.audience=l),t.from(slackContinuationToken(r,c)).send(e.message,{auth:e.auth,state:u,title:e.title})}function shouldDropSlackHttpTimeoutRetry(e){return Number(e.get(`x-slack-retry-num`)??`0`)>=1&&e.get(`x-slack-retry-reason`)===`http_timeout`}async function handleEventPost(e){let{config:t}=e,n,r;try{n=parseSlackWebhookBody(e.body,{headers:e.headers}),r=parseSlackEventEnvelope(e.body)}catch(e){return log.warn(`inbound webhook body is not valid JSON`,{error:e}),new Response(`ok`)}if(n.kind===`url_verification`)return new Response(n.challenge,{status:200,headers:{"content-type":`text/plain`}});if(r===null)return new Response(`ok`);let i=typeof r.api_app_id==`string`?r.api_app_id:void 0,a=slackEventBotUserId(r),o=slackEventReceivingBotUserId(r),s=slackEventInstallationTeamId(r),dispatch=null,c=null,dispatchMessage=(n,r,c)=>()=>dispatchSlackMessage({api:e.api,appId:i,botUserId:a,receivingBotUserId:o,from:e.from,resolveSession:e.resolveSession,credentials:t.credentials,handler:c,installationTeamId:s,kind:n,message:r,received:e.received,threadContext:t.threadContext,uploadPolicy:e.uploadPolicy});if(n.kind===`app_mention`||n.kind===`direct_message`){let e=n.kind,r=slackMessageFromWebhookPayload(n);if(r!==null&&!isSelfAuthoredSlackMessage({appId:i,botUserId:a},r)){let n=(e===`app_mention`?t.onAppMention:t.onDirectMessage)??t.onMessage;n===void 0?c=dispatchMessage(e,r,defaultOnMessage):dispatch=dispatchMessage(e,r,n)}}let l=t.onMessage;if(dispatch===null&&l!==void 0){let e=parseMessageEvent(r);e!==null&&!isSelfAuthoredSlackMessage({appId:i,botUserId:a},e)&&(a===void 0||!e.text.includes(`<@${a}`))&&(dispatch=dispatchMessage(`channel_message`,e,l))}let u=t.onEvent;if(dispatch===null&&u!==void 0&&(dispatch=()=>dispatchSlackEvent({api:e.api,from:e.from,resolveSession:e.resolveSession,credentials:t.credentials,envelope:r,handler:u,installationTeamId:s})),dispatch??=c,dispatch===null)return new Response(`ok`);let d=r.event_id;if(d){if(e.handledEvents.has(d))return log.warn(`received a duplicate event`,{event_id:d,event_time:r.event_time,retry_num:n.retry?.num??`(null)`,retry_reason:n.retry?.reason??`(null)`}),new Response(`ok`);markEventHandled(d,e.handledEvents)}return e.waitUntil(dispatch()),new Response(`ok`)}function isSelfAuthoredSlackMessage(e,t){return e.botUserId!==void 0&&t.author?.userId===e.botUserId||e.appId!==void 0&&t.raw.app_id===e.appId}async function dispatchSlackMessage(e){let t=slackContinuationToken(e.message.channelId,e.message.threadTs),{thread:n,slack:r}=buildSlackBinding({api:e.api,appId:e.appId,botToken:e.credentials?.botToken,botUserId:e.botUserId,channelId:e.message.channelId,threadTs:e.message.threadTs,installationTeamId:e.installationTeamId,teamId:e.message.teamId}),i=e.message.author,a={channelId:e.message.channelId,installationTeamId:e.installationTeamId??null,teamId:e.message.teamId??null,threadTs:e.message.threadTs,triggeringMessageTs:e.message.ts,triggeringUserId:i?.userId??null},o=bindSlackSessionOperations({address:t,defaultAuth:i===void 0?null:buildSlackAuthContext({channelId:e.message.channelId,fullName:i.fullName,isBot:i.isBot,teamId:e.message.teamId,threadTs:e.message.threadTs,userId:i.userId,userName:i.userName}),from:e.from,resolveSession:e.resolveSession,state:a}),s,isDMOrPrivateChannel=()=>s??=isPrivateSlackConversation({channelId:e.message.channelId,raw:e.message.raw,request:r.request}),c=e.kind===`app_mention`||e.botUserId!==void 0&&e.message.text.includes(`<@${e.botUserId}`),l={...o,isBotMentioned:()=>c,isDMOrPrivateChannel,isSubscribed:async()=>await o.resolveSession()!==void 0,slack:r,thread:n},u=e.kind===`channel_message`?void 0:acknowledgeMessage(e.received,e.message,{slack:r,thread:n}),d;try{d=await e.handler(l,e.message)}catch(t){logError(log,`${e.kind} handler failed`,t,{channelId:e.message.channelId})}if(d==null){u!==void 0&&(await u,await n.startTyping());return}await(u??acknowledgeMessage(e.received,e.message,{slack:r,thread:n}));let f=await isDMOrPrivateChannel();a.audience=e.kind===`direct_message`||f?`private`:`public`,await deliverSlackMessage({botUserId:e.receivingBotUserId,credentials:e.credentials,kind:e.kind,isPrivateConversation:f,isMentioned:c,message:e.message,result:d,sessionOperations:o,thread:n,threadContext:e.threadContext,uploadPolicy:e.uploadPolicy})}async function acknowledgeMessage(e,t,n){try{await e(t,n)}catch(e){logError(log,`received renderer failed`,e,{channelId:t.channelId})}}async function dispatchSlackEvent(e){let t=e.envelope.event.team_id,n=typeof t==`string`?t:typeof e.envelope.team_id==`string`?e.envelope.team_id:void 0,r=[],sourceFor=t=>e.from(slackContinuationToken(t.channelId,t.threadTs)),i={cancel:({target:e,turnId:t})=>sourceFor(e).cancel({turnId:t}),clear:({target:e})=>sourceFor(e).clear(),compact:({target:e})=>sourceFor(e).compact(),envelope:e.envelope,reset:({reason:e,target:t})=>sourceFor(t).reset({reason:e}),resolveSession:({target:t})=>e.resolveSession(slackContinuationToken(t.channelId,t.threadTs)),respond:(t,{auth:n,target:r})=>sourceFor(r).respond(t,{auth:n,state:withSlackResponder(void 0,typeof e.envelope.event.user==`string`?e.envelope.event.user:void 0)}),send:(t,{auth:r,target:i,title:a})=>receiveOnSlack({auth:r,message:t,target:i,title:a},{from:e.from,api:e.api,credentials:e.credentials,installationTeamId:e.installationTeamId,teamId:n,...typeof e.envelope.event.user==`string`?{triggeringUserId:e.envelope.event.user}:{}}),slack:buildSlackWorkspaceHandle({api:e.api,botToken:e.credentials?.botToken,installationTeamId:e.installationTeamId,teamId:n}),waitUntil(e){r.push(e)}};try{await e.handler(i,e.envelope.event)}catch(t){logError(log,`event handler failed`,t,{eventId:e.envelope.event_id,eventType:e.envelope.event.type})}await Promise.allSettled(r)}async function verifyInbound(e,t){try{return await verifySlackRequest$1(e,{signingSecret:t?.signingSecret??(t?.webhookVerifier?void 0:process.env.SLACK_SIGNING_SECRET),webhookVerifier:t?.webhookVerifier})}catch(e){return log.warn(`slack inbound verification failed`,{error:e}),null}}async function deliverSlackMessage(e){let{message:t,thread:n}=e;try{let r=e.threadContext===void 0?[]:await loadThreadContextMessages(n,t,e.threadContext),i=formatSlackThreadContext(r),a=await collectInboundFileParts({mention:t,thread:n,policy:e.uploadPolicy}),o={botUserId:e.botUserId,channelId:t.channelId,fullName:t.author?.fullName,isMentioned:e.isMentioned,teamId:t.teamId,threadTs:t.threadTs,userId:t.author?.userId??``,userName:t.author?.userName},s=formatSlackInboundMessage(o,t),c=buildSlackTurnMessage(i===void 0?s:`${i}\n\n${s}`,a),l=e.result.context??[],u=e.isPrivateConversation?`Private message`:e.result.title??t.markdown,d=l.length===0?{auth:e.result.auth,title:u}:{auth:e.result.auth,context:l,title:u};await e.sessionOperations.send(c,d)}catch(n){logError(log,`${e.kind} delivery failed`,n,{channelId:t.channelId})}}function recordSlackPrincipal(e,t,n){if(t===null)return;let r=n.state?.triggeringUserId,i=slackUserIdFromAuthContext(t)??(typeof r==`string`?r:void 0);i!==void 0&&(e.slackUsersByPrincipal={...e.slackUsersByPrincipal,[t.principalId]:i})}export{slackChannel};
1
+ import{markEventHandled}from"./utils.js";import{createLogger,logError}from"#internal/logging.js";import{normalizeChannelAudience}from"#shared/channel-audience.js";import{setChannelBuildMetadata}from"#channel/compiled-channel.js";import{defaultDeliverResult}from"#channel/adapter.js";import{POST,defineChannel}from"#public/definitions/channel.js";import{mergeUploadPolicy}from"#public/channels/upload-policy.js";import{resolveSlackTransportOptions}from"#public/channels/slack/transport.js";import{buildSlackAuthContext,slackUserIdFromAuthContext}from"#public/channels/slack/auth.js";import{buildSlackBinding,buildSlackWorkspaceHandle,slackContinuationToken}from"#public/channels/slack/api.js";import{defaultInputRequestedHandler}from"#public/channels/slack/approval-cards.js";import{withFinalReplyDelivery,withUndeliveredReplyNote}from"#public/channels/slack/reply-delivery.js";import{defaultEvents,defaultOnMessage,defaultReceived}from"#public/channels/slack/defaults.js";import{composeSlackRenderers}from"#public/channels/slack/renderers.js";import{loadThreadContextMessages}from"#public/channels/slack/thread.js";import{parseSlackWebhookBody}from"#compiled/@chat-adapter/slack/webhook.js";import{bindSlackSessionOperations,withSlackResponder}from"#public/channels/slack/session-operations.js";import{buildSlackTurnMessage,collectInboundFileParts,createSlackFetchFile}from"#public/channels/slack/attachments.js";import{renderDefaultSlackTaskCard,withTaskCards}from"#public/channels/slack/task-card.js";import{parseMessageEvent,parseSlackEventEnvelope,slackEventBotUserId,slackEventInstallationTeamId,slackEventReceivingBotUserId,slackMessageFromWebhookPayload}from"#public/channels/slack/inbound.js";import{formatSlackInboundMessage,formatSlackThreadContext}from"#public/channels/slack/model-context.js";import{isPrivateSlackConversation}from"#public/channels/slack/privacy.js";import{SLACK_CHANNEL_DEFAULT_ROUTE}from"#public/channels/slack/constants.js";import{defineSlackAppManifest}from"#public/channels/slack/app-manifest.js";import{handleInteractionPost}from"#public/channels/slack/interactions.js";import{verifySlackRequest as verifySlackRequest$1}from"#public/channels/slack/verify.js";const log=createLogger(`slack.channel`);function rebuildSlackContext(e,t,n,r){let{thread:i,slack:a}=buildSlackBinding({api:n,botToken:r?.botToken,channelId:e.channelId??``,threadTs:e.threadTs??``,installationTeamId:e.installationTeamId??void 0,teamId:e.teamId??void 0,onThreadTsChanged(n){e.threadTs=n,e.channelId&&t.continuation?.alias(slackContinuationToken(e.channelId,n))}});return{thread:i,slack:a,state:e}}function slackChannel(e={}){let t=resolveSlackTransportOptions(e.api),n=mergeUploadPolicy(e.uploadPolicy),r=createSlackFetchFile({api:t,botToken:e.credentials?.botToken}),i=e.onInputResponse??defaultOnInputResponse,a=composeSlackRenderers(e.renderers??[],{events:{...defaultEvents,"input.requested":defaultInputRequestedHandler(e.approvalChannel)},received:defaultReceived,taskCard:renderDefaultSlackTaskCard}),o=a.events[`turn.started`],s=withTaskCards({...a.events,"message.completed":withFinalReplyDelivery(a.events[`message.completed`]),async"turn.started"(e,t,n){let r=slackUserIdFromAuthContext(n.session.auth.current);r!==void 0&&(t.state.triggeringUserId=r),await o?.(e,t,n)}},a.taskCard),c=new Set,l=defineChannel({kindHint:`slack`,turnPolicy:e.turnPolicy,state:{channelId:null,threadTs:null,teamId:null,installationTeamId:null,triggeringUserId:null,triggeringMessageTs:null,pendingToolCallMessage:null,lastReasoningTypingAtMs:null,lastReasoningTypingStatus:null,pendingAuthMessageTs:{},pendingApprovalCards:{},slackUsersByPrincipal:{}},fetchFile:r,metadata(e){return{channelId:e.channelId,teamId:e.teamId,threadTs:e.threadTs,triggeringUserId:e.triggeringUserId??null}},audience:({state:e})=>e.audience??`unknown`,context(n,r){return rebuildSlackContext(n,r,t,e.credentials)},deliver(e,t){return recordSlackPrincipal(t.state,t.session.auth.current,e),defaultDeliverResult(withUndeliveredReplyNote(t.state,e))},routes:[POST(e.route??SLACK_CHANNEL_DEFAULT_ROUTE,async(r,o)=>{let{waitUntil:s}=o,{from:l,resolveSession:u}=o,d=await verifyInbound(r,e.credentials);return d===null?new Response(`unauthorized`,{status:401}):shouldDropSlackHttpTimeoutRetry(r.headers)?new Response(`ok`):(r.headers.get(`content-type`)??``).includes(`application/x-www-form-urlencoded`)?handleInteractionPost(d,{from:l,resolveSession:u,waitUntil:s},{api:t,config:e,onInputResponse:i}):handleEventPost({api:t,body:d,from:l,resolveSession:u,waitUntil:s,config:e,received:a.received,uploadPolicy:n,handledEvents:c,headers:r.headers})})],receive(n,{from:r}){return receiveOnSlack(n,{from:r,api:t,credentials:e.credentials})},events:s}),u=e.credentials,d=defineSlackAppManifest({botName:e.botName});return setChannelBuildMetadata(l,e=>({externalCredentials:u?.vercelConnect,manifest:d.build(e)})),l}function defaultOnInputResponse(e){return{auth:e.defaultAuth}}async function receiveOnSlack(e,t){let n=e.target,r=n.channelId;if(!r||typeof r!=`string`)throw Error(`slackChannel().receive requires target.channelId.`);let i=typeof n.threadTs==`string`?n.threadTs:``,a=typeof n.installationTeamId==`string`?n.installationTeamId:t.installationTeamId,o=n.initialMessage;if(o&&i.length>0)throw Error("slackChannel().receive: `threadTs` and `initialMessage` are mutually exclusive.");let s=i;if(o){let{thread:e}=buildSlackBinding({api:t.api,botToken:t.credentials?.botToken,channelId:r,threadTs:``,installationTeamId:a,teamId:t.teamId}),n={card:o.card};o.fallbackText!==void 0&&(n.fallbackText=o.fallbackText),s=(await e.post(n)).id}let c=s||crypto.randomUUID(),l=n.audience===void 0?void 0:normalizeChannelAudience(n.audience),u={channelId:r,installationTeamId:a??null,threadTs:s||null,teamId:t.teamId??null,triggeringUserId:t.triggeringUserId??null};return l!==void 0&&(u.audience=l),t.from(slackContinuationToken(r,c)).send(e.message,{auth:e.auth,state:u,title:e.title})}function shouldDropSlackHttpTimeoutRetry(e){return Number(e.get(`x-slack-retry-num`)??`0`)>=1&&e.get(`x-slack-retry-reason`)===`http_timeout`}async function handleEventPost(e){let{config:t}=e,n,r;try{n=parseSlackWebhookBody(e.body,{headers:e.headers}),r=parseSlackEventEnvelope(e.body)}catch(e){return log.warn(`inbound webhook body is not valid JSON`,{error:e}),new Response(`ok`)}if(n.kind===`url_verification`)return new Response(n.challenge,{status:200,headers:{"content-type":`text/plain`}});if(r===null)return new Response(`ok`);let i=typeof r.api_app_id==`string`?r.api_app_id:void 0,a=slackEventBotUserId(r),o=slackEventReceivingBotUserId(r),s=slackEventInstallationTeamId(r),dispatch=null,c=null,dispatchMessage=(n,r,c)=>()=>dispatchSlackMessage({api:e.api,appId:i,botUserId:a,receivingBotUserId:o,from:e.from,resolveSession:e.resolveSession,credentials:t.credentials,handler:c,installationTeamId:s,kind:n,message:r,received:e.received,threadContext:t.threadContext,uploadPolicy:e.uploadPolicy});if(n.kind===`app_mention`||n.kind===`direct_message`){let e=n.kind,r=slackMessageFromWebhookPayload(n,s);if(r!==null&&!isSelfAuthoredSlackMessage({appId:i,botUserId:a},r)){let n=(e===`app_mention`?t.onAppMention:t.onDirectMessage)??t.onMessage;n===void 0?c=dispatchMessage(e,r,defaultOnMessage):dispatch=dispatchMessage(e,r,n)}}let l=t.onMessage;if(dispatch===null&&l!==void 0){let e=parseMessageEvent(r);e!==null&&!isSelfAuthoredSlackMessage({appId:i,botUserId:a},e)&&(a===void 0||!e.text.includes(`<@${a}`))&&(dispatch=dispatchMessage(`channel_message`,e,l))}let u=t.onEvent;if(dispatch===null&&u!==void 0&&(dispatch=()=>dispatchSlackEvent({api:e.api,from:e.from,resolveSession:e.resolveSession,credentials:t.credentials,envelope:r,handler:u,installationTeamId:s})),dispatch??=c,dispatch===null)return new Response(`ok`);let d=r.event_id;if(d){if(e.handledEvents.has(d))return log.warn(`received a duplicate event`,{event_id:d,event_time:r.event_time,retry_num:n.retry?.num??`(null)`,retry_reason:n.retry?.reason??`(null)`}),new Response(`ok`);markEventHandled(d,e.handledEvents)}return e.waitUntil(dispatch()),new Response(`ok`)}function isSelfAuthoredSlackMessage(e,t){return e.botUserId!==void 0&&t.author?.userId===e.botUserId||e.appId!==void 0&&t.raw.app_id===e.appId}async function dispatchSlackMessage(e){let t=slackContinuationToken(e.message.channelId,e.message.threadTs),{thread:n,slack:r}=buildSlackBinding({api:e.api,appId:e.appId,botToken:e.credentials?.botToken,botUserId:e.botUserId,channelId:e.message.channelId,threadTs:e.message.threadTs,installationTeamId:e.installationTeamId,teamId:e.message.teamId}),i=e.message.author,a={channelId:e.message.channelId,installationTeamId:e.installationTeamId??null,teamId:e.message.teamId??null,threadTs:e.message.threadTs,triggeringMessageTs:e.message.ts,triggeringUserId:i?.userId??null},o=bindSlackSessionOperations({address:t,defaultAuth:i===void 0?null:buildSlackAuthContext({channelId:e.message.channelId,fullName:i.fullName,installationTeamId:e.installationTeamId,isBot:i.isBot,teamId:e.message.teamId,threadTs:e.message.threadTs,userId:i.userId,userName:i.userName}),from:e.from,resolveSession:e.resolveSession,state:a}),s,isDMOrPrivateChannel=()=>s??=isPrivateSlackConversation({channelId:e.message.channelId,raw:e.message.raw,request:r.request}),c=e.kind===`app_mention`||e.botUserId!==void 0&&e.message.text.includes(`<@${e.botUserId}`),l={...o,isBotMentioned:()=>c,isDMOrPrivateChannel,isSubscribed:async()=>await o.resolveSession()!==void 0,slack:r,thread:n},u=e.kind===`channel_message`?void 0:acknowledgeMessage(e.received,e.message,{slack:r,thread:n}),d;try{d=await e.handler(l,e.message)}catch(t){logError(log,`${e.kind} handler failed`,t,{channelId:e.message.channelId})}if(d==null){u!==void 0&&(await u,await n.startTyping());return}await(u??acknowledgeMessage(e.received,e.message,{slack:r,thread:n}));let f=await isDMOrPrivateChannel();a.audience=e.kind===`direct_message`||f?`private`:`public`,await deliverSlackMessage({botUserId:e.receivingBotUserId,credentials:e.credentials,kind:e.kind,isPrivateConversation:f,isMentioned:c,message:e.message,result:d,sessionOperations:o,thread:n,threadContext:e.threadContext,uploadPolicy:e.uploadPolicy})}async function acknowledgeMessage(e,t,n){try{await e(t,n)}catch(e){logError(log,`received renderer failed`,e,{channelId:t.channelId})}}async function dispatchSlackEvent(e){let t=e.envelope.event.team_id,n=typeof t==`string`?t:typeof e.envelope.team_id==`string`?e.envelope.team_id:void 0,r=[],sourceFor=t=>e.from(slackContinuationToken(t.channelId,t.threadTs)),i={cancel:({target:e,turnId:t})=>sourceFor(e).cancel({turnId:t}),clear:({target:e})=>sourceFor(e).clear(),compact:({target:e})=>sourceFor(e).compact(),envelope:e.envelope,reset:({reason:e,target:t})=>sourceFor(t).reset({reason:e}),resolveSession:({target:t})=>e.resolveSession(slackContinuationToken(t.channelId,t.threadTs)),respond:(t,{auth:n,target:r})=>sourceFor(r).respond(t,{auth:n,state:withSlackResponder(void 0,typeof e.envelope.event.user==`string`?e.envelope.event.user:void 0)}),send:(t,{auth:r,target:i,title:a})=>receiveOnSlack({auth:r,message:t,target:i,title:a},{from:e.from,api:e.api,credentials:e.credentials,installationTeamId:e.installationTeamId,teamId:n,...typeof e.envelope.event.user==`string`?{triggeringUserId:e.envelope.event.user}:{}}),slack:buildSlackWorkspaceHandle({api:e.api,botToken:e.credentials?.botToken,installationTeamId:e.installationTeamId,teamId:n}),waitUntil(e){r.push(e)}};try{await e.handler(i,e.envelope.event)}catch(t){logError(log,`event handler failed`,t,{eventId:e.envelope.event_id,eventType:e.envelope.event.type})}await Promise.allSettled(r)}async function verifyInbound(e,t){try{return await verifySlackRequest$1(e,{signingSecret:t?.signingSecret??(t?.webhookVerifier?void 0:process.env.SLACK_SIGNING_SECRET),webhookVerifier:t?.webhookVerifier})}catch(e){return log.warn(`slack inbound verification failed`,{error:e}),null}}async function deliverSlackMessage(e){let{message:t,thread:n}=e;try{let r=e.threadContext===void 0?[]:await loadThreadContextMessages(n,t,e.threadContext),i=formatSlackThreadContext(r),a=await collectInboundFileParts({mention:t,thread:n,policy:e.uploadPolicy}),o={botUserId:e.botUserId,channelId:t.channelId,fullName:t.author?.fullName,isMentioned:e.isMentioned,teamId:t.teamId,threadTs:t.threadTs,userId:t.author?.userId??``,userName:t.author?.userName},s=formatSlackInboundMessage(o,t),c=buildSlackTurnMessage(i===void 0?s:`${i}\n\n${s}`,a),l=e.result.context??[],u=e.isPrivateConversation?`Private message`:e.result.title??t.markdown,d=l.length===0?{auth:e.result.auth,title:u}:{auth:e.result.auth,context:l,title:u};await e.sessionOperations.send(c,d)}catch(n){logError(log,`${e.kind} delivery failed`,n,{channelId:t.channelId})}}function recordSlackPrincipal(e,t,n){if(t===null)return;let r=n.state?.triggeringUserId,i=slackUserIdFromAuthContext(t)??(typeof r==`string`?r:void 0);i!==void 0&&(e.slackUsersByPrincipal={...e.slackUsersByPrincipal,[t.principalId]:i})}export{slackChannel};
@@ -1 +1 @@
1
- import{createHash}from"node:crypto";import{createLogger,logError}from"#internal/logging.js";import{normalizeChannelAudience}from"#shared/channel-audience.js";import{contextStorage}from"#context/container.js";import{ScheduleIdKey}from"#context/keys.js";import{AGENT_TOOL_NAME}from"#tools/framework/agent-contract.js";import{formatDuration}from"#shared/format-duration.js";import{truncateMessageText}from"#public/channels/slack/limits.js";import{closeSettledTasks,taskCardView,trackTaskCardEvent}from"#channel/task-card.js";const log=createLogger(`slack.task-card`);function renderDefaultSlackTaskCard(e){if(e.tasks.length===0)return null;let t=collapseEarlierRows(e.tasks).map(toSlackTask),n=planTitle(e),r=slackBlockId(e.turnId),i=t.length===1?[{block_id:r,type:`task_card`,...t[0]}]:[{block_id:r,type:`plan`,tasks:t,title:n}],a=e.tasks.map(e=>e.title).join(`, `);return{blocks:i,text:truncateMessageText(`${n}: ${a}`)}}function planTitle(e){let{tasks:t}=e;if(e.state===`blocked`){let e=t.find(e=>e.blockedOn!==void 0)?.blockedOn;return waitingText(e?.kind??`input`)}let n=t.length,names=e=>n>1?agentNames(e):void 0;if(e.state===`working`){let e=t.filter(e=>e.status===`working`),r=n-e.length;if(r===0){let e=names(t);return e===void 0?`Working on ${countTasks(n)}`:`Asking ${e}`}let i=`${String(r)} of ${countTasks(n)} done`,a=names(e);return a===void 0?i:`Waiting on ${a} · ${i}`}let r=t.filter(e=>e.status===`failed`).length,i=t.filter(isInterrupted).length,a=[];r>0&&a.push(`${String(r)} failed`),i>0&&a.push(`${String(i)} stopped`);let o=turnDuration(t),s=`Finished ${countTasks(n)}${o===void 0?``:` in ${o}`}`;return a.length===0?s:`${s}: ${a.join(`, `)}`}function agentNames(e){if(e.some(e=>e.kind!==`agent`||e.name===AGENT_TOOL_NAME))return;let t=[...new Set(e.map(e=>e.name))];if(!(t.length===0||t.length>3))return t.length<=2?t.join(` and `):`${t.slice(0,-1).join(`, `)}, and ${t.at(-1)}`}function turnDuration(e){let t=e.flatMap(e=>e.settledAt===void 0?[]:[Date.parse(e.settledAt)]);if(t.length===0)return;let n=Math.min(...e.map(e=>Date.parse(e.startedAt)));return shownDuration(Math.max(...t)-n)}function taskDuration(e){if(e.settledAt!==void 0)return shownDuration(Date.parse(e.settledAt)-Date.parse(e.startedAt))}function shownDuration(e){return Number.isFinite(e)&&e>=1e3?formatDuration(e):void 0}function isInterrupted(e){return e.status===`cancelled`&&e.cancelReason!==`task_cancel`}function countTasks(e){return e===1?`1 task`:`${String(e)} tasks`}function collapseEarlierRows(e){if(e.length<=50)return e;let t=e.length-49,n=new Set(e.filter(e=>e.status!==`working`).slice(0,t).map(e=>e.id)),r=e.filter(e=>!n.has(e.id));if(n.size===0)return r.slice(-50);let i=e.some(e=>n.has(e.id)&&(e.status===`failed`||isInterrupted(e)));return[{id:`earlier`,kind:`tool`,name:`earlier`,startedAt:e[0].startedAt,status:i?`failed`:`completed`,taskId:`earlier`,title:`${countTasks(n.size)} finished earlier`},...r].slice(-50)}function toSlackTask(e){let t={status:slackStatus(e),task_id:slackTaskId(e.id),title:truncate(e.title,80)};e.blockedOn!==void 0&&(t.details=richText(blockerLine(e.blockedOn)));let n=outputLine(e);return n!==void 0&&(t.output=richText(n)),t}function slackStatus(e){switch(e.status){case`working`:case`blocked`:return`in_progress`;case`completed`:return`complete`;case`cancelled`:return isInterrupted(e)?`error`:`complete`;case`failed`:return`error`}}function outputLine(e){let t=taskDuration(e);switch(e.status){case`completed`:{if(t===void 0)return e.summary;let n=`Done in ${t}`;return e.summary===void 0?n:`${n}: ${e.summary}`}case`failed`:{let n=t===void 0?`Failed`:`Failed after ${t}`;return e.summary===void 0?n:`${n}: ${e.summary}`}case`cancelled`:return stoppedLine(e.cancelReason);default:return}}function stoppedLine(e){switch(e){case`task_cancel`:return`Stopped early since it was no longer needed`;case`turn_cancelled`:return`Stopped by request`;case`turn_ended`:return`Stopped when the turn ended`;case void 0:return`Stopped`}}function blockerLine(e){let t=waitingText(e.kind);return e.label===void 0?t:`${t}: ${e.label}`}function waitingText(e){switch(e){case`approval`:return`Waiting for approval`;case`authorization`:return`Waiting for sign-in`;case`input`:return`Waiting for a response`}}function richText(e){return{elements:[{elements:[{text:truncate(e,100),type:`text`}],type:`rich_text_section`}],type:`rich_text`}}function truncate(e,t){if(e.length<=t)return e;let n=e.slice(0,t-1),r=n.lastIndexOf(` `);return`${(r>t/2?n.slice(0,r):n).trimEnd()}…`}function slackTaskId(e){return e.replace(/[^a-zA-Z0-9_-]/g,`_`).slice(-200)}function slackBlockId(e){return`eve_task_card_${slackTaskId(e)}`}const TRACKED_EVENTS=[`actions.requested`,`action.result`,`task.started`,`task.settled`,`input.requested`,`input.resolved`,`authorization.required`,`authorization.completed`,`turn.completed`,`turn.failed`,`turn.cancelled`];function withTaskCards(e,t){let n={};for(let r of TRACKED_EVENTS){let i=e[r];n[r]=async(e,n,a)=>{let o={data:e,type:r};o.type===`task.started`&&await closeSettledCard(n,o.data,t);let s=trackTaskCardEvent(trackedTurns(n.state),o,new Date().toISOString());for(let[e,t]of Object.entries(s))rememberTurn(n.state,e,t);try{await i?.(e,n,a)}finally{for(let e of Object.keys(s))await writeTaskCard(n,e,t)}}}return{...e,...n}}async function closeSettledCard(e,t,n){let r=e.state.taskCards?.[t.turnId],i=r&&closeSettledTasks(r.turn,t.callId);i!==void 0&&(e.state.taskCards={...e.state.taskCards,[t.turnId]:{...r,turn:i.closed}},await writeTaskCard(e,t.turnId,n),e.state.taskCards={...e.state.taskCards,[t.turnId]:{turn:i.open}})}function trackedTurns(e){return Object.fromEntries(Object.entries(e.taskCards??{}).map(([e,t])=>[e,t.turn]))}function rememberTurn(e,t,n){let r={...e.taskCards,[t]:{...e.taskCards?.[t],turn:n}},i=Object.keys(r);for(let e of i.slice(0,Math.max(0,i.length-20)))delete r[e];e.taskCards=r}async function writeTaskCard(e,t,n){let r=e.state.taskCards?.[t];if(r===void 0)return;let i=normalizeChannelAudience(e.state.audience),a=taskCardView(t,r.turn,{audience:i}),{channelId:o,threadTs:s}=e.state,c=contextStorage.getStore()?.get(ScheduleIdKey)!==void 0,l=o&&s&&!c?{channelId:o,threadTs:s}:void 0,u=l===void 0?null:renderCard(n,a);if(l!==void 0&&u!==null){let n=createHash(`sha256`).update(JSON.stringify(u)).digest(`base64url`);if(n!==r.fingerprint){let i=await writeCardWithRetry(e.slack,{...l,card:u,ts:r.ts});if(i===void 0)return;e.state.taskCards={...e.state.taskCards,[t]:{fingerprint:n,ts:i,turn:r.turn}}}}a.state===`finished`&&forgetTurn(e.state,t)}function forgetTurn(e,t){let{[t]:n,...r}=e.taskCards??{};e.taskCards=r}function renderCard(e,t){try{return e(t)}catch(e){return logError(log,`task card renderer failed`,e,{turnId:t.turnId}),null}}async function writeCardWithRetry(e,t){for(let n of[1,2])try{return await writeCard(e,t)}catch(e){logError(log,`task card write failed`,e,{attempt:n}),n===1&&await new Promise(e=>setTimeout(e,1e3))}}async function writeCard(e,t){let n={blocks:t.card.blocks,channel:t.channelId,text:t.card.text};if(t.ts!==void 0){let r=await e.request(`chat.update`,{...n,ts:t.ts});if(r.ok===!0)return t.ts;if(r.error!==`message_not_found`)throw slackError(r.error)}let r=await e.request(`chat.postMessage`,{...n,thread_ts:t.threadTs,unfurl_links:!1,unfurl_media:!1});if(r.ok!==!0)throw slackError(r.error);if(typeof r.ts!=`string`||r.ts===``)throw Error(`Slack did not return a ts for the task card.`);return r.ts}function slackError(e){return Error(`Slack task card failed: ${e??`unknown_error`}`)}export{renderDefaultSlackTaskCard,withTaskCards};
1
+ import{createHash}from"node:crypto";import{createLogger,logError}from"#internal/logging.js";import{normalizeChannelAudience}from"#shared/channel-audience.js";import{contextStorage}from"#context/container.js";import{ScheduleIdKey}from"#context/keys.js";import{displayName}from"#shared/display-name.js";import{AGENT_TOOL_NAME}from"#tools/framework/agent-contract.js";import{formatDuration}from"#shared/format-duration.js";import{truncateMessageText}from"#public/channels/slack/limits.js";import{closeSettledTasks,taskCardView,trackTaskCardEvent}from"#channel/task-card.js";const log=createLogger(`slack.task-card`);function renderDefaultSlackTaskCard(e){if(e.tasks.length===0)return null;let t=collapseEarlierRows(e.tasks).map(toSlackTask),n=planTitle(e),r=slackBlockId(e.turnId),i=t.length===1?[{block_id:r,type:`task_card`,...t[0]}]:[{block_id:r,type:`plan`,tasks:t,title:n}],a=e.tasks.map(e=>e.title).join(`, `);return{blocks:i,text:truncateMessageText(`${n}: ${a}`)}}function planTitle(e){let{tasks:t}=e;if(e.state===`blocked`){let e=t.find(e=>e.blockedOn!==void 0)?.blockedOn;return waitingText(e?.kind??`input`)}let n=t.length,names=e=>n>1?agentNames(e):void 0;if(e.state===`working`){let e=t.filter(e=>e.status===`working`),r=n-e.length;if(r===0){let e=names(t);return e===void 0?`Working on ${countTasks(n)}`:`Asking ${e}`}let i=`${String(r)} of ${countTasks(n)} done`,a=names(e);return a===void 0?i:`Waiting on ${a} · ${i}`}let r=t.filter(e=>e.status===`failed`).length,i=t.filter(isInterrupted).length,a=[];r>0&&a.push(`${String(r)} failed`),i>0&&a.push(`${String(i)} stopped`);let o=turnDuration(t),s=`Finished ${countTasks(n)}${o===void 0?``:` in ${o}`}`;return a.length===0?s:`${s}: ${a.join(`, `)}`}function agentNames(e){if(e.some(e=>e.kind!==`agent`||e.name===AGENT_TOOL_NAME))return;let t=[...new Set(e.map(e=>displayName(e.name)))];if(!(t.length===0||t.length>3))return t.length<=2?t.join(` and `):`${t.slice(0,-1).join(`, `)}, and ${t.at(-1)}`}function turnDuration(e){let t=e.flatMap(e=>e.settledAt===void 0?[]:[Date.parse(e.settledAt)]);if(t.length===0)return;let n=Math.min(...e.map(e=>Date.parse(e.startedAt)));return shownDuration(Math.max(...t)-n)}function taskDuration(e){if(e.settledAt!==void 0)return shownDuration(Date.parse(e.settledAt)-Date.parse(e.startedAt))}function shownDuration(e){return Number.isFinite(e)&&e>=1e3?formatDuration(e):void 0}function isInterrupted(e){return e.status===`cancelled`&&e.cancelReason!==`task_cancel`}function countTasks(e){return e===1?`1 task`:`${String(e)} tasks`}function collapseEarlierRows(e){if(e.length<=50)return e;let t=e.length-49,n=new Set(e.filter(e=>e.status!==`working`).slice(0,t).map(e=>e.id)),r=e.filter(e=>!n.has(e.id));if(n.size===0)return r.slice(-50);let i=e.some(e=>n.has(e.id)&&(e.status===`failed`||isInterrupted(e)));return[{id:`earlier`,kind:`tool`,name:`earlier`,startedAt:e[0].startedAt,status:i?`failed`:`completed`,taskId:`earlier`,title:`${countTasks(n.size)} finished earlier`},...r].slice(-50)}function toSlackTask(e){let t={status:slackStatus(e),task_id:slackTaskId(e.id),title:truncate(e.title,80)};e.blockedOn!==void 0&&(t.details=richText(blockerLine(e.blockedOn)));let n=outputLine(e);return n!==void 0&&(t.output=richText(n)),t}function slackStatus(e){switch(e.status){case`working`:case`blocked`:return`in_progress`;case`completed`:return`complete`;case`cancelled`:return isInterrupted(e)?`error`:`complete`;case`failed`:return`error`}}function outputLine(e){let t=taskDuration(e);switch(e.status){case`completed`:{if(t===void 0)return e.summary;let n=`Done in ${t}`;return e.summary===void 0?n:`${n}: ${e.summary}`}case`failed`:{let n=t===void 0?`Failed`:`Failed after ${t}`;return e.summary===void 0?n:`${n}: ${e.summary}`}case`cancelled`:return stoppedLine(e.cancelReason);default:return}}function stoppedLine(e){switch(e){case`task_cancel`:return`Stopped early since it was no longer needed`;case`turn_cancelled`:return`Stopped by request`;case`turn_ended`:return`Stopped when the turn ended`;case void 0:return`Stopped`}}function blockerLine(e){let t=waitingText(e.kind);return e.label===void 0?t:`${t}: ${e.label}`}function waitingText(e){switch(e){case`approval`:return`Waiting for approval`;case`authorization`:return`Waiting for sign-in`;case`input`:return`Waiting for a response`}}function richText(e){return{elements:[{elements:[{text:truncate(e,100),type:`text`}],type:`rich_text_section`}],type:`rich_text`}}function truncate(e,t){if(e.length<=t)return e;let n=e.slice(0,t-1),r=n.lastIndexOf(` `);return`${(r>t/2?n.slice(0,r):n).trimEnd()}…`}function slackTaskId(e){return e.replace(/[^a-zA-Z0-9_-]/g,`_`).slice(-200)}function slackBlockId(e){return`eve_task_card_${slackTaskId(e)}`}const TRACKED_EVENTS=[`actions.requested`,`action.result`,`task.started`,`task.settled`,`input.requested`,`input.resolved`,`authorization.required`,`authorization.completed`,`turn.completed`,`turn.failed`,`turn.cancelled`];function withTaskCards(e,t){let n={};for(let r of TRACKED_EVENTS){let i=e[r];n[r]=async(e,n,a)=>{let o={data:e,type:r};o.type===`task.started`&&await closeSettledCard(n,o.data,t);let s=trackTaskCardEvent(trackedTurns(n.state),o,new Date().toISOString());for(let[e,t]of Object.entries(s))rememberTurn(n.state,e,t);try{await i?.(e,n,a)}finally{for(let e of Object.keys(s))await writeTaskCard(n,e,t)}}}return{...e,...n}}async function closeSettledCard(e,t,n){let r=e.state.taskCards?.[t.turnId],i=r&&closeSettledTasks(r.turn,t.callId);i!==void 0&&(e.state.taskCards={...e.state.taskCards,[t.turnId]:{...r,turn:i.closed}},await writeTaskCard(e,t.turnId,n),e.state.taskCards={...e.state.taskCards,[t.turnId]:{turn:i.open}})}function trackedTurns(e){return Object.fromEntries(Object.entries(e.taskCards??{}).map(([e,t])=>[e,t.turn]))}function rememberTurn(e,t,n){let r={...e.taskCards,[t]:{...e.taskCards?.[t],turn:n}},i=Object.keys(r);for(let e of i.slice(0,Math.max(0,i.length-20)))delete r[e];e.taskCards=r}async function writeTaskCard(e,t,n){let r=e.state.taskCards?.[t];if(r===void 0)return;let i=normalizeChannelAudience(e.state.audience),a=taskCardView(t,r.turn,{audience:i}),{channelId:o,threadTs:s}=e.state,c=contextStorage.getStore()?.get(ScheduleIdKey)!==void 0,l=o&&s&&!c?{channelId:o,threadTs:s}:void 0,u=l===void 0?null:renderCard(n,a);if(l!==void 0&&u!==null){let n=createHash(`sha256`).update(JSON.stringify(u)).digest(`base64url`);if(n!==r.fingerprint){let i=await writeCardWithRetry(e.slack,{...l,card:u,ts:r.ts});if(i===void 0)return;e.state.taskCards={...e.state.taskCards,[t]:{fingerprint:n,ts:i,turn:r.turn}}}}a.state===`finished`&&forgetTurn(e.state,t)}function forgetTurn(e,t){let{[t]:n,...r}=e.taskCards??{};e.taskCards=r}function renderCard(e,t){try{return e(t)}catch(e){return logError(log,`task card renderer failed`,e,{turnId:t.turnId}),null}}async function writeCardWithRetry(e,t){for(let n of[1,2])try{return await writeCard(e,t)}catch(e){logError(log,`task card write failed`,e,{attempt:n}),n===1&&await new Promise(e=>setTimeout(e,1e3))}}async function writeCard(e,t){let n={blocks:t.card.blocks,channel:t.channelId,text:t.card.text};if(t.ts!==void 0){let r=await e.request(`chat.update`,{...n,ts:t.ts});if(r.ok===!0)return t.ts;if(r.error!==`message_not_found`)throw slackError(r.error)}let r=await e.request(`chat.postMessage`,{...n,thread_ts:t.threadTs,unfurl_links:!1,unfurl_media:!1});if(r.ok!==!0)throw slackError(r.error);if(typeof r.ts!=`string`||r.ts===``)throw Error(`Slack did not return a ts for the task card.`);return r.ts}function slackError(e){return Error(`Slack task card failed: ${e??`unknown_error`}`)}export{renderDefaultSlackTaskCard,withTaskCards};
@@ -9,7 +9,7 @@ export declare function defaultTeamsAuth(message: TeamsMessageActivity | TeamsIn
9
9
  export declare function defaultOnMessage(ctx: TeamsContext, message: TeamsMessageActivity): Promise<TeamsInboundResult>;
10
10
  /** Built-in Teams event handlers for typing, replies, HITL, auth cards, and terminal errors. */
11
11
  export declare const defaultEvents: TeamsChannelEvents;
12
- /** Capitalizes the first character of a connection name for Teams auth card display (e.g. "linear" -> "Linear"). */
12
+ /** A connection name for the Teams auth card (`linear` → `Linear`). */
13
13
  export declare function formatConnectionDisplayName(connectionName: string): string;
14
14
  /** Builds final-state text for a completed connection authorization attempt. */
15
15
  export declare function buildAuthCompletedText(input: {
@@ -1,3 +1,3 @@
1
- import{extractErrorId,formatErrorHint}from"#internal/logging.js";import{parseJsonObject}from"#shared/json.js";import{splitTeamsMessageText}from"#public/channels/teams/api.js";import{renderAnsweredInputRequestMessage,renderInputRequestMessage}from"#public/channels/teams/hitl.js";function defaultTeamsAuth(e){let t=e.tenantId,n={activity_id:e.id,conversation_id:e.conversation.id,scope:e.scope,user_id:e.from.id};e.from.name!==void 0&&(n.user_name=e.from.name),e.from.aadObjectId!==void 0&&(n.aad_object_id=e.from.aadObjectId),t!==void 0&&(n.tenant_id=t),e.teamId!==void 0&&(n.team_id=e.teamId),e.teamsChannelId!==void 0&&(n.channel_id=e.teamsChannelId);let r=t?`teams:${t}:${e.from.id}`:`teams:${e.from.id}`;return{attributes:n,authenticator:`teams-activity`,issuer:t?`teams:${t}`:`teams`,principalId:r,principalType:e.from.role===`bot`?`service`:`user`,subject:e.from.aadObjectId}}async function defaultOnMessage(e,t){return t.from.role===`bot`||t.from.id===t.recipient.id||t.scope!==`personal`&&!t.isBotMentioned?null:(await e.thread.startTyping(),{auth:defaultTeamsAuth(t)})}const defaultEvents={async"turn.started"(e,t,n){await t.thread.startTyping()},async"actions.requested"(e,t,n){await t.thread.startTyping()},async"input.requested"(e,t,n){for(let n of e.requests){let e=await t.thread.post(renderInputRequestMessage(n,{adaptiveCardVersion:t.adaptiveCardVersion,replyToActivityId:t.teams.replyToActivityId}));n.kind===`tool-approval`&&e.id&&(t.state.pendingApprovalCards={...t.state.pendingApprovalCards,[n.requestId]:{activityId:e.id,prompt:n.prompt}})}},async"approval.settled"(e,t,n){let r=t.state.pendingApprovalCards??{},i=r[e.requestId];if(i===void 0)return;let a=t.state.approvalResponderAccounts?.[e.responderPrincipalId],o=e.outcome===`approved`?`Approved`:`Cancelled`,s=a?.name??a?.id;await t.thread.update(i.activityId,renderAnsweredInputRequestMessage({includeText:!1,label:s===void 0?o:`${o} by ${s}`,prompt:i.prompt}));let c={...r};delete c[e.requestId],t.state.pendingApprovalCards=c},async"message.completed"(e,t,n){if(e.finishReason!==`tool-calls`&&e.message)for(let n of splitTeamsMessageText(e.message))await t.thread.post(n)},async"session.failed"(e,t){let n=formatErrorHint(e),r=extractErrorId(e.details);await t.thread.post([`This session could not recover from an error${n}.`,``,`Start a new Teams conversation to continue.`,...r?[``,`Error id: ${r}`]:[]].join(`
1
+ import{extractErrorId,formatErrorHint}from"#internal/logging.js";import{displayProperName}from"#shared/display-name.js";import{parseJsonObject}from"#shared/json.js";import{splitTeamsMessageText}from"#public/channels/teams/api.js";import{renderAnsweredInputRequestMessage,renderInputRequestMessage}from"#public/channels/teams/hitl.js";function defaultTeamsAuth(e){let t=e.tenantId,n={activity_id:e.id,conversation_id:e.conversation.id,scope:e.scope,user_id:e.from.id};e.from.name!==void 0&&(n.user_name=e.from.name),e.from.aadObjectId!==void 0&&(n.aad_object_id=e.from.aadObjectId),t!==void 0&&(n.tenant_id=t),e.teamId!==void 0&&(n.team_id=e.teamId),e.teamsChannelId!==void 0&&(n.channel_id=e.teamsChannelId);let r=t?`teams:${t}:${e.from.id}`:`teams:${e.from.id}`;return{attributes:n,authenticator:`teams-activity`,issuer:t?`teams:${t}`:`teams`,principalId:r,principalType:e.from.role===`bot`?`service`:`user`,subject:e.from.aadObjectId}}async function defaultOnMessage(e,t){return t.from.role===`bot`||t.from.id===t.recipient.id||t.scope!==`personal`&&!t.isBotMentioned?null:(await e.thread.startTyping(),{auth:defaultTeamsAuth(t)})}const defaultEvents={async"turn.started"(e,t,n){await t.thread.startTyping()},async"actions.requested"(e,t,n){await t.thread.startTyping()},async"input.requested"(e,t,n){for(let n of e.requests){let e=await t.thread.post(renderInputRequestMessage(n,{adaptiveCardVersion:t.adaptiveCardVersion,replyToActivityId:t.teams.replyToActivityId}));n.kind===`tool-approval`&&e.id&&(t.state.pendingApprovalCards={...t.state.pendingApprovalCards,[n.requestId]:{activityId:e.id,prompt:n.prompt}})}},async"approval.settled"(e,t,n){let r=t.state.pendingApprovalCards??{},i=r[e.requestId];if(i===void 0)return;let a=t.state.approvalResponderAccounts?.[e.responderPrincipalId],o=e.outcome===`approved`?`Approved`:`Cancelled`,s=a?.name??a?.id;await t.thread.update(i.activityId,renderAnsweredInputRequestMessage({includeText:!1,label:s===void 0?o:`${o} by ${s}`,prompt:i.prompt}));let c={...r};delete c[e.requestId],t.state.pendingApprovalCards=c},async"message.completed"(e,t,n){if(e.finishReason!==`tool-calls`&&e.message)for(let n of splitTeamsMessageText(e.message))await t.thread.post(n)},async"session.failed"(e,t){let n=formatErrorHint(e),r=extractErrorId(e.details);await t.thread.post([`This session could not recover from an error${n}.`,``,`Start a new Teams conversation to continue.`,...r?[``,`Error id: ${r}`]:[]].join(`
2
2
  `))},async"turn.failed"(e,t,n){let r=formatErrorHint(e),i=extractErrorId(e.details);await t.thread.post([`I hit an error while handling your request${r}.`,``,`Please try again, rephrase, or reach out if it keeps failing.`,...i?[``,`Error id: ${i}`]:[]].join(`
3
- `))},async"authorization.required"(e,t,n){let r=e.authorization?.displayName??formatConnectionDisplayName(e.name),i=e.authorization?.url,a=i?`Authorization required for ${r}: ${i}`:`Authorization required for ${r}.`,o=await t.thread.post({attachments:[{content:parseJsonObject({$schema:`http://adaptivecards.io/schemas/adaptive-card.json`,actions:i?[{title:`Sign in with ${r}`,type:`Action.OpenUrl`,url:i}]:[],body:[{text:`Authorization required for ${r}`,type:`TextBlock`,weight:`Bolder`,wrap:!0},{text:t.state.triggeringUser?`Requested by ${t.state.triggeringUser.name??t.state.triggeringUser.id}.`:`No triggering user is available for a private prompt.`,type:`TextBlock`,wrap:!0}],type:`AdaptiveCard`,version:t.adaptiveCardVersion}),contentType:`application/vnd.microsoft.card.adaptive`}],text:a});o.id&&(t.state.pendingAuthActivityId=o.id)},async"authorization.completed"(e,t,n){e.outcome===`authorized`&&await t.thread.startTyping();let r=t.state.pendingAuthActivityId;if(!r)return;let i=buildAuthCompletedText({displayName:e.authorization?.displayName??formatConnectionDisplayName(e.name),outcome:e.outcome,reason:e.reason});await t.thread.update(r,renderAnsweredInputRequestMessage({prompt:i})),t.state.pendingAuthActivityId=null}};function formatConnectionDisplayName(e){return e.length===0?e:e.charAt(0).toUpperCase()+e.slice(1)}function buildAuthCompletedText(e){if(e.outcome===`authorized`)return`${e.displayName} connected.`;let t=e.reason===void 0?``:` (${e.reason})`;return`${e.displayName} authorization ${e.outcome}${t}.`}function teamsMentionUser(e){let t=e.name??e.id;return{mentioned:{id:e.id,name:e.name},text:`<at>${t}</at>`,type:`mention`}}export{buildAuthCompletedText,defaultEvents,defaultOnMessage,defaultTeamsAuth,formatConnectionDisplayName,teamsMentionUser};
3
+ `))},async"authorization.required"(e,t,n){let r=e.authorization?.displayName??formatConnectionDisplayName(e.name),i=e.authorization?.url,a=i?`Authorization required for ${r}: ${i}`:`Authorization required for ${r}.`,o=await t.thread.post({attachments:[{content:parseJsonObject({$schema:`http://adaptivecards.io/schemas/adaptive-card.json`,actions:i?[{title:`Sign in with ${r}`,type:`Action.OpenUrl`,url:i}]:[],body:[{text:`Authorization required for ${r}`,type:`TextBlock`,weight:`Bolder`,wrap:!0},{text:t.state.triggeringUser?`Requested by ${t.state.triggeringUser.name??t.state.triggeringUser.id}.`:`No triggering user is available for a private prompt.`,type:`TextBlock`,wrap:!0}],type:`AdaptiveCard`,version:t.adaptiveCardVersion}),contentType:`application/vnd.microsoft.card.adaptive`}],text:a});o.id&&(t.state.pendingAuthActivityId=o.id)},async"authorization.completed"(e,t,n){e.outcome===`authorized`&&await t.thread.startTyping();let r=t.state.pendingAuthActivityId;if(!r)return;let i=buildAuthCompletedText({displayName:e.authorization?.displayName??formatConnectionDisplayName(e.name),outcome:e.outcome,reason:e.reason});await t.thread.update(r,renderAnsweredInputRequestMessage({prompt:i})),t.state.pendingAuthActivityId=null}};function formatConnectionDisplayName(e){return displayProperName(e)}function buildAuthCompletedText(e){if(e.outcome===`authorized`)return`${e.displayName} connected.`;let t=e.reason===void 0?``:` (${e.reason})`;return`${e.displayName} authorization ${e.outcome}${t}.`}function teamsMentionUser(e){let t=e.name??e.id;return{mentioned:{id:e.id,name:e.name},text:`<at>${t}</at>`,type:`mention`}}export{buildAuthCompletedText,defaultEvents,defaultOnMessage,defaultTeamsAuth,formatConnectionDisplayName,teamsMentionUser};
@@ -126,6 +126,7 @@ export interface ChannelEvents<TCtx = void> {
126
126
  readonly "message.appended"?: ChannelEventHandler<"message.appended", TCtx>;
127
127
  readonly "reasoning.appended"?: ChannelEventHandler<"reasoning.appended", TCtx>;
128
128
  readonly "reasoning.completed"?: ChannelEventHandler<"reasoning.completed", TCtx>;
129
+ readonly "step.started"?: ChannelEventHandler<"step.started", TCtx>;
129
130
  readonly "step.completed"?: ChannelEventHandler<"step.completed", TCtx>;
130
131
  readonly "input.requested"?: ChannelEventHandler<"input.requested", TCtx>;
131
132
  readonly "input.resolved"?: ChannelEventHandler<"input.resolved", TCtx>;
@@ -1 +1 @@
1
- import{createMetadataAudienceProjector}from"#channel/audience.js";import{CHANNEL_SENTINEL}from"#channel/compiled-channel.js";import{defaultDeliverResult}from"#channel/adapter.js";import{buildCallbackContext}from"#context/build-callback-context.js";import{normalizeChannelCors}from"#channel/cors.js";import{HTTP_ADAPTER_KIND}from"#channel/http.js";import{DELETE,GET,HEAD,OPTIONS,PATCH,POST,PUT,WS}from"#channel/routes.js";const DISABLED_ROUTE_SENTINEL_KIND=`eve:disabled-channel`;function disableRoute(){return{kind:DISABLED_ROUTE_SENTINEL_KIND}}function isDisabledRouteSentinel(e){return typeof e==`object`&&!!e&&e.kind===DISABLED_ROUTE_SENTINEL_KIND}function defineChannel(e){let t=buildAdapter(e),n=normalizeChannelCors(e.cors);return{__kind:CHANNEL_SENTINEL,routes:e.routes,adapter:t,cors:n,receive:e.receive,turnPolicy:e.turnPolicy}}const eventTypes=Object.keys({"approval.candidate":null,"approval.settled":null,"context.cleared":null,"compaction.requested":null,"compaction.completed":null,"turn.started":null,"actions.requested":null,"action.partial":null,"action.result":null,"message.completed":null,"message.appended":null,"reasoning.appended":null,"reasoning.completed":null,"step.completed":null,"input.requested":null,"input.resolved":null,"task.started":null,"task.settled":null,"turn.waiting":null,"turn.failed":null,"turn.completed":null,"turn.cancelled":null,"session.failed":null,"session.completed":null,"session.waiting":null,"authorization.required":null,"authorization.completed":null});function buildAdapter(e){let t=e.state!=null,n=e.context!=null,r=e.fetchFile!==void 0,i=e.metadata,a=i!==void 0,o=e.audience,s=t||n||a,c={},l=!1,u={kind:e.kindHint??`defineChannel`},d=e.events;for(let e of eventTypes){let t=d?.[e];t&&(l=!0,c[e]=(n,r)=>{let{session:i,...a}=r,o={...a,continuation:i?.continuation===void 0?void 0:{token:i.continuation.token,alias:e=>i.continuation?.alias(e)}};if(e===`session.failed`)return t(n,o);let s=buildCallbackContext();return t(n,o,s)})}return!s&&!l&&!r?{kind:e.kindHint??HTTP_ADAPTER_KIND,...o===void 0?void 0:{instrumentation:{audience:o}}}:{kind:e.kindHint??`defineChannel`,state:t?{...e.state}:{},fetchFile:e.fetchFile,instrumentation:i===void 0&&o===void 0?void 0:{...i===void 0?void 0:{metadata(e){let{audience:t,...n}=i(e);return n}},...o===void 0?i===void 0?void 0:{audience:createMetadataAudienceProjector(u,i)}:{audience:o}},createAdapterContext(t){let r=t.state,i=t.session;return{...n?e.context(r,i):{},state:r,ctx:t.ctx,session:i}},deliver(t,n){return e.deliver===void 0?defaultDeliverResult(t):e.deliver(t,n)},...c}}export{DELETE,GET,HEAD,OPTIONS,PATCH,POST,PUT,WS,defineChannel,disableRoute,isDisabledRouteSentinel};
1
+ import{createMetadataAudienceProjector}from"#channel/audience.js";import{CHANNEL_SENTINEL}from"#channel/compiled-channel.js";import{defaultDeliverResult}from"#channel/adapter.js";import{buildCallbackContext}from"#context/build-callback-context.js";import{normalizeChannelCors}from"#channel/cors.js";import{HTTP_ADAPTER_KIND}from"#channel/http.js";import{DELETE,GET,HEAD,OPTIONS,PATCH,POST,PUT,WS}from"#channel/routes.js";const DISABLED_ROUTE_SENTINEL_KIND=`eve:disabled-channel`;function disableRoute(){return{kind:DISABLED_ROUTE_SENTINEL_KIND}}function isDisabledRouteSentinel(e){return typeof e==`object`&&!!e&&e.kind===DISABLED_ROUTE_SENTINEL_KIND}function defineChannel(e){let t=buildAdapter(e),n=normalizeChannelCors(e.cors);return{__kind:CHANNEL_SENTINEL,routes:e.routes,adapter:t,cors:n,receive:e.receive,turnPolicy:e.turnPolicy}}const eventTypes=Object.keys({"approval.candidate":null,"approval.settled":null,"context.cleared":null,"compaction.requested":null,"compaction.completed":null,"turn.started":null,"actions.requested":null,"action.partial":null,"action.result":null,"message.completed":null,"message.appended":null,"reasoning.appended":null,"reasoning.completed":null,"step.started":null,"step.completed":null,"input.requested":null,"input.resolved":null,"task.started":null,"task.settled":null,"turn.waiting":null,"turn.failed":null,"turn.completed":null,"turn.cancelled":null,"session.failed":null,"session.completed":null,"session.waiting":null,"authorization.required":null,"authorization.completed":null});function buildAdapter(e){let t=e.state!=null,n=e.context!=null,r=e.fetchFile!==void 0,i=e.metadata,a=i!==void 0,o=e.audience,s=t||n||a,c={},l=!1,u={kind:e.kindHint??`defineChannel`},d=e.events;for(let e of eventTypes){let t=d?.[e];t&&(l=!0,c[e]=(n,r)=>{let{session:i,...a}=r,o={...a,continuation:i?.continuation===void 0?void 0:{token:i.continuation.token,alias:e=>i.continuation?.alias(e)}};if(e===`session.failed`)return t(n,o);let s=buildCallbackContext();return t(n,o,s)})}return!s&&!l&&!r?{kind:e.kindHint??HTTP_ADAPTER_KIND,...o===void 0?void 0:{instrumentation:{audience:o}}}:{kind:e.kindHint??`defineChannel`,state:t?{...e.state}:{},fetchFile:e.fetchFile,instrumentation:i===void 0&&o===void 0?void 0:{...i===void 0?void 0:{metadata(e){let{audience:t,...n}=i(e);return n}},...o===void 0?i===void 0?void 0:{audience:createMetadataAudienceProjector(u,i)}:{audience:o}},createAdapterContext(t){let r=t.state,i=t.session;return{...n?e.context(r,i):{},state:r,ctx:t.ctx,session:i}},deliver(t,n){return e.deliver===void 0?defaultDeliverResult(t):e.deliver(t,n)},...c}}export{DELETE,GET,HEAD,OPTIONS,PATCH,POST,PUT,WS,defineChannel,disableRoute,isDisabledRouteSentinel};
@@ -37,3 +37,5 @@ export interface StateHandle<T> {
37
37
  export declare function defineState<T>(name: string, initial: () => T): StateHandle<T>;
38
38
  /** Internal registration of generated, mount-owned keys. */
39
39
  export declare function defineMountedState<T>(mountId: string, name: string, initial: () => T): StateHandle<T>;
40
+ /** Durable context key name of one mount's state slot. */
41
+ export declare function mountedStateKeyName(mountId: string, name: string): string;
@@ -1 +1 @@
1
- import{loadContext}from"#context/container.js";import{ContextKey}from"#context/key.js";const RESERVED_STATE_NAME_PREFIXES=[`eve.`,`eve:mount.`];function defineState(e,t){let n=RESERVED_STATE_NAME_PREFIXES.find(t=>e.startsWith(t));if(n!==void 0)throw Error(`defineState() name "${e}" uses the reserved "${n}" prefix. Use an application-owned namespace instead.`);return createStateHandle(e,t)}function defineMountedState(e,t,n){return createStateHandle(`eve:mount.v1:${encodeURIComponent(e)}:${encodeURIComponent(t)}`,n)}function createStateHandle(e,t){let n=new ContextKey(e);return{get(){return loadContext().ensure(n,t)},update(e){let r=loadContext(),i=r.ensure(n,t);r.set(n,e(i))}}}export{defineMountedState,defineState};
1
+ import{loadContext}from"#context/container.js";import{ContextKey}from"#context/key.js";const RESERVED_STATE_NAME_PREFIXES=[`eve.`,`eve:mount.`];function defineState(e,t){let n=RESERVED_STATE_NAME_PREFIXES.find(t=>e.startsWith(t));if(n!==void 0)throw Error(`defineState() name "${e}" uses the reserved "${n}" prefix. Use an application-owned namespace instead.`);return createStateHandle(e,t)}function defineMountedState(e,t,n){return createStateHandle(mountedStateKeyName(e,t),n)}function mountedStateKeyName(e,t){return`eve:mount.v1:${encodeURIComponent(e)}:${encodeURIComponent(t)}`}function createStateHandle(e,t){let n=new ContextKey(e);return{get(){return loadContext().ensure(n,t)},update(e){let r=loadContext(),i=r.ensure(n,t);r.set(n,e(i))}}}export{defineMountedState,defineState,mountedStateKeyName};
@@ -1 +1 @@
1
- import{resolveEveDestinationPrefix}from"./server.js";import{ensureEveVercelOutputConfig}from"./vercel-output-config.js";import{EVE_ROUTE_PREFIX}from"#protocol/routes.js";import{joinEveRoutePath}from"#shared/eve-route-path.js";import{resolve}from"node:path";import{findEveProjectContext}from"#internal/project-context.js";import{assertValidPublicAgentName}from"#internal/agent-name.js";import{quoteVercelShellArgument,toVercelRelativePath}from"#internal/vercel/build-command.js";import{resolveEveBinaryPath}from"#shared/resolve-eve-binary.js";const EVE_NEXT_SERVICE_PREFIX=`/_eve_internal/eve`,EVE_NEXT_PRODUCTION_PORT_ENV=`EVE_NEXT_PRODUCTION_PORT`;function resolveApplicationRoot(e){return e===void 0||e.length===0?process.cwd():resolve(process.cwd(),e)}function resolveDevServerTimeout(e){if(e!==void 0){if(!Number.isFinite(e)||e<=0)throw Error(`eve Next.js development server timeout must be a positive number.`);return e}}function normalizeRoutePrefix(e){let t=(e.startsWith(`/`)?e:`/${e}`).replace(/\/+$/,``);if(t.length===0)throw Error(`eve Next.js service prefix cannot resolve to the root route.`);return t}function joinRoutePrefix(e,t){return`${e.replace(/\/+$/,``)}/${t.replace(/^\/+/,``)}`}function createNamedAgentRoutePrefix(e){return joinRoutePrefix(`/eve`,e)}function createNamedAgentServicePrefix(e,t){return joinRoutePrefix(e,t)}function createAgentRewriteSource(e){return joinEveRoutePath(e,`${EVE_ROUTE_PREFIX}/:path+`)}function normalizeOrigin(e){return new URL(e.trim()).origin}function readLocalProductionPort(e){let t=process.env[EVE_NEXT_PRODUCTION_PORT_ENV],n=t===void 0||t.trim().length===0?4274:Number.parseInt(t,10);if(t!==void 0&&t.trim().length>0&&String(n)!==t.trim())throw Error(`${EVE_NEXT_PRODUCTION_PORT_ENV} must be an integer between 1 and 65535.`);let r=n+e;if(r<1||r>65535)throw Error(`${EVE_NEXT_PRODUCTION_PORT_ENV} plus the eve agent count exceeds 65535.`);return r}function resolveProductionDestination(e){if(process.env.VERCEL)return{destinationPrefix:e.servicePrefix};let t=process.env.EVE_NEXT_PRODUCTION_ORIGIN;if(t!==void 0&&t.trim().length>0)return{destinationPrefix:joinRoutePrefix(normalizeOrigin(t),e.servicePrefix)};let n=`http://127.0.0.1:${String(readLocalProductionPort(e.localProductionPortOffset))}`;return{destinationPrefix:n,localServerOrigin:n}}function createEveRewriteRule(e){let t=createAgentRewriteSource(e.publicRoutePrefix);return{destination:joinRoutePrefix(e.destinationPrefix,`${EVE_ROUTE_PREFIX}/:path+`),source:t}}async function resolveExistingRewrites(e){return await e?.()}function mergeRewriteRules(e,t){return e===void 0?{beforeFiles:t}:isRewriteSections(e)?{...e,beforeFiles:[...t,...e.beforeFiles??[]]}:{afterFiles:e,beforeFiles:t}}function isRewriteSections(e){return!Array.isArray(e)}async function resolveNextConfig(e,t,n){return typeof e==`function`?await e(t,n):e}function assertValidAgentName(e){assertValidPublicAgentName(e,`eve Next.js agent name`)}function assertValidWithEveOptions(e){if(e.eveRoot!==void 0&&e.agents!==void 0)throw Error(`withEve cannot combine eveRoot with agents. Use one configuration form.`);if(e.agents===void 0)return;let t=Object.keys(e.agents);if(t.length===0)throw Error(`withEve agents must contain at least one named eve agent.`);for(let e of t)assertValidAgentName(e)}function createDefaultBuildCommand(e){let t=toVercelRelativePath(e.agentRoot,resolveEveBinaryPath(e.agentRoot));return`node ${quoteVercelShellArgument(t)} build`}async function normalizeAgentsConfig(e){let t=normalizeRoutePrefix(e.servicePrefix??`/_eve_internal/eve`),resolveBuildCommand=(t,n)=>n??e.eveBuildCommand??createDefaultBuildCommand({agentRoot:t});if(e.agents===void 0){let n=resolveApplicationRoot(e.eveRoot),r=await findEveProjectContext(n);if(r?.kind===`workspace`&&r.workspace.root===n&&r.workspace.members.length>0)return r.workspace.members.map((e,n)=>({appRoot:e.appRoot,buildCommand:resolveBuildCommand(e.appRoot,void 0),localProductionPortOffset:n,name:e.name,publicRoutePrefix:createNamedAgentRoutePrefix(e.name),servicePrefix:createNamedAgentServicePrefix(t,e.name),workspaceMember:!0}));let i=n;return[{appRoot:i,buildCommand:resolveBuildCommand(i,void 0),localProductionPortOffset:0,publicRoutePrefix:``,servicePrefix:t}]}let n=Object.entries(e.agents);if(n.length===0)throw Error(`withEve agents must contain at least one named eve agent.`);return n.map(([e,n],r)=>{assertValidAgentName(e);let i=typeof n==`string`?{root:n}:n,a=resolveApplicationRoot(i.root);return{appRoot:a,buildCommand:resolveBuildCommand(a,i.buildCommand),localProductionPortOffset:r,name:e,publicRoutePrefix:createNamedAgentRoutePrefix(e),servicePrefix:normalizeRoutePrefix(i.servicePrefix??createNamedAgentServicePrefix(t,e))}})}async function buildAgentWorkspaceExtensions(e){let[{buildWorkspaceExtensions:t},{DiscoveryProjectResolutionError:n}]=await Promise.all([import(`#internal/nitro/host/workspace-extensions.js`),import(`#discover/project.js`)]);for(let r of e)try{await t(r.appRoot)}catch(e){if(e instanceof n)continue;throw e}}function withEve(e,t={}){let n=process.cwd(),r=resolveDevServerTimeout(t.devServerTimeoutMs);return assertValidWithEveOptions(t),async function(i,a){let[o,s]=await Promise.all([normalizeAgentsConfig(t),resolveNextConfig(e,i,a)]);i===`phase-production-build`&&await buildAgentWorkspaceExtensions(o);let c=s.rewrites,l=await ensureEveVercelOutputConfig({agents:o.map(e=>{let t={appRoot:e.appRoot,buildCommand:e.buildCommand,name:e.name,publicRoutePrefix:e.publicRoutePrefix,servicePrefix:e.servicePrefix};return e.workspaceMember===!0&&(t.workspaceMember=!0),t}),nextRoot:n});if(process.env.VERCEL)return s;let u=new Map(l.agents.map(e=>[e.name,e])),d=o.map(e=>{let t=u.get(e.name),n=resolveProductionDestination({localProductionPortOffset:e.localProductionPortOffset,servicePrefix:t?.servicePrefix??e.servicePrefix});return{...e,productionDestination:n}});return{...s,async rewrites(){let[e,t]=await Promise.all([resolveExistingRewrites(c),Promise.all(d.map(async e=>createEveRewriteRule({destinationPrefix:await resolveEveDestinationPrefix({appRoot:e.appRoot,devServerTimeoutMs:r,logLabel:e.name,phase:i,productionDestinationPrefix:e.productionDestination.destinationPrefix,productionServerOrigin:e.productionDestination.localServerOrigin,workspaceAgentName:e.workspaceMember===!0?e.name:void 0}),publicRoutePrefix:e.publicRoutePrefix})))]);return mergeRewriteRules(e,t)}}}}export{EVE_NEXT_SERVICE_PREFIX,withEve};
1
+ import{EVE_NEXT_HOST,resolveEveDestinationPrefix}from"./server.js";import{ensureEveVercelOutputConfig}from"./vercel-output-config.js";import{EVE_ROUTE_PREFIX}from"#protocol/routes.js";import{joinEveRoutePath}from"#shared/eve-route-path.js";import{resolve}from"node:path";import{findEveProjectContext}from"#internal/project-context.js";import{assertValidPublicAgentName}from"#internal/agent-name.js";import{quoteVercelShellArgument,toVercelRelativePath}from"#internal/vercel/build-command.js";import{resolveEveBinaryPath}from"#shared/resolve-eve-binary.js";import{resolveDevServerTimeout}from"#shared/framework-eve-server.js";const EVE_NEXT_SERVICE_PREFIX=`/_eve_internal/eve`,EVE_NEXT_PRODUCTION_PORT_ENV=`EVE_NEXT_PRODUCTION_PORT`;function resolveApplicationRoot(e){return e===void 0||e.length===0?process.cwd():resolve(process.cwd(),e)}function normalizeRoutePrefix(e){let t=(e.startsWith(`/`)?e:`/${e}`).replace(/\/+$/,``);if(t.length===0)throw Error(`eve Next.js service prefix cannot resolve to the root route.`);return t}function joinRoutePrefix(e,t){return`${e.replace(/\/+$/,``)}/${t.replace(/^\/+/,``)}`}function createNamedAgentRoutePrefix(e){return joinRoutePrefix(`/eve`,e)}function createNamedAgentServicePrefix(e,t){return joinRoutePrefix(e,t)}function createAgentRewriteSource(e){return joinEveRoutePath(e,`${EVE_ROUTE_PREFIX}/:path+`)}function normalizeOrigin(e){return new URL(e.trim()).origin}function readLocalProductionPort(e){let t=process.env[EVE_NEXT_PRODUCTION_PORT_ENV],n=t===void 0||t.trim().length===0?4274:Number.parseInt(t,10);if(t!==void 0&&t.trim().length>0&&String(n)!==t.trim())throw Error(`${EVE_NEXT_PRODUCTION_PORT_ENV} must be an integer between 1 and 65535.`);let r=n+e;if(r<1||r>65535)throw Error(`${EVE_NEXT_PRODUCTION_PORT_ENV} plus the eve agent count exceeds 65535.`);return r}function resolveProductionDestination(e){if(process.env.VERCEL)return{destinationPrefix:e.servicePrefix};let t=process.env.EVE_NEXT_PRODUCTION_ORIGIN;if(t!==void 0&&t.trim().length>0)return{destinationPrefix:joinRoutePrefix(normalizeOrigin(t),e.servicePrefix)};let n=`http://127.0.0.1:${String(readLocalProductionPort(e.localProductionPortOffset))}`;return{destinationPrefix:n,localServerOrigin:n}}function createEveRewriteRule(e){let t=createAgentRewriteSource(e.publicRoutePrefix);return{destination:joinRoutePrefix(e.destinationPrefix,`${EVE_ROUTE_PREFIX}/:path+`),source:t}}async function resolveExistingRewrites(e){return await e?.()}function mergeRewriteRules(e,t){return e===void 0?{beforeFiles:t}:isRewriteSections(e)?{...e,beforeFiles:[...t,...e.beforeFiles??[]]}:{afterFiles:e,beforeFiles:t}}function isRewriteSections(e){return!Array.isArray(e)}async function resolveNextConfig(e,t,n){return typeof e==`function`?await e(t,n):e}function assertValidAgentName(e){assertValidPublicAgentName(e,`eve Next.js agent name`)}function assertValidWithEveOptions(e){if(e.eveRoot!==void 0&&e.agents!==void 0)throw Error(`withEve cannot combine eveRoot with agents. Use one configuration form.`);if(e.agents===void 0)return;let t=Object.keys(e.agents);if(t.length===0)throw Error(`withEve agents must contain at least one named eve agent.`);for(let e of t)assertValidAgentName(e)}function createDefaultBuildCommand(e){let t=toVercelRelativePath(e.agentRoot,resolveEveBinaryPath(e.agentRoot));return`node ${quoteVercelShellArgument(t)} build`}async function normalizeAgentsConfig(e){let t=normalizeRoutePrefix(e.servicePrefix??`/_eve_internal/eve`),resolveBuildCommand=(t,n)=>n??e.eveBuildCommand??createDefaultBuildCommand({agentRoot:t});if(e.agents===void 0){let n=resolveApplicationRoot(e.eveRoot),r=await findEveProjectContext(n);if(r?.kind===`workspace`&&r.workspace.root===n&&r.workspace.members.length>0)return r.workspace.members.map((e,n)=>({appRoot:e.appRoot,buildCommand:resolveBuildCommand(e.appRoot,void 0),localProductionPortOffset:n,name:e.name,publicRoutePrefix:createNamedAgentRoutePrefix(e.name),servicePrefix:createNamedAgentServicePrefix(t,e.name),workspaceMember:!0}));let i=n;return[{appRoot:i,buildCommand:resolveBuildCommand(i,void 0),localProductionPortOffset:0,publicRoutePrefix:``,servicePrefix:t}]}let n=Object.entries(e.agents);if(n.length===0)throw Error(`withEve agents must contain at least one named eve agent.`);return n.map(([e,n],r)=>{assertValidAgentName(e);let i=typeof n==`string`?{root:n}:n,a=resolveApplicationRoot(i.root);return{appRoot:a,buildCommand:resolveBuildCommand(a,i.buildCommand),localProductionPortOffset:r,name:e,publicRoutePrefix:createNamedAgentRoutePrefix(e),servicePrefix:normalizeRoutePrefix(i.servicePrefix??createNamedAgentServicePrefix(t,e))}})}async function buildAgentWorkspaceExtensions(e){let[{buildWorkspaceExtensions:t},{DiscoveryProjectResolutionError:n}]=await Promise.all([import(`#internal/nitro/host/workspace-extensions.js`),import(`#discover/project.js`)]);for(let r of e)try{await t(r.appRoot)}catch(e){if(e instanceof n)continue;throw e}}function withEve(e,t={}){let n=process.cwd(),r=resolveDevServerTimeout(t.devServerTimeoutMs,EVE_NEXT_HOST);return assertValidWithEveOptions(t),async function(i,a){let[o,s]=await Promise.all([normalizeAgentsConfig(t),resolveNextConfig(e,i,a)]);i===`phase-production-build`&&await buildAgentWorkspaceExtensions(o);let c=s.rewrites,l=await ensureEveVercelOutputConfig({agents:o.map(e=>{let t={appRoot:e.appRoot,buildCommand:e.buildCommand,name:e.name,publicRoutePrefix:e.publicRoutePrefix,servicePrefix:e.servicePrefix};return e.workspaceMember===!0&&(t.workspaceMember=!0),t}),nextRoot:n});if(process.env.VERCEL)return s;let u=new Map(l.agents.map(e=>[e.name,e])),d=o.map(e=>{let t=u.get(e.name),n=resolveProductionDestination({localProductionPortOffset:e.localProductionPortOffset,servicePrefix:t?.servicePrefix??e.servicePrefix});return{...e,productionDestination:n}});return{...s,async rewrites(){let[e,t]=await Promise.all([resolveExistingRewrites(c),Promise.all(d.map(async e=>createEveRewriteRule({destinationPrefix:await resolveEveDestinationPrefix({appRoot:e.appRoot,devServerTimeoutMs:r,logLabel:e.name,phase:i,productionDestinationPrefix:e.productionDestination.destinationPrefix,productionServerOrigin:e.productionDestination.localServerOrigin,workspaceAgentName:e.workspaceMember===!0?e.name:void 0}),publicRoutePrefix:e.publicRoutePrefix})))]);return mergeRewriteRules(e,t)}}}}export{EVE_NEXT_SERVICE_PREFIX,withEve};
@@ -1,4 +1,6 @@
1
+ import { type EveFrameworkHost } from "#shared/framework-eve-server.js";
1
2
  export declare const NEXT_PHASE_PRODUCTION_BUILD = "phase-production-build";
3
+ export declare const EVE_NEXT_HOST: EveFrameworkHost;
2
4
  export declare function resolveEveDestinationPrefix(input: {
3
5
  readonly appRoot: string;
4
6
  readonly devServerTimeoutMs?: number;
@@ -1,2 +1 @@
1
- import{mkdir,open,readFile,rm,stat,writeFile}from"node:fs/promises";import{resolvePackageRoot}from"#internal/application/package.js";import{existsSync}from"node:fs";import{join}from"node:path";import{spawn}from"node:child_process";import{readDevelopmentRuntimeArtifactsRevision}from"#services/dev-client/runtime-artifacts.js";const DEFAULT_SERVER_READY_TIMEOUT_MS=18e4,ANSI_ESCAPE_PATTERN=RegExp(`\x1B\\[[0-?]*[ -/]*[@-~]`,`g`),SERVER_URL_CANDIDATE_PATTERN=/https?:\/\/[^\s"'<>]+/g,NEXT_PHASE_PRODUCTION_BUILD=`phase-production-build`,globalStateSymbol=Symbol.for(`eve.next.state`);function getGlobalState(){let e=globalThis;return e[globalStateSymbol]??={servers:new Map},e[globalStateSymbol]}function normalizeOrigin(e){return new URL(e).origin}function readEveBaseUrlEnvironment(){let e=process.env.EVE_BASE_URL;if(e!==void 0&&e.trim().length!==0)return normalizeOrigin(e)}function isNodeErrorWithCode(e,t){return e instanceof Error&&`code`in e&&e.code===t}function delay(e){return new Promise(t=>setTimeout(t,e))}function isRecord(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function resolveEveCacheDirectory(e){return join(e,`.eve`)}function resolveEveDevServerRegistryPath(e){return join(resolveEveCacheDirectory(e),`next-dev-server.json`)}function resolveEveDevServerLockPath(e){return join(resolveEveCacheDirectory(e),`next-dev-server.lock`)}function normalizeDevServerRegistry(e){if(isRecord(e)&&typeof e.appRoot==`string`&&typeof e.origin==`string`&&typeof e.updatedAt==`string`&&(e.pid===null||typeof e.pid==`number`))try{return{appRoot:e.appRoot,origin:normalizeOrigin(e.origin),pid:e.pid,updatedAt:e.updatedAt}}catch{return}}async function readUsableEveDevServerRegistry(e){try{let t=normalizeDevServerRegistry(JSON.parse(await readFile(resolveEveDevServerRegistryPath(e),`utf8`)));return t===void 0||t.appRoot!==e||await readDevelopmentRuntimeArtifactsRevision({serverUrl:t.origin,timeoutMs:1e3})===void 0?void 0:t.origin}catch(e){if(isNodeErrorWithCode(e,`ENOENT`))return;throw e}}async function writeEveDevServerRegistry(e,t){await mkdir(resolveEveCacheDirectory(e),{recursive:!0}),await writeFile(resolveEveDevServerRegistryPath(e),`${JSON.stringify({appRoot:e,origin:t.origin,pid:t.process?.pid??null,updatedAt:new Date().toISOString()},null,2)}\n`)}async function removeStaleEveDevServerLock(e){try{let t=await stat(e);Date.now()-t.mtimeMs>3e4&&await rm(e,{force:!0})}catch(e){if(!isNodeErrorWithCode(e,`ENOENT`))throw e}}async function acquireEveDevServerLock(e,t){let n=resolveEveCacheDirectory(e),r=resolveEveDevServerLockPath(e),i=Date.now()+t;for(await mkdir(n,{recursive:!0});;)try{let e=await open(r,`wx`);return await e.writeFile(`${String(process.pid)}\n`),await e.close(),async()=>{await rm(r,{force:!0})}}catch(n){if(!isNodeErrorWithCode(n,`EEXIST`))throw n;if(await readUsableEveDevServerRegistry(e)!==void 0)return async()=>{};if(await removeStaleEveDevServerLock(r),Date.now()>i)throw Error(`Timed out after ${t}ms waiting for another Next.js process to start eve.`);await delay(100)}}function createEveBinaryPath(){return join(resolvePackageRoot(),`bin`,`eve.js`)}function isLoopbackHostname(e){return e===`localhost`||e===`::1`||e===`[::1]`||/^127(?:\.\d{1,3}){3}$/.test(e)}function parseLocalServerOrigin(e){let t=URL.parse(e);if(!(t===null||t.protocol!==`http:`&&t.protocol!==`https:`||!isLoopbackHostname(t.hostname)||t.port.length===0))return t.origin}function findLocalServerOrigin(e){for(let t of e.matchAll(SERVER_URL_CANDIDATE_PATTERN)){let e=t[0],n=parseLocalServerOrigin(e);if(n!==void 0)return n}}function formatEveDevOutputLine(e,t){let n=e.replace(/\r$/,``),r=n.replace(ANSI_ESCAPE_PATTERN,``).trim();if(r.length===0||/^☰eve\b/.test(r)||r===`CONFIGURATION_FIELD_CONFLICT`||r.startsWith(`[CONFIGURATION_FIELD_CONFLICT]`))return;let i=t===void 0?`[eve:dev]`:`[eve:dev:${t}]`,a=/server listening at\s+(https?:\/\/[^\s]+)/i.exec(n);return a===null?`${i} ${n}`:`${i} server listening at ${a[1]}`}function createEveDevOutputWriter(e){let t=``,writeLine=t=>{let n=formatEveDevOutputLine(t,e.logLabel);n!==void 0&&e.stream.write(`${n}\n`)};return{flush(){t.length!==0&&(writeLine(t),t=``)},write(e){t+=e.toString(`utf8`);let n=t.split(`
2
- `);t=n.pop()??``;for(let e of n)writeLine(e)}}}function startServerProcess(e){return new Promise((t,n)=>{let r=spawn(e.command,e.args,{cwd:e.cwd,env:{...process.env,...e.env},stdio:[`ignore`,`pipe`,`pipe`]}),i=createEveDevOutputWriter({logLabel:e.logLabel,stream:process.stderr}),a=createEveDevOutputWriter({logLabel:e.logLabel,stream:process.stdout}),o=setTimeout(()=>{r.kill(),n(Error(`Timed out after ${e.timeoutMs??DEFAULT_SERVER_READY_TIMEOUT_MS}ms waiting for eve to print its server URL.`))},e.timeoutMs??DEFAULT_SERVER_READY_TIMEOUT_MS),cleanup=()=>{clearTimeout(o),r.off(`error`,handleError),r.off(`exit`,handleEarlyExit)},flushOutput=()=>{a.flush(),i.flush()},handleError=e=>{flushOutput(),cleanup(),n(e)},handleEarlyExit=(e,t)=>{flushOutput(),cleanup(),n(Error(`eve server process exited before printing its server URL (code ${String(e)}, signal ${String(t)}).`))},handleOutput=e=>{let n=findLocalServerOrigin(e.toString(`utf8`));n!==void 0&&(cleanup(),t({origin:n,process:r}))};r.once(`error`,handleError),r.once(`exit`,handleEarlyExit),r.stdout.on(`data`,e=>{a.write(e),handleOutput(e)}),r.stderr.on(`data`,e=>{i.write(e),handleOutput(e)})})}function installProcessShutdown(e){let t=e.process;if(t===void 0)return e;let close=()=>{t.killed||t.kill()};return process.once(`beforeExit`,close),process.once(`exit`,close),e}function startEveDevServer(e,t,n,r){return startServerProcess({args:[createEveBinaryPath(),`dev`,`--no-ui`,`--port`,`0`,...r===void 0?[]:[`--agent`,r]],command:process.execPath,cwd:e,logLabel:n,timeoutMs:t}).then(e=>installProcessShutdown(e))}function startEveProductionServer(e){let t=new URL(e.origin),n=t.port,r=join(e.appRoot,`.output`,`server`,`index.mjs`);if(!existsSync(r))throw Error(`eve production output is missing at ${r}. Run eve build from ${e.appRoot} before starting Next.js.`);return startServerProcess({args:[r],command:process.execPath,cwd:e.appRoot,env:{HOST:t.hostname,NITRO_HOST:t.hostname,NITRO_PORT:n,PORT:n}}).then(installProcessShutdown)}async function resolveSharedEveDevServer(e,t,n,r){let i=await readUsableEveDevServerRegistry(e);if(i!==void 0)return{origin:i};let a=await acquireEveDevServerLock(e,t);try{let i=await readUsableEveDevServerRegistry(e);if(i!==void 0)return{origin:i};let a=await startEveDevServer(e,t,n,r);return await writeEveDevServerRegistry(e,a),a}finally{await a()}}async function resolveEveDestinationPrefix(e){let t=getGlobalState();if(process.env.NODE_ENV===`production`){if(e.phase===`phase-production-build`)return e.productionDestinationPrefix;let n=`production:${e.appRoot}`,r=t.servers.get(n);return r===void 0&&(r=process.env.VERCEL||e.productionServerOrigin===void 0?void 0:startEveProductionServer({appRoot:e.appRoot,origin:e.productionServerOrigin}),r!==void 0&&(r=r.catch(e=>{throw t.servers.delete(n),e}),t.servers.set(n,r))),r===void 0?e.productionDestinationPrefix:(await r).origin}let n=readEveBaseUrlEnvironment();if(n!==void 0)return n;if(process.env.NODE_ENV!==`development`)return e.productionDestinationPrefix;let r=`dev:${e.appRoot}`,i=t.servers.get(r);return i===void 0&&(i=resolveSharedEveDevServer(e.appRoot,e.devServerTimeoutMs??18e4,e.logLabel,e.workspaceAgentName).catch(e=>{throw t.servers.delete(r),e}),t.servers.set(r,i)),(await i).origin}export{NEXT_PHASE_PRODUCTION_BUILD,resolveEveDestinationPrefix};
1
+ import{resolveSharedEveDevServer,startEveProductionServer}from"#shared/framework-eve-server.js";const NEXT_PHASE_PRODUCTION_BUILD=`phase-production-build`,EVE_NEXT_HOST={label:`Next.js`,slug:`next`},globalStateSymbol=Symbol.for(`eve.next.state`);function getGlobalState(){let e=globalThis;return e[globalStateSymbol]??={servers:new Map},e[globalStateSymbol]}function readEveBaseUrlEnvironment(){let e=process.env.EVE_BASE_URL;if(e!==void 0&&e.trim().length!==0)return new URL(e).origin}async function resolveEveDestinationPrefix(e){let t=getGlobalState();if(process.env.NODE_ENV===`production`){if(e.phase===`phase-production-build`)return e.productionDestinationPrefix;let n=`production:${e.appRoot}`,r=t.servers.get(n);return r===void 0&&(r=process.env.VERCEL||e.productionServerOrigin===void 0?void 0:startEveProductionServer({appRoot:e.appRoot,host:EVE_NEXT_HOST,origin:e.productionServerOrigin}),r!==void 0&&(r=r.catch(e=>{throw t.servers.delete(n),e}),t.servers.set(n,r))),r===void 0?e.productionDestinationPrefix:(await r).origin}let n=readEveBaseUrlEnvironment();if(n!==void 0)return n;if(process.env.NODE_ENV!==`development`)return e.productionDestinationPrefix;let r=`dev:${e.appRoot}`,i=t.servers.get(r);return i===void 0&&(i=resolveSharedEveDevServer({appRoot:e.appRoot,host:EVE_NEXT_HOST,logLabel:e.logLabel,timeoutMs:e.devServerTimeoutMs,workspaceAgentName:e.workspaceAgentName}).catch(e=>{throw t.servers.delete(r),e}),t.servers.set(r,i)),(await i).origin}export{EVE_NEXT_HOST,NEXT_PHASE_PRODUCTION_BUILD,resolveEveDestinationPrefix};
@@ -3,6 +3,12 @@ import type { NuxtModule } from "@nuxt/schema";
3
3
  * Options for the eve Nuxt module.
4
4
  */
5
5
  export interface EveNuxtModuleOptions {
6
+ /**
7
+ * Maximum time in milliseconds to wait for the eve development server to
8
+ * start, including waiting for another Nuxt process to start it. Defaults
9
+ * to 180000 (three minutes).
10
+ */
11
+ devServerTimeoutMs?: number;
6
12
  /**
7
13
  * Path to the eve application root, resolved relative to the Nuxt project
8
14
  * root unless absolute. Defaults to the Nuxt project root. The dev server is
@@ -1 +1 @@
1
- import{joinRoutePrefix,normalizeOrigin,resolveProductionTarget}from"./routing.js";import{EVE_BASE_URL_ENV,resolveSharedEveDevServer}from"./dev-server.js";import{EVE_ROUTE_PREFIX}from"#protocol/routes.js";import{isAbsolute,resolve}from"node:path";import{addImports,defineNuxtModule,extendRouteRules}from"@nuxt/kit";import{ensureEveVercelServicesConfig,mergeEveVercelConfig}from"#shared/vercel-services.js";function resolveApplicationRoot(e,t){return t===void 0||t.length===0?e:isAbsolute(t)?t:resolve(e,t)}async function resolveEveProxyTarget(e){if(!e.dev)return resolveProductionTarget();let t=process.env[EVE_BASE_URL_ENV]?.trim();if(t&&t.length>0)return joinRoutePrefix(normalizeOrigin(t),EVE_ROUTE_PREFIX);let n=await resolveSharedEveDevServer(e.appRoot);return n.process!==void 0&&e.onDevServerSpawned?.(n.process),joinRoutePrefix(n.origin,EVE_ROUTE_PREFIX)}const eveNuxtModule=defineNuxtModule({meta:{name:`eve`,configKey:`eve`,compatibility:{nuxt:`>=4.0.0`}},defaults:{},async setup(e,t){let n=t.options.rootDir,r=resolveApplicationRoot(n,e.eveRoot);if(addImports({name:`useEveAgent`,from:`eve/vue`}),!t.options.dev&&process.env.VERCEL){let i=await ensureEveVercelServicesConfig({appRoot:r,eveBuildCommand:e.eveBuildCommand,frameworkName:`Nuxt`,hostRoot:n});if(i.mode===`generated`){let e=t.options.nitro;e.vercel={...e.vercel,config:mergeEveVercelConfig(e.vercel?.config,i)}}}else t.hook(`modules:done`,async()=>{let e=await resolveEveProxyTarget({appRoot:r,dev:t.options.dev,onDevServerSpawned:e=>{t.hook(`close`,()=>{e.killed||e.kill()})}});extendRouteRules(`${EVE_ROUTE_PREFIX}/**`,{proxy:`${e}/**`})})}});export{eveNuxtModule as default};
1
+ import{joinRoutePrefix,normalizeOrigin,resolveProductionTarget}from"./routing.js";import{EVE_ROUTE_PREFIX}from"#protocol/routes.js";import{isAbsolute,resolve}from"node:path";import{resolveDevServerTimeout,resolveSharedEveDevServer}from"#shared/framework-eve-server.js";import{addImports,defineNuxtModule,extendRouteRules}from"@nuxt/kit";import{ensureEveVercelServicesConfig,mergeEveVercelConfig}from"#shared/vercel-services.js";const EVE_NUXT_HOST={label:`Nuxt`,slug:`nuxt`};function resolveApplicationRoot(e,t){return t===void 0||t.length===0?e:isAbsolute(t)?t:resolve(e,t)}async function resolveEveProxyTarget(e){if(!e.dev)return resolveProductionTarget();let t=process.env.EVE_BASE_URL?.trim();if(t&&t.length>0)return joinRoutePrefix(normalizeOrigin(t),EVE_ROUTE_PREFIX);let n=await resolveSharedEveDevServer({appRoot:e.appRoot,host:EVE_NUXT_HOST,timeoutMs:e.devServerTimeoutMs});return n.process!==void 0&&e.onDevServerSpawned?.(n.process),joinRoutePrefix(n.origin,EVE_ROUTE_PREFIX)}const eveNuxtModule=defineNuxtModule({meta:{name:`eve`,configKey:`eve`,compatibility:{nuxt:`>=4.0.0`}},defaults:{},async setup(e,t){let n=t.options.rootDir,r=resolveApplicationRoot(n,e.eveRoot),i=resolveDevServerTimeout(e.devServerTimeoutMs,EVE_NUXT_HOST);if(addImports({name:`useEveAgent`,from:`eve/vue`}),!t.options.dev&&process.env.VERCEL){let i=await ensureEveVercelServicesConfig({appRoot:r,eveBuildCommand:e.eveBuildCommand,frameworkName:`Nuxt`,hostRoot:n});if(i.mode===`generated`){let e=t.options.nitro;e.vercel={...e.vercel,config:mergeEveVercelConfig(e.vercel?.config,i)}}}else t.hook(`modules:done`,async()=>{let e=await resolveEveProxyTarget({appRoot:r,dev:t.options.dev,devServerTimeoutMs:i,onDevServerSpawned:e=>{t.hook(`close`,()=>{e.killed||e.kill()})}});extendRouteRules(`${EVE_ROUTE_PREFIX}/**`,{proxy:`${e}/**`})})}});export{eveNuxtModule as default};
@@ -1,3 +1,6 @@
1
1
  export { useEveAgent, type PrepareSend, type UseEveAgentHelpers, type UseEveAgentOptions, type UseEveAgentSnapshot, type UseEveAgentStatus, } from "#react/use-eve-agent.js";
2
2
  export { type EveAgentReducer, type EveAgentReducerEvent, type ClientInputRespondedEvent, type ClientMessageFailedEvent, type ClientMessageSubmittedEvent, } from "#client/reducer.js";
3
+ export { conversationReducer } from "#client/conversation-reducer.js";
4
+ export { openConversationInputs } from "#client/conversation-state.js";
5
+ export type { AgentObservation, ConversationAgentSession, ConversationInput, ConversationState, ConversationTask, ConversationTaskCall, ConversationTurn, } from "#client/conversation-state.js";
3
6
  export { defaultMessageReducer, type EveAuthorizationChallenge, type EveAuthorizationOutcome, type EveAuthorizationPart, type EveMessageData, type EveDynamicToolPart, type EveMessageInputRequest, type EveMessage, type EveMessageMetadata, type EveMessagePart, type EveMessageToolMetadata, } from "#client/message-reducer.js";
@@ -1 +1 @@
1
- import{defaultMessageReducer}from"#client/message-reducer.js";import{useEveAgent}from"#react/use-eve-agent.js";export{defaultMessageReducer,useEveAgent};
1
+ import{openConversationInputs}from"#client/conversation-state.js";import{conversationReducer}from"#client/conversation-reducer.js";import{defaultMessageReducer}from"#client/message-reducer.js";import{useEveAgent}from"#react/use-eve-agent.js";export{conversationReducer,defaultMessageReducer,openConversationInputs,useEveAgent};
@@ -1,7 +1,7 @@
1
1
  import { type EveAgentStoreCallbacks, type EveAgentStoreSnapshot, type EveAgentStoreStatus, type PrepareSend } from "#client/eve-agent-store.js";
2
2
  import type { EveAgentReducer } from "#client/reducer.js";
3
3
  import type { ClientSession } from "#client/session.js";
4
- import { type EveMessageData } from "#client/message-reducer.js";
4
+ import type { ConversationState } from "#client/conversation-state.js";
5
5
  import type { MessageStreamEvent } from "#protocol/message.js";
6
6
  import type { UserContent } from "ai";
7
7
  import type { CancelSessionResult, ClientAuth, HeadersValue, RespondTurnOptions, SendTurnOptions, ClientSessionState } from "#client/types.js";
@@ -17,9 +17,9 @@ export type { PrepareSend };
17
17
  */
18
18
  export type UseEveAgentStatus = EveAgentStoreStatus;
19
19
  /**
20
- * Snapshot of an eve agent session: `data` (the reducer projection), `events`
21
- * (the authoritative server stream), `session` (resumable cursor), `status`,
22
- * and `error`.
20
+ * Snapshot of an eve agent session: `conversation` (canonical state), `data`
21
+ * (the selected view), `events` (the authoritative server stream), `session`
22
+ * (resumable cursor), `status`, and `error`.
23
23
  */
24
24
  export type UseEveAgentSnapshot<TData> = EveAgentStoreSnapshot<TData>;
25
25
  /**
@@ -82,6 +82,8 @@ export interface UseEveAgentOptions<TData> extends EveAgentStoreCallbacks<TData>
82
82
  * @default true
83
83
  */
84
84
  readonly optimistic?: boolean;
85
+ /** Follow each subagent call's session into `conversation.agents` while mounted. @default false */
86
+ readonly followSubagents?: boolean;
85
87
  /**
86
88
  * Prewarm an owned session when true. React observes this value across renders;
87
89
  * changing it from false to true prepares the current session, and reset checks
@@ -103,7 +105,7 @@ export interface UseEveAgentOptions<TData> extends EveAgentStoreCallbacks<TData>
103
105
  readonly resume?: boolean;
104
106
  readonly session?: ClientSession;
105
107
  }
106
- export declare function useEveAgent(options?: UseEveAgentOptions<EveMessageData>): UseEveAgentHelpers<EveMessageData>;
108
+ export declare function useEveAgent(options?: UseEveAgentOptions<ConversationState>): UseEveAgentHelpers<ConversationState>;
107
109
  export declare function useEveAgent<TData>(options: UseEveAgentOptions<TData> & {
108
110
  readonly reducer: EveAgentReducer<TData>;
109
111
  }): UseEveAgentHelpers<TData>;
@@ -1 +1 @@
1
- import{EveAgentStore,attachEveAgentStore,detachEveAgentStore}from"#client/eve-agent-store.js";import{defaultMessageReducer}from"#client/message-reducer.js";import{useCallback,useEffect,useMemo,useRef,useState,useSyncExternalStore}from"react";import{resolveEveAgentHost}from"#client/agent-host.js";function useEveAgent(e={}){let t=useRef(void 0),n=useRef(e.resume??!1),[r,i]=useState(n.current),[a,o]=useState(0),s=e.prewarm??!1;if(!t.current){if(n.current&&e.initialSession===void 0&&e.session===void 0)throw Error(`useEveAgent({ resume: true }) requires initialSession or session.`);let r=e.reducer??defaultMessageReducer();t.current=new EveAgentStore({auth:e.auth,headers:e.headers,host:resolveEveAgentHost({agent:e.agent,host:e.host}),initialEvents:e.initialEvents,initialSession:e.initialSession,optimistic:e.optimistic,reducer:r,session:e.session})}let c=t.current;c.setCallbacks({onError:e.onError,onEvent:e.onEvent,onFinish:e.onFinish,onSessionChange:e.onSessionChange,prepareSend:e.prepareSend});let l=useCallback(e=>c.subscribe(e),[c]),u=useSyncExternalStore(l,()=>c.snapshot,()=>c.snapshot);useEffect(()=>{let e=setTimeout(()=>attachEveAgentStore(c),0);return()=>{clearTimeout(e),detachEveAgentStore(c)}},[c]),useEffect(()=>{if(!s)return;let e=setTimeout(()=>void c.prewarm().catch(()=>{}),0);return()=>clearTimeout(e)},[a,s,c]),useEffect(()=>{if(!n.current)return;let e=!0,finish=()=>{e&&i(!1)},t=setTimeout(()=>void c.resume().then(finish,finish),0);return()=>{e=!1,clearTimeout(t)}},[c]);let d=useCallback(()=>c.cancel(),[c]),f=useCallback(()=>{c.reset(),o(e=>e+1)},[c]),p=useCallback(()=>c.prewarm(),[c]),m=useCallback(()=>c.resume(),[c]),h=useCallback((e,t)=>c.send({...t,message:e}),[c]),g=useCallback((e,t)=>c.send({...t,inputResponses:e}),[c]),_=r&&u.status===`ready`?{...u,status:`resuming`}:u;return useMemo(()=>({..._,cancel:d,prewarm:p,reset:f,respond:g,resume:m,send:h}),[d,p,f,g,m,h,_])}export{useEveAgent};
1
+ import{EveAgentStore,attachEveAgentStore,detachEveAgentStore}from"#client/eve-agent-store.js";import{conversationReducer}from"#client/conversation-reducer.js";import{useCallback,useEffect,useMemo,useRef,useState,useSyncExternalStore}from"react";import{resolveEveAgentHost}from"#client/agent-host.js";function useEveAgent(e={}){let t=useRef(void 0),n=useRef(e.resume??!1),[r,i]=useState(n.current),[a,o]=useState(0),s=e.prewarm??!1;if(!t.current){if(n.current&&e.initialSession===void 0&&e.session===void 0)throw Error(`useEveAgent({ resume: true }) requires initialSession or session.`);let r=e.reducer??conversationReducer;t.current=new EveAgentStore({auth:e.auth,headers:e.headers,host:resolveEveAgentHost({agent:e.agent,host:e.host}),initialEvents:e.initialEvents,initialSession:e.initialSession,optimistic:e.optimistic,followSubagents:e.followSubagents,reducer:r,session:e.session})}let c=t.current;c.setCallbacks({onError:e.onError,onEvent:e.onEvent,onFinish:e.onFinish,onSessionChange:e.onSessionChange,prepareSend:e.prepareSend});let l=useCallback(e=>c.subscribe(e),[c]),u=useSyncExternalStore(l,()=>c.snapshot,()=>c.snapshot);useEffect(()=>{let e=setTimeout(()=>attachEveAgentStore(c),0);return()=>{clearTimeout(e),detachEveAgentStore(c)}},[c]),useEffect(()=>{if(!s)return;let e=setTimeout(()=>void c.prewarm().catch(()=>{}),0);return()=>clearTimeout(e)},[a,s,c]),useEffect(()=>{if(!n.current)return;let e=!0,finish=()=>{e&&i(!1)},t=setTimeout(()=>void c.resume().then(finish,finish),0);return()=>{e=!1,clearTimeout(t)}},[c]);let d=useCallback(()=>c.cancel(),[c]),f=useCallback(()=>{c.reset(),o(e=>e+1)},[c]),p=useCallback(()=>c.prewarm(),[c]),m=useCallback(()=>c.resume(),[c]),h=useCallback((e,t)=>c.send({...t,message:e}),[c]),g=useCallback((e,t)=>c.send({...t,inputResponses:e}),[c]),_=r&&u.status===`ready`?{...u,status:`resuming`}:u;return useMemo(()=>({..._,cancel:d,prewarm:p,reset:f,respond:g,resume:m,send:h}),[d,p,f,g,m,h,_])}export{useEveAgent};
@@ -2,10 +2,7 @@
2
2
  * Parses a fetched spec body as either JSON or YAML.
3
3
  *
4
4
  * JSON is tried first (the common case and fastest path); on a parse
5
- * failure the body is treated as YAML. YAML is parsed by wrapping the
6
- * document in front-matter delimiters so the bundled `gray-matter`
7
- * engine reads the whole file — the same approach the eval YAML loader
8
- * uses, avoiding a second YAML dependency.
5
+ * failure the body is treated as YAML.
9
6
  */
10
7
  export declare function parseSpecDocument(text: string): unknown;
11
8
  /**
@@ -1 +1 @@
1
- import{isObject}from"#shared/guards.js";import{parseFrontmatter}from"#internal/helpers/gray-matter.js";import{isArray}from"#runtime/connections/openapi-schema.js";function parseSpecDocument(e){try{return JSON.parse(e)}catch{}let t=e.replace(/^\uFEFF/,``),n=t.trimStart().startsWith(`---`)?t:`---\n${t}\n---`;return parseFrontmatter(n).data}function extractServerUrl(e,t){let n=extractOpenApiServerUrl(e,t);return n===void 0?extractSwaggerBaseUrl(e,t):n}function extractOpenApiServerUrl(e,t){let n=e.servers;if(isArray(n))for(let e of n){if(!isObject(e)||typeof e.url!=`string`||e.url.length===0)continue;let n=isObject(e.variables)?substituteServerVariables(e.url,e.variables):e.url;if(n.startsWith(`http://`)||n.startsWith(`https://`))return n;if(typeof t==`string`&&URL.canParse(t))try{return new URL(n,t).toString()}catch{}}}function extractSwaggerBaseUrl(e,t){let n=typeof e.basePath==`string`?e.basePath:``,r=typeof e.host==`string`&&e.host.length>0?e.host:``,i=typeof t==`string`&&URL.canParse(t)?new URL(t):void 0,a=extractSwaggerScheme(e)??i?.protocol.replace(/:$/,``)??`https`;if(r.length>0)return`${a}://${r}${normalizeBasePath(n)}`;if(i!==void 0){let e=new URL(normalizeBasePath(n)||`/`,i.origin).toString();return e.endsWith(`/`)&&normalizeBasePath(n).length===0?e.slice(0,-1):e}}function extractSwaggerScheme(e){let t=e.schemes;if(isArray(t)){for(let e of t)if(e===`https`||e===`http`)return e}}function normalizeBasePath(e){let t=e.trim();return t.length===0||t===`/`?``:t.startsWith(`/`)?t:`/${t}`}function substituteServerVariables(e,t){return e.replace(/\{([^}]+)\}/g,(e,n)=>{let r=t[n];return isObject(r)&&typeof r.default==`string`?r.default:e})}export{extractServerUrl,parseSpecDocument};
1
+ import{isObject}from"#shared/guards.js";import{parseYaml}from"#internal/helpers/frontmatter.js";import{isArray}from"#runtime/connections/openapi-schema.js";function parseSpecDocument(e){try{return JSON.parse(e)}catch{}return parseYaml(e.replace(/^\uFEFF/,``))}function extractServerUrl(e,t){let n=extractOpenApiServerUrl(e,t);return n===void 0?extractSwaggerBaseUrl(e,t):n}function extractOpenApiServerUrl(e,t){let n=e.servers;if(isArray(n))for(let e of n){if(!isObject(e)||typeof e.url!=`string`||e.url.length===0)continue;let n=isObject(e.variables)?substituteServerVariables(e.url,e.variables):e.url;if(n.startsWith(`http://`)||n.startsWith(`https://`))return n;if(typeof t==`string`&&URL.canParse(t))try{return new URL(n,t).toString()}catch{}}}function extractSwaggerBaseUrl(e,t){let n=typeof e.basePath==`string`?e.basePath:``,r=typeof e.host==`string`&&e.host.length>0?e.host:``,i=typeof t==`string`&&URL.canParse(t)?new URL(t):void 0,a=extractSwaggerScheme(e)??i?.protocol.replace(/:$/,``)??`https`;if(r.length>0)return`${a}://${r}${normalizeBasePath(n)}`;if(i!==void 0){let e=new URL(normalizeBasePath(n)||`/`,i.origin).toString();return e.endsWith(`/`)&&normalizeBasePath(n).length===0?e.slice(0,-1):e}}function extractSwaggerScheme(e){let t=e.schemes;if(isArray(t)){for(let e of t)if(e===`https`||e===`http`)return e}}function normalizeBasePath(e){let t=e.trim();return t.length===0||t===`/`?``:t.startsWith(`/`)?t:`/${t}`}function substituteServerVariables(e,t){return e.replace(/\{([^}]+)\}/g,(e,n)=>{let r=t[n];return isObject(r)&&typeof r.default==`string`?r.default:e})}export{extractServerUrl,parseSpecDocument};
@@ -33,6 +33,8 @@ export declare function createAuthorizationExecution(options?: {
33
33
  readonly completeAuthorization?: typeof completeScopedAuthorization;
34
34
  }): {
35
35
  complete: (scoped: ScopedAuthorization) => Promise<void>;
36
+ /** Whether this execution completed a sign-in for `scoped`. */
37
+ isJustAuthorized(scoped: ScopedAuthorization): boolean;
36
38
  getToken(scoped: ScopedAuthorization): Promise<TokenResult>;
37
39
  requireAuth: (scoped: ScopedAuthorization, cause?: unknown) => never;
38
40
  handleError(error: unknown, scoped?: ScopedAuthorization): Promise<AuthorizationSignal>;
@@ -1 +1 @@
1
- import{contextStorage,loadContext}from"#context/container.js";import{AuthKey}from"#context/keys.js";import{consumeAuthorizationResult,createAuthorizationAttempt,requestAuthorization}from"#harness/authorization.js";import{ConnectionAuthorizationFailedError,ConnectionAuthorizationRequiredError,isConnectionAuthorizationRequiredError}from"#connections/errors.js";import{supportsInteractiveAuthorization}from"#shared/connection-types.js";import{isAsyncIterable}from"#shared/async-iterable.js";import{evictCachedToken,readCachedToken,writeCachedToken}from"#runtime/connections/authorization-tokens.js";import{principalKey,resolveConnectionPrincipal,resolveConnectionPrincipalFromAuth}from"#runtime/connections/principal.js";const LOCAL_HTTP_VERCEL_CONNECT_HOSTNAMES=new Set([`127.0.0.1`,`[::1]`]);function createAuthorizationExecution(e={}){let t=new Set;async function complete(n){let r=n.instanceId??n.scope;!t.has(r)&&await(e.completeAuthorization??completeScopedAuthorization)(n)&&t.add(r)}function requireAuth(e,n){throw new ScopedAuthorizationRequiredError(e,t.has(e.instanceId??e.scope),n)}return{complete,async getToken(e){await complete(e);try{return await resolveScopedToken(e)}catch(t){if(!isConnectionAuthorizationRequiredError(t))throw t;return requireAuth(e,t)}},requireAuth,async handleError(e,n){return n!==void 0&&isConnectionAuthorizationRequiredError(e)?await handleAuthorizationError(new ScopedAuthorizationRequiredError(n,t.has(n.instanceId??n.scope),e),{evictToken:!1}):await handleAuthorizationError(e)},run:executeWithAuthorization}}var ScopedAuthorizationRequiredError=class extends Error{scoped;justAuthorized;constructor(e,t,n){super(`Authorization required.`,{cause:n}),this.name=`ScopedAuthorizationRequiredError`,this.scoped=e,this.justAuthorized=t}};function isScopedAuthorizationRequiredError(e){return e instanceof Error&&e.name===`ScopedAuthorizationRequiredError`}async function handleAuthorizationError(e,t={evictToken:!0}){if(!isScopedAuthorizationRequiredError(e))throw e;let{scoped:n}=e;if(e.justAuthorized)throw new ConnectionAuthorizationFailedError(n.scope,{message:`Authorization for "${n.scope}" failed: the service rejected the token immediately after authorization.`,reason:`token_rejected_after_authorization`,retryable:!1});t.evictToken&&await evictScopedToken(n);let r=await startScopedAuthorization(n);if(r!==void 0)return r;throw supportsInteractiveAuthorization(n.authorization)?new ConnectionAuthorizationFailedError(n.scope,{message:`Authorization for "${n.scope}" requires sign-in, but no authorization callback URL could be minted for this run (missing session context).`,reason:`authorization_callback_unavailable`,retryable:!1}):e.cause??new ConnectionAuthorizationRequiredError(n.scope)}function executeWithAuthorization(e){try{let t=e();return isAsyncIterable(t)?handleIterable(t):Promise.resolve(t).catch(handleAuthorizationError)}catch(e){return handleAuthorizationError(e)}}async function*handleIterable(e){try{for await(let t of e)yield t}catch(e){yield await handleAuthorizationError(e)}}async function resolveScopedToken(e){let{scope:t,authorization:n,connection:r}=e,i=e.instanceId??t,a=contextStorage.getStore(),o=resolveScopedPrincipal(e,a);if(a===void 0)return await n.getToken({connection:r,principal:o});let s=principalKey(o),c=readCachedToken(a,i,s);if(c!==void 0)return c;let l=await n.getToken({connection:r,principal:o});return writeCachedToken(a,i,s,l),l}async function evictScopedToken(e){let{scope:t,authorization:n,connection:r}=e,i=e.instanceId??t,a=contextStorage.getStore();if(a===void 0)return;let o;try{o=resolveScopedPrincipal(e,a),evictCachedToken(a,i,principalKey(o))}catch{return}try{await n.evict?.({connection:r,principal:o})}catch{}}async function completeScopedAuthorization(e){let{scope:t,authorization:n,connection:r}=e;if(!supportsInteractiveAuthorization(n))return!1;let i=consumeAuthorizationResult(t,e.instanceId);if(i===void 0)return!1;let a=n,o=loadContext(),s=i.principal??resolveScopedPrincipal(e,o),c=await a.completeAuthorization({callbackUrl:i.hookUrl,connection:r,principal:s,resume:i.resume,callback:i.callback});return writeCachedToken(o,e.instanceId??t,principalKey(s),c),!0}async function startScopedAuthorization(e){let{scope:t,authorization:n,connection:r}=e;if(!supportsInteractiveAuthorization(n))return;let i=createAuthorizationAttempt(t);if(i===void 0)return;let a=n,o=resolveScopedPrincipal(e),s=(e.boundResponder??contextStorage.getStore()?.get(AuthKey))?.principalId,c=resolveAuthorizationCallbackUrl({authorization:n,callbackUrl:i.hookUrl}),{challenge:l,resume:u}=await a.startAuthorization({callbackUrl:c,connection:r,principal:o});return requestAuthorization([{attemptId:i.attemptId,challenge:stampChallengeDisplayName(l,n),hookUrl:c,instanceId:e.instanceId,name:t,principal:o,principalId:s,resume:u}])}function resolveScopedPrincipal(e,t){return e.boundResponder===void 0?resolveConnectionPrincipal(e.scope,e.authorization,t):resolveConnectionPrincipalFromAuth(e.scope,e.authorization,e.boundResponder,t)}function resolveAuthorizationCallbackUrl(e){if(e.authorization.vercelConnect===void 0)return e.callbackUrl;let t;try{t=new URL(e.callbackUrl)}catch{return e.callbackUrl}return t.protocol!==`http:`||!LOCAL_HTTP_VERCEL_CONNECT_HOSTNAMES.has(t.hostname)?e.callbackUrl:(t.hostname=`localhost`,t.toString())}function stampChallengeDisplayName(e,t){let n=t.displayName??e.displayName;return n===e.displayName?e:{...e,displayName:n}}export{completeScopedAuthorization,createAuthorizationExecution,evictScopedToken,handleAuthorizationError,resolveAuthorizationCallbackUrl,resolveScopedToken,stampChallengeDisplayName};
1
+ import{contextStorage,loadContext}from"#context/container.js";import{AuthKey}from"#context/keys.js";import{consumeAuthorizationResult,createAuthorizationAttempt,requestAuthorization}from"#harness/authorization.js";import{ConnectionAuthorizationFailedError,ConnectionAuthorizationRequiredError,isConnectionAuthorizationRequiredError}from"#connections/errors.js";import{supportsInteractiveAuthorization}from"#shared/connection-types.js";import{isAsyncIterable}from"#shared/async-iterable.js";import{evictCachedToken,readCachedToken,writeCachedToken}from"#runtime/connections/authorization-tokens.js";import{principalKey,resolveConnectionPrincipal,resolveConnectionPrincipalFromAuth}from"#runtime/connections/principal.js";const LOCAL_HTTP_VERCEL_CONNECT_HOSTNAMES=new Set([`127.0.0.1`,`[::1]`]);function createAuthorizationExecution(e={}){let t=new Set;async function complete(n){let r=n.instanceId??n.scope;!t.has(r)&&await(e.completeAuthorization??completeScopedAuthorization)(n)&&t.add(r)}function requireAuth(e,n){throw new ScopedAuthorizationRequiredError(e,t.has(e.instanceId??e.scope),n)}return{complete,isJustAuthorized(e){return t.has(e.instanceId??e.scope)},async getToken(e){await complete(e);try{return await resolveScopedToken(e)}catch(t){if(!isConnectionAuthorizationRequiredError(t))throw t;return requireAuth(e,t)}},requireAuth,async handleError(e,n){return n!==void 0&&isConnectionAuthorizationRequiredError(e)?await handleAuthorizationError(new ScopedAuthorizationRequiredError(n,t.has(n.instanceId??n.scope),e),{evictToken:!1}):await handleAuthorizationError(e)},run:executeWithAuthorization}}var ScopedAuthorizationRequiredError=class extends Error{scoped;justAuthorized;constructor(e,t,n){super(`Authorization required.`,{cause:n}),this.name=`ScopedAuthorizationRequiredError`,this.scoped=e,this.justAuthorized=t}};function isScopedAuthorizationRequiredError(e){return e instanceof Error&&e.name===`ScopedAuthorizationRequiredError`}async function handleAuthorizationError(e,t={evictToken:!0}){if(!isScopedAuthorizationRequiredError(e))throw e;let{scoped:n}=e;if(e.justAuthorized)throw new ConnectionAuthorizationFailedError(n.scope,{message:`Authorization for "${n.scope}" failed: the service rejected the token immediately after authorization.`,reason:`token_rejected_after_authorization`,retryable:!1});t.evictToken&&await evictScopedToken(n);let r=await startScopedAuthorization(n);if(r!==void 0)return r;throw supportsInteractiveAuthorization(n.authorization)?new ConnectionAuthorizationFailedError(n.scope,{message:`Authorization for "${n.scope}" requires sign-in, but no authorization callback URL could be minted for this run (missing session context).`,reason:`authorization_callback_unavailable`,retryable:!1}):e.cause??new ConnectionAuthorizationRequiredError(n.scope)}function executeWithAuthorization(e){try{let t=e();return isAsyncIterable(t)?handleIterable(t):Promise.resolve(t).catch(handleAuthorizationError)}catch(e){return handleAuthorizationError(e)}}async function*handleIterable(e){try{for await(let t of e)yield t}catch(e){yield await handleAuthorizationError(e)}}async function resolveScopedToken(e){let{scope:t,authorization:n,connection:r}=e,i=e.instanceId??t,a=contextStorage.getStore(),o=resolveScopedPrincipal(e,a);if(a===void 0)return await n.getToken({connection:r,principal:o});let s=principalKey(o),c=readCachedToken(a,i,s);if(c!==void 0)return c;let l=await n.getToken({connection:r,principal:o});return writeCachedToken(a,i,s,l),l}async function evictScopedToken(e){let{scope:t,authorization:n,connection:r}=e,i=e.instanceId??t,a=contextStorage.getStore();if(a===void 0)return;let o;try{o=resolveScopedPrincipal(e,a),evictCachedToken(a,i,principalKey(o))}catch{return}try{await n.evict?.({connection:r,principal:o})}catch{}}async function completeScopedAuthorization(e){let{scope:t,authorization:n,connection:r}=e;if(!supportsInteractiveAuthorization(n))return!1;let i=consumeAuthorizationResult(t,e.instanceId);if(i===void 0)return!1;let a=n,o=loadContext(),s=i.principal??resolveScopedPrincipal(e,o),c=await a.completeAuthorization({callbackUrl:i.hookUrl,connection:r,principal:s,resume:i.resume,callback:i.callback});return writeCachedToken(o,e.instanceId??t,principalKey(s),c),!0}async function startScopedAuthorization(e){let{scope:t,authorization:n,connection:r}=e;if(!supportsInteractiveAuthorization(n))return;let i=createAuthorizationAttempt(t);if(i===void 0)return;let a=n,o=resolveScopedPrincipal(e),s=e.boundResponder??contextStorage.getStore()?.get(AuthKey)??void 0,c=resolveAuthorizationCallbackUrl({authorization:n,callbackUrl:i.hookUrl}),{challenge:l,resume:u}=await a.startAuthorization({callbackUrl:c,connection:r,principal:o});return requestAuthorization([{attemptId:i.attemptId,challenge:stampChallengeDisplayName(l,n),grant:n.vercelConnect?.connector,hookUrl:c,instanceId:e.instanceId,name:t,principal:o,principalId:s?.principalId,requester:s,resume:u}])}function resolveScopedPrincipal(e,t){return e.boundResponder===void 0?resolveConnectionPrincipal(e.scope,e.authorization,t):resolveConnectionPrincipalFromAuth(e.scope,e.authorization,e.boundResponder,t)}function resolveAuthorizationCallbackUrl(e){if(e.authorization.vercelConnect===void 0)return e.callbackUrl;let t;try{t=new URL(e.callbackUrl)}catch{return e.callbackUrl}return t.protocol!==`http:`||!LOCAL_HTTP_VERCEL_CONNECT_HOSTNAMES.has(t.hostname)?e.callbackUrl:(t.hostname=`localhost`,t.toString())}function stampChallengeDisplayName(e,t){let n=t.displayName??e.displayName;return n===e.displayName?e:{...e,displayName:n}}export{completeScopedAuthorization,createAuthorizationExecution,evictScopedToken,handleAuthorizationError,resolveAuthorizationCallbackUrl,resolveScopedToken,stampChallengeDisplayName};
@@ -1 +1 @@
1
- import{detectDeployment,isProjectResolved,mergeProjectResolution,projectResolutionFromDeployResult,projectResolutionFromDeployment}from"../project-resolution.js";import{hasVercelProject,requireProjectPath}from"../state.js";import{syncHostFrameworkPreset}from"../vercel-project-framework.js";import{detectPackageManager}from"#setup/package-manager.js";import{runVercel}from"#setup/primitives/run-vercel.js";import{HumanActionRequiredError}from"#setup/human-action.js";import{createPromptCommandOutput,withPhase}from"#setup/cli/index.js";import{packageManagerInstallSucceeded,runPackageManagerInstall}from"#setup/primitives/pm/run.js";const VERCEL_DEPLOY_ENV={VERCEL_USE_EXPERIMENTAL_FRAMEWORKS:`1`};function deployProject(e){let t=e.deps??{runVercel,detectPackageManager,runPackageManagerInstall,detectDeployment,syncHostFrameworkPreset};return{id:`deploy-project`,shouldRun(t){return e.skip||!t.deploymentPending?!1:hasVercelProject(t)||e.ensureLinkedProject===`interactive-vercel-link`},async gather(){return{headless:e.headless??!1}},async perform({state:n,input:r,signal:i}){let a=requireProjectPath(n),{log:o}=e.prompter,s=createPromptCommandOutput(o),c=n.project;if(!isProjectResolved(c)){if(r.headless)throw new HumanActionRequiredError({kind:`vercel-link`,command:`vercel link`,reason:`Deployment needs this directory linked to a Vercel project.`});if(o.message(`Linking this directory to a Vercel project before deployment...`),!await t.runVercel([`link`],{cwd:a,signal:i}))throw i?.throwIfAborted(),Error(`Vercel project linking failed. Deployment did not start.`);if(c=mergeProjectResolution(c,projectResolutionFromDeployment(await t.detectDeployment(a,{signal:i}))),!isProjectResolved(c))throw Error(`Vercel project linking failed. Deployment did not start.`)}if(await t.syncHostFrameworkPreset(e.prompter,a,s,i?{signal:i}:{}),!n.deploymentDependenciesInstalled){let e=await t.detectPackageManager(a),n=await withPhase(o,`Installing project dependencies before deployment (${e.kind} install)...`,()=>t.runPackageManagerInstall(e.kind,a,{onOutput:s,signal:i}));if(!packageManagerInstallSucceeded(n))throw i?.throwIfAborted(),Error(`Dependency installation failed. Deployment did not start.`)}let l=[`deploy`,`--prod`,`--yes`,...r.headless?[`--non-interactive`]:[]],u=await withPhase(o,`Deploying the agent to Vercel production...`,()=>t.runVercel(l,{cwd:a,extraEnv:VERCEL_DEPLOY_ENV,nonInteractive:r.headless,onOutput:s,signal:i}));if(i?.throwIfAborted(),!u)throw o.error("`vercel deploy --prod` failed. The deploy output above shows the cause; fix it, then retry."),Error(`Deployment failed after channel setup.`);let d=await withPhase(o,`Pulling Vercel environment variables into .env.local...`,()=>t.runVercel([`env`,`pull`,`--yes`],{cwd:a,nonInteractive:r.headless,onOutput:s,signal:i}));i?.throwIfAborted(),d||o.warning(`Deployment succeeded, but pulling Vercel environment variables did not complete.`);let f=await t.detectDeployment(a,{signal:i}),p=f.state===`deployed`?f.productionUrl:void 0;return p===void 0?o.warning(`Deployment succeeded, but eve could not verify its production URL.`):o.info(`Production URL: ${p}`),{project:projectResolutionFromDeployResult(c,{deployed:!0,productionUrl:p}),deploymentPending:!1,deploymentDependenciesInstalled:!0}},apply(e,t){return{...e,project:t.project,deploymentPending:t.deploymentPending,deploymentDependenciesInstalled:t.deploymentDependenciesInstalled}}}}export{deployProject};
1
+ import{detectDeployment,isProjectResolved,mergeProjectResolution,projectResolutionFromDeployResult,projectResolutionFromDeployment}from"../project-resolution.js";import{hasVercelProject,requireProjectPath}from"../state.js";import{syncHostFrameworkPreset}from"../vercel-project-framework.js";import{detectPackageManager}from"#setup/package-manager.js";import{runVercel}from"#setup/primitives/run-vercel.js";import{HumanActionRequiredError}from"#setup/human-action.js";import{createPromptCommandOutput,withPhase}from"#setup/cli/index.js";import{packageManagerInstallSucceeded,runPackageManagerInstall}from"#setup/primitives/pm/run.js";const VERCEL_DEPLOY_ENV={VERCEL_USE_EXPERIMENTAL_FRAMEWORKS:`1`};function deployProject(e){let t=e.deps??{runVercel,detectPackageManager,runPackageManagerInstall,detectDeployment,syncHostFrameworkPreset};return{id:`deploy-project`,shouldRun(t){return e.skip||!t.deploymentPending?!1:hasVercelProject(t)||e.ensureLinkedProject===`interactive-vercel-link`},async gather(){return{headless:e.headless??!1}},async perform({state:n,input:r,signal:i}){let a=requireProjectPath(n),{log:o}=e.prompter,s=createPromptCommandOutput(o),c=n.project;if(!isProjectResolved(c)){if(r.headless)throw new HumanActionRequiredError({kind:`vercel-link`,command:`vercel link`,reason:`Deployment needs this directory linked to a Vercel project.`});if(o.message(`Linking this directory to a Vercel project before deployment...`),!await t.runVercel([`link`],{cwd:a,signal:i}))throw i?.throwIfAborted(),Error(`Vercel project linking failed. Deployment did not start.`);if(c=mergeProjectResolution(c,projectResolutionFromDeployment(await t.detectDeployment(a,{signal:i}))),!isProjectResolved(c))throw Error(`Vercel project linking failed. Deployment did not start.`)}if(await t.syncHostFrameworkPreset(e.prompter,a,s,i?{signal:i}:{}),!n.deploymentDependenciesInstalled){let e=await t.detectPackageManager(a),n=await withPhase(o,`Installing project dependencies before deployment (${e.kind} install)...`,()=>t.runPackageManagerInstall(e.kind,a,{onOutput:s,signal:i}));if(!packageManagerInstallSucceeded(n))throw i?.throwIfAborted(),Error(`Dependency installation failed. Deployment did not start.`)}let l=[`deploy`,`--prod`,`--yes`,`--logs`,...r.headless?[`--non-interactive`]:[]],u=await withPhase(o,`Deploying the agent to Vercel production...`,()=>t.runVercel(l,{cwd:a,extraEnv:VERCEL_DEPLOY_ENV,nonInteractive:r.headless,onOutput:s,signal:i}));if(i?.throwIfAborted(),!u)throw o.error("`vercel deploy --prod` failed. Check the build logs above for the first error, then retry. To retrieve the logs again, run `vercel inspect <deployment-url> --logs` from this project."),Error("Deployment failed. Check the build logs above, or run `vercel inspect <deployment-url> --logs` from this project.");let d=await withPhase(o,`Pulling Vercel environment variables into .env.local...`,()=>t.runVercel([`env`,`pull`,`--yes`],{cwd:a,nonInteractive:r.headless,onOutput:s,signal:i}));i?.throwIfAborted(),d||o.warning(`Deployment succeeded, but pulling Vercel environment variables did not complete.`);let f=await t.detectDeployment(a,{signal:i}),p=f.state===`deployed`?f.productionUrl:void 0;return p===void 0?o.warning(`Deployment succeeded, but eve could not verify its production URL.`):o.info(`Production URL: ${p}`),{project:projectResolutionFromDeployResult(c,{deployed:!0,productionUrl:p}),deploymentPending:!1,deploymentDependenciesInstalled:!0}},apply(e,t){return{...e,project:t.project,deploymentPending:t.deploymentPending,deploymentDependenciesInstalled:t.deploymentDependenciesInstalled}}}}export{deployProject};