eve 0.33.3 → 0.35.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (414) hide show
  1. package/CHANGELOG.md +40 -0
  2. package/README.md +3 -3
  3. package/dist/src/channel/channel-address.d.ts +3 -6
  4. package/dist/src/channel/channel-address.js +1 -1
  5. package/dist/src/channel/channel-operations.d.ts +2 -3
  6. package/dist/src/channel/delivery-metadata.d.ts +9 -0
  7. package/dist/src/channel/delivery-metadata.js +1 -0
  8. package/dist/src/channel/routes.d.ts +1 -0
  9. package/dist/src/channel/session.d.ts +3 -4
  10. package/dist/src/channel/session.js +1 -1
  11. package/dist/src/channel/types.d.ts +20 -3
  12. package/dist/src/chunks/{use-eve-agent-B-Hky2f4.js → use-eve-agent-COmP-H8R.js} +39 -3
  13. package/dist/src/chunks/{use-eve-agent-3oBnxzhV.js → use-eve-agent-CnppTEFk.js} +39 -3
  14. package/dist/src/cli/commands/info.js +1 -1
  15. package/dist/src/cli/commands/trace-detail.d.ts +3 -2
  16. package/dist/src/cli/commands/trace-detail.js +1 -1
  17. package/dist/src/cli/dev/tui/traces/trace-conversation.d.ts +4 -6
  18. package/dist/src/cli/dev/tui/traces/trace-conversation.js +1 -2
  19. package/dist/src/client/agent-info-schema.d.ts +12 -4
  20. package/dist/src/client/agent-info-schema.js +1 -1
  21. package/dist/src/client/index.d.ts +1 -1
  22. package/dist/src/client/message-reducer.js +1 -1
  23. package/dist/src/compiled/.vendor-stamp.json +4 -4
  24. package/dist/src/compiled/@chat-adapter/slack/index.js +1 -1
  25. package/dist/src/compiled/@opentelemetry/api/index.d.ts +32 -3
  26. package/dist/src/compiled/@vercel/otel/index.d.ts +45 -2
  27. package/dist/src/compiled/@workflow/core/index.js +1 -1
  28. package/dist/src/compiled/@workflow/core/runtime.js +3 -3
  29. package/dist/src/compiled/@workflow/core/workflow.js +1 -1
  30. package/dist/src/compiled/@workflow/world/env-config.d.ts +1 -0
  31. package/dist/src/compiled/@workflow/world/events.d.ts +92 -35
  32. package/dist/src/compiled/@workflow/world/index.d.ts +3 -2
  33. package/dist/src/compiled/@workflow/world/interfaces.d.ts +25 -23
  34. package/dist/src/compiled/@workflow/world/queue.d.ts +4 -0
  35. package/dist/src/compiled/@workflow/world/runs.d.ts +4 -0
  36. package/dist/src/compiled/@workflow/world/slot-identity.d.ts +53 -0
  37. package/dist/src/compiled/@workflow/world/spec-version.d.ts +36 -1
  38. package/dist/src/compiled/@workflow/world/steps.d.ts +4 -0
  39. package/dist/src/compiled/@workflow/world/ulid.d.ts +6 -0
  40. package/dist/src/compiled/@workflow/world-local/index.js +4 -4
  41. package/dist/src/compiled/@workflow/world-vercel/index.js +13 -17
  42. package/dist/src/compiled/_chunks/workflow/{attribute-changes-6OqdYdi4.js → attribute-changes-BoH7JsWp.js} +3 -3
  43. package/dist/src/compiled/_chunks/workflow/dist-DlFv0aHY.js +40 -0
  44. package/dist/src/compiled/_chunks/workflow/env-config-DxamfI7T.js +1 -0
  45. package/dist/src/compiled/_chunks/workflow/frames-CTpeJYEQ.js +3 -0
  46. package/dist/src/compiled/_chunks/workflow/{functions-CXb61C6h.js → functions-CeeNvKsq.js} +1 -1
  47. package/dist/src/compiled/_chunks/workflow/resume-hook-BPQHjeY5.js +1 -0
  48. package/dist/src/compiled/_chunks/workflow/run-DQ5dOyjm.js +1 -0
  49. package/dist/src/compiled/_chunks/workflow/run-id-BdE0MZz9.js +1 -0
  50. package/dist/src/compiled/_chunks/workflow/sleep-CzdoBiqy.js +1 -0
  51. package/dist/src/compiled/_chunks/workflow/spec-version-DBUVfF_R.js +1 -0
  52. package/dist/src/compiled/_chunks/workflow/undici-CUIybhQ2.js +95 -0
  53. package/dist/src/compiled/_chunks/workflow/wait-until-DK2lnH6U.js +15 -0
  54. package/dist/src/compiled/_chunks/workflow/{wrapper-CDq65xJV.js → wrapper-CMGju7QA.js} +1 -1
  55. package/dist/src/compiled/_chunks/workflow/ws-transport-Csi6Cydc.js +1 -0
  56. package/dist/src/compiler/extension-compatibility.d.ts +14 -14
  57. package/dist/src/compiler/extension-compatibility.js +1 -1
  58. package/dist/src/compiler/manifest.d.ts +8 -8
  59. package/dist/src/compiler/manifest.js +1 -1
  60. package/dist/src/compiler/normalize-agent-config.js +1 -1
  61. package/dist/src/compiler/normalize-extension.d.ts +3 -3
  62. package/dist/src/compiler/normalize-extension.js +1 -1
  63. package/dist/src/compiler/normalize-instructions.d.ts +1 -1
  64. package/dist/src/compiler/normalize-instructions.js +1 -1
  65. package/dist/src/compiler/normalize-manifest.js +1 -3
  66. package/dist/src/context/build-dynamic-tools.d.ts +7 -0
  67. package/dist/src/context/build-dynamic-tools.js +1 -1
  68. package/dist/src/context/dynamic-instruction-lifecycle.d.ts +5 -1
  69. package/dist/src/context/dynamic-instruction-lifecycle.js +1 -1
  70. package/dist/src/context/dynamic-tool-lifecycle.d.ts +7 -0
  71. package/dist/src/context/dynamic-tool-lifecycle.js +1 -1
  72. package/dist/src/context/keys.d.ts +18 -2
  73. package/dist/src/context/keys.js +1 -1
  74. package/dist/src/discover/filesystem.d.ts +1 -1
  75. package/dist/src/discover/filesystem.js +1 -1
  76. package/dist/src/discover/manifest.d.ts +1 -1
  77. package/dist/src/discover/manifest.js +1 -1
  78. package/dist/src/evals/cli/eval.js +2 -2
  79. package/dist/src/evals/index.d.ts +2 -2
  80. package/dist/src/evals/reporters/index.d.ts +1 -1
  81. package/dist/src/evals/runner/artifacts.js +1 -1
  82. package/dist/src/evals/runner/derive-run-facts.js +1 -1
  83. package/dist/src/evals/runner/execute-eval.d.ts +5 -0
  84. package/dist/src/evals/runner/execute-eval.js +1 -1
  85. package/dist/src/evals/runner/execute-task.d.ts +3 -0
  86. package/dist/src/evals/runner/execute-task.js +1 -1
  87. package/dist/src/evals/runner/reporters/braintrust.js +1 -1
  88. package/dist/src/evals/runner/reporters/types.d.ts +28 -2
  89. package/dist/src/evals/runner/run-evals.js +1 -1
  90. package/dist/src/evals/session.d.ts +11 -2
  91. package/dist/src/evals/session.js +1 -1
  92. package/dist/src/evals/target.js +1 -1
  93. package/dist/src/evals/types.d.ts +10 -1
  94. package/dist/src/execution/dispatch-runtime-actions-step.d.ts +1 -5
  95. package/dist/src/execution/dispatch-runtime-actions-step.js +1 -1
  96. package/dist/src/execution/dispatch-turn-step.d.ts +5 -0
  97. package/dist/src/execution/dispatch-turn-step.js +1 -0
  98. package/dist/src/execution/durable-session-migrations/turn-workflow.d.ts +1 -0
  99. package/dist/src/execution/node-step.js +1 -1
  100. package/dist/src/execution/parked-delivery-wait.d.ts +1 -1
  101. package/dist/src/execution/parked-delivery-wait.js +1 -1
  102. package/dist/src/execution/remote-agent-dispatch.d.ts +2 -1
  103. package/dist/src/execution/remote-agent-dispatch.js +1 -1
  104. package/dist/src/execution/route-child-delivery.d.ts +3 -4
  105. package/dist/src/execution/route-child-delivery.js +1 -1
  106. package/dist/src/execution/route-proxied-deliver-step.d.ts +34 -0
  107. package/dist/src/execution/route-proxied-deliver-step.js +1 -0
  108. package/dist/src/execution/runtime-context.js +1 -1
  109. package/dist/src/execution/session-command-inbox.d.ts +2 -2
  110. package/dist/src/execution/session-command-wire.js +1 -1
  111. package/dist/src/execution/session.js +1 -1
  112. package/dist/src/execution/settle-cancelled-turn-step.js +1 -1
  113. package/dist/src/execution/subagent-adapter.js +1 -1
  114. package/dist/src/execution/subagent-event-proxy-step.js +1 -1
  115. package/dist/src/execution/tool-auth.d.ts +9 -0
  116. package/dist/src/execution/tool-auth.js +1 -1
  117. package/dist/src/execution/turn-control-receiver.js +1 -1
  118. package/dist/src/execution/turn-dispatch.js +1 -1
  119. package/dist/src/execution/turn-workflow.js +1 -1
  120. package/dist/src/execution/workflow-entry.js +1 -1
  121. package/dist/src/execution/workflow-runtime.js +1 -1
  122. package/dist/src/execution/workflow-steps.d.ts +1 -27
  123. package/dist/src/execution/workflow-steps.js +1 -1
  124. package/dist/src/execution/workflow-trace-context.d.ts +11 -0
  125. package/dist/src/execution/workflow-trace-context.js +1 -0
  126. package/dist/src/harness/ai-sdk-hook-bridge.d.ts +1 -1
  127. package/dist/src/harness/ai-sdk-hook-bridge.js +1 -1
  128. package/dist/src/harness/ai-sdk-telemetry.d.ts +19 -0
  129. package/dist/src/harness/ai-sdk-telemetry.js +1 -0
  130. package/dist/src/harness/approval-candidates.d.ts +109 -0
  131. package/dist/src/harness/approval-candidates.js +1 -0
  132. package/dist/src/harness/approval-delivery-coordinator.d.ts +39 -0
  133. package/dist/src/harness/approval-delivery-coordinator.js +1 -0
  134. package/dist/src/harness/authorization.d.ts +1 -0
  135. package/dist/src/harness/authorization.js +1 -1
  136. package/dist/src/harness/channel-delivery-instrumentation.d.ts +25 -0
  137. package/dist/src/harness/channel-delivery-instrumentation.js +1 -0
  138. package/dist/src/harness/emission.d.ts +2 -2
  139. package/dist/src/harness/emission.js +1 -1
  140. package/dist/src/harness/execute-tool.d.ts +1 -0
  141. package/dist/src/harness/hitl/approval-input-requests.js +1 -1
  142. package/dist/src/harness/hitl/pending-input-resolution.d.ts +3 -0
  143. package/dist/src/harness/hitl/pending-input-resolution.js +1 -1
  144. package/dist/src/harness/hitl/question-input-requests.js +1 -1
  145. package/dist/src/harness/hitl/session-limit-input-requests.js +1 -1
  146. package/dist/src/harness/input-extraction.js +1 -1
  147. package/dist/src/harness/input-request-resolution.d.ts +22 -0
  148. package/dist/src/harness/input-request-resolution.js +1 -0
  149. package/dist/src/harness/input-requests.d.ts +1 -0
  150. package/dist/src/harness/input-requests.js +1 -1
  151. package/dist/src/harness/{instrumentation-config.d.ts → instrumentation/config.d.ts} +9 -4
  152. package/dist/src/harness/instrumentation/config.js +1 -0
  153. package/dist/src/harness/instrumentation/content.d.ts +5 -0
  154. package/dist/src/harness/instrumentation/content.js +1 -0
  155. package/dist/src/harness/instrumentation/dispatch.d.ts +2 -0
  156. package/dist/src/harness/instrumentation/dispatch.js +1 -0
  157. package/dist/src/harness/instrumentation/lifecycle.d.ts +491 -0
  158. package/dist/src/harness/instrumentation/lifecycle.js +1 -0
  159. package/dist/src/harness/{instrumentation-native-events.d.ts → instrumentation/native-events.d.ts} +10 -1
  160. package/dist/src/harness/instrumentation/native-events.js +1 -0
  161. package/dist/src/harness/instrumentation/providers.d.ts +50 -0
  162. package/dist/src/harness/instrumentation/providers.js +1 -0
  163. package/dist/src/harness/{instrumentation-runtime.d.ts → instrumentation/runtime.d.ts} +7 -2
  164. package/dist/src/harness/{instrumentation-runtime.js → instrumentation/runtime.js} +1 -1
  165. package/dist/src/harness/instrumentation/setup-context.d.ts +12 -0
  166. package/dist/src/harness/instrumentation/setup-context.js +1 -0
  167. package/dist/src/harness/instrumentation/state.d.ts +59 -0
  168. package/dist/src/harness/instrumentation/state.js +1 -0
  169. package/dist/src/harness/messages.d.ts +2 -1
  170. package/dist/src/harness/messages.js +1 -1
  171. package/dist/src/harness/parent-lineage.d.ts +1 -1
  172. package/dist/src/harness/pending-input-batches.d.ts +2 -0
  173. package/dist/src/harness/pending-input-batches.js +1 -1
  174. package/dist/src/harness/prepare-trace-context.d.ts +16 -0
  175. package/dist/src/harness/prepare-trace-context.js +1 -0
  176. package/dist/src/harness/runtime-action-settlement-state.d.ts +3 -0
  177. package/dist/src/harness/runtime-action-settlement-state.js +1 -0
  178. package/dist/src/harness/runtime-actions.js +1 -1
  179. package/dist/src/harness/stale-input-responses.js +1 -1
  180. package/dist/src/harness/tool-call-action.d.ts +9 -0
  181. package/dist/src/harness/tool-call-action.js +1 -0
  182. package/dist/src/harness/tool-loop.js +2 -2
  183. package/dist/src/harness/tools.js +1 -1
  184. package/dist/src/harness/types.d.ts +16 -2
  185. package/dist/src/internal/application/compiled-artifacts.d.ts +13 -4
  186. package/dist/src/internal/application/compiled-artifacts.js +5 -4
  187. package/dist/src/internal/application/dev-environment.d.ts +12 -0
  188. package/dist/src/internal/application/dev-environment.js +1 -1
  189. package/dist/src/internal/application/package.js +1 -1
  190. package/dist/src/internal/authored-definition/approval.d.ts +3 -0
  191. package/dist/src/internal/authored-definition/approval.js +1 -0
  192. package/dist/src/internal/authored-definition/connection.js +1 -1
  193. package/dist/src/internal/authored-definition/core.d.ts +3 -3
  194. package/dist/src/internal/authored-definition/core.js +1 -1
  195. package/dist/src/internal/authored-definition/schema-backed.js +1 -1
  196. package/dist/src/internal/authored-package-boundary.js +1 -1
  197. package/dist/src/internal/helpers/markdown.js +1 -1
  198. package/dist/src/internal/instrumentation-layout.d.ts +28 -0
  199. package/dist/src/internal/instrumentation-layout.js +1 -0
  200. package/dist/src/internal/instrumentation.d.ts +1 -1
  201. package/dist/src/internal/materialized-authored-modules.d.ts +13 -2
  202. package/dist/src/internal/materialized-authored-modules.js +1 -1
  203. package/dist/src/internal/nitro/host/build-vercel-agent-summary.js +1 -1
  204. package/dist/src/internal/nitro/host/create-application-nitro.js +1 -1
  205. package/dist/src/internal/nitro/host/dev-host-fingerprint.js +1 -1
  206. package/dist/src/internal/nitro/host/local-tracing-runtime-plugin.d.ts +5 -1
  207. package/dist/src/internal/nitro/host/local-tracing-runtime-plugin.js +1 -1
  208. package/dist/src/internal/nitro/routes/agent-info/build-agent-info-response-from-manifest.js +1 -1
  209. package/dist/src/internal/nitro/routes/agent-info/build-agent-info-response.d.ts +4 -3
  210. package/dist/src/internal/nitro/routes/agent-info/build-agent-info-response.js +1 -1
  211. package/dist/src/internal/nitro/routes/channel-dispatch.js +1 -1
  212. package/dist/src/internal/nitro/routes/channel-request-instrumentation.d.ts +2 -3
  213. package/dist/src/internal/nitro/routes/channel-request-instrumentation.js +1 -1
  214. package/dist/src/internal/vercel/project-link.d.ts +1 -1
  215. package/dist/src/internal/vercel/project-link.js +1 -1
  216. package/dist/src/internal/vercel-agent-summary.d.ts +10 -9
  217. package/dist/src/internal/vercel-agent-summary.js +1 -1
  218. package/dist/src/internal/workflow/development-world-client.js +1 -1
  219. package/dist/src/packages/eve-catalog/src/index.js +1 -1
  220. package/dist/src/protocol/message.d.ts +51 -2
  221. package/dist/src/protocol/message.js +2 -2
  222. package/dist/src/protocol/traceparent.d.ts +10 -0
  223. package/dist/src/protocol/traceparent.js +1 -0
  224. package/dist/src/public/channels/eve.js +1 -1
  225. package/dist/src/public/channels/github/auth.d.ts +30 -0
  226. package/dist/src/public/channels/github/auth.js +2 -2
  227. package/dist/src/public/channels/github/defaults.d.ts +4 -3
  228. package/dist/src/public/channels/github/defaults.js +5 -2
  229. package/dist/src/public/channels/github/dispatch.d.ts +3 -2
  230. package/dist/src/public/channels/github/dispatch.js +1 -1
  231. package/dist/src/public/channels/github/githubChannel.d.ts +10 -5
  232. package/dist/src/public/channels/github/githubChannel.js +1 -1
  233. package/dist/src/public/channels/github/index.d.ts +1 -1
  234. package/dist/src/public/channels/slack/defaults.js +3 -3
  235. package/dist/src/public/channels/slack/interactions.js +1 -1
  236. package/dist/src/public/channels/slack/slackChannel.d.ts +11 -3
  237. package/dist/src/public/channels/slack/slackChannel.js +1 -1
  238. package/dist/src/public/definitions/approval.d.ts +57 -16
  239. package/dist/src/public/definitions/approval.js +1 -1
  240. package/dist/src/public/definitions/channel.d.ts +2 -2
  241. package/dist/src/public/definitions/channel.js +1 -1
  242. package/dist/src/public/definitions/hook.d.ts +4 -2
  243. package/dist/src/public/definitions/instructions.d.ts +14 -4
  244. package/dist/src/public/definitions/instructions.js +1 -1
  245. package/dist/src/public/definitions/tool.d.ts +5 -8
  246. package/dist/src/public/instructions/index.d.ts +1 -2
  247. package/dist/src/public/instructions/index.js +1 -1
  248. package/dist/src/public/instrumentation/index.d.ts +36 -20
  249. package/dist/src/public/instrumentation/index.js +1 -1
  250. package/dist/src/public/instrumentation/otel.d.ts +32 -0
  251. package/dist/src/public/instrumentation/otel.js +1 -0
  252. package/dist/src/public/instrumentation/provider.d.ts +117 -0
  253. package/dist/src/public/instrumentation/provider.js +1 -0
  254. package/dist/src/public/tools/approval/approval-helpers.d.ts +4 -4
  255. package/dist/src/public/tools/index.d.ts +1 -1
  256. package/dist/src/runtime/actions/results.d.ts +3 -3
  257. package/dist/src/runtime/agent/bootstrap.d.ts +2 -0
  258. package/dist/src/runtime/agent/bootstrap.js +1 -1
  259. package/dist/src/runtime/attributes/emit.js +1 -1
  260. package/dist/src/runtime/connections/principal.d.ts +3 -0
  261. package/dist/src/runtime/connections/principal.js +1 -1
  262. package/dist/src/runtime/connections/scoped-authorization.d.ts +3 -5
  263. package/dist/src/runtime/connections/scoped-authorization.js +1 -1
  264. package/dist/src/runtime/connections/types.d.ts +5 -0
  265. package/dist/src/runtime/prompt/compose.d.ts +1 -1
  266. package/dist/src/runtime/prompt/compose.js +3 -1
  267. package/dist/src/runtime/resolve-agent.js +1 -1
  268. package/dist/src/runtime/resolve-tool.js +1 -1
  269. package/dist/src/runtime/types.d.ts +4 -3
  270. package/dist/src/setup/index.d.ts +1 -0
  271. package/dist/src/setup/index.js +1 -1
  272. package/dist/src/setup/project-resolution.d.ts +3 -3
  273. package/dist/src/setup/scaffold/create/project.js +1 -1
  274. package/dist/src/setup/scaffold/version-tokens.js +1 -1
  275. package/dist/src/setup/slack-connect-lifecycle.d.ts +0 -9
  276. package/dist/src/setup/slack-connect-lifecycle.js +1 -1
  277. package/dist/src/setup/slackbot.d.ts +2 -1
  278. package/dist/src/setup/slackbot.js +1 -1
  279. package/dist/src/setup/verified-remote-agent.d.ts +30 -0
  280. package/dist/src/setup/verified-remote-agent.js +1 -0
  281. package/dist/src/shared/agent-definition.d.ts +9 -0
  282. package/dist/src/shared/channel-definition.d.ts +3 -1
  283. package/dist/src/shared/dynamic-tool-definition.d.ts +3 -4
  284. package/dist/src/shared/instructions-definition.d.ts +15 -11
  285. package/dist/src/svelte/index.js +1 -1
  286. package/dist/src/svelte/use-eve-agent.js +1 -1
  287. package/dist/src/tracing/agent-action-instrumentation.d.ts +31 -0
  288. package/dist/src/tracing/agent-action-instrumentation.js +1 -0
  289. package/dist/src/tracing/agent-approval-instrumentation.d.ts +13 -0
  290. package/dist/src/tracing/agent-approval-instrumentation.js +1 -0
  291. package/dist/src/tracing/agent-channel-delivery-instrumentation.d.ts +13 -0
  292. package/dist/src/tracing/agent-channel-delivery-instrumentation.js +1 -0
  293. package/dist/src/tracing/agent-otel-content.d.ts +6 -0
  294. package/dist/src/tracing/agent-otel-content.js +2 -2
  295. package/dist/src/tracing/agent-otel-provider.d.ts +10 -8
  296. package/dist/src/tracing/agent-otel-provider.js +2 -2
  297. package/dist/src/tracing/agent-otel-session-context.d.ts +17 -0
  298. package/dist/src/tracing/agent-otel-session-context.js +1 -0
  299. package/dist/src/tracing/agent-otel-usage.d.ts +4 -0
  300. package/dist/src/tracing/agent-otel-usage.js +1 -0
  301. package/dist/src/tracing/agent-span-id-generator.d.ts +2 -0
  302. package/dist/src/tracing/agent-span-id-generator.js +1 -1
  303. package/dist/src/tracing/agent-tool-instrumentation.d.ts +28 -0
  304. package/dist/src/tracing/agent-tool-instrumentation.js +1 -0
  305. package/dist/src/tracing/agent-trace-context-store.d.ts +8 -1
  306. package/dist/src/tracing/agent-trace-context-store.js +1 -1
  307. package/dist/src/tracing/agent-trace-span-processor.d.ts +0 -1
  308. package/dist/src/tracing/agent-trace-span-processor.js +1 -1
  309. package/dist/src/tracing/agent-trace-state.d.ts +33 -3
  310. package/dist/src/tracing/agent-trace-state.js +1 -1
  311. package/dist/src/tracing/batch-span-processor.d.ts +20 -0
  312. package/dist/src/tracing/batch-span-processor.js +1 -0
  313. package/dist/src/tracing/content-attributes.d.ts +28 -0
  314. package/dist/src/tracing/content-attributes.js +1 -0
  315. package/dist/src/tracing/content-span-processor.d.ts +19 -0
  316. package/dist/src/tracing/content-span-processor.js +1 -0
  317. package/dist/src/tracing/install-instrumentation-runtime.d.ts +19 -0
  318. package/dist/src/tracing/install-instrumentation-runtime.js +1 -0
  319. package/dist/src/tracing/local-instrumentation-runtime.d.ts +1 -1
  320. package/dist/src/tracing/local-instrumentation-runtime.js +1 -1
  321. package/dist/src/tracing/local-traces.d.ts +56 -0
  322. package/dist/src/tracing/local-traces.js +1 -0
  323. package/dist/src/tracing/otel-declaration.d.ts +150 -0
  324. package/dist/src/tracing/otel-declaration.js +1 -0
  325. package/dist/src/tracing/otel-registration.d.ts +21 -0
  326. package/dist/src/tracing/otel-registration.js +1 -0
  327. package/dist/src/tracing/vercel-runtime-span-exporter.d.ts +5 -0
  328. package/dist/src/tracing/vercel-runtime-span-exporter.js +1 -0
  329. package/dist/src/vue/index.js +1 -1
  330. package/dist/src/vue/use-eve-agent.js +1 -1
  331. package/docs/README.md +18 -20
  332. package/docs/agent-config.md +5 -5
  333. package/docs/channels/eve.mdx +10 -56
  334. package/docs/channels/github.mdx +1 -1
  335. package/docs/channels/meta.json +1 -0
  336. package/docs/concepts/context-control.md +32 -56
  337. package/docs/concepts/default-harness.md +2 -2
  338. package/docs/concepts/execution-model-and-durability.mdx +4 -4
  339. package/docs/concepts/meta.json +3 -1
  340. package/docs/concepts/sessions-runs-and-streaming.md +22 -10
  341. package/docs/{guides → concepts}/state.md +3 -3
  342. package/docs/connections/mcp.mdx +6 -89
  343. package/docs/connections/meta.json +1 -0
  344. package/docs/connections/openapi.mdx +5 -69
  345. package/docs/connections/overview.mdx +29 -3
  346. package/docs/evals/meta.json +1 -0
  347. package/docs/evals/reporters.mdx +14 -4
  348. package/docs/extensions.md +1 -1
  349. package/docs/getting-started.mdx +175 -13
  350. package/docs/guides/auth-and-route-protection.md +3 -18
  351. package/docs/guides/client/meta.json +2 -1
  352. package/docs/guides/client/output-schema.mdx +2 -2
  353. package/docs/guides/client/overview.mdx +1 -1
  354. package/docs/guides/deployment/meta.json +1 -0
  355. package/docs/guides/deployment/overview.md +1 -1
  356. package/docs/guides/deployment/self-hosting.md +3 -3
  357. package/docs/guides/deployment/vercel.mdx +1 -1
  358. package/docs/guides/dev-tui.md +3 -13
  359. package/docs/guides/dynamic-capabilities.md +26 -4
  360. package/docs/guides/frontend/meta.json +2 -1
  361. package/docs/guides/frontend/nextjs.mdx +1 -10
  362. package/docs/guides/frontend/nuxt.mdx +1 -10
  363. package/docs/guides/frontend/overview.mdx +12 -3
  364. package/docs/guides/frontend/sveltekit.mdx +1 -10
  365. package/docs/guides/frontend/use-eve-agent-svelte.mdx +39 -126
  366. package/docs/guides/frontend/use-eve-agent-vue.mdx +40 -139
  367. package/docs/guides/instrumentation.md +37 -15
  368. package/docs/guides/meta.json +1 -5
  369. package/docs/guides/remote-agents.md +9 -9
  370. package/docs/guides/session-context.md +34 -103
  371. package/docs/install-integrations.mdx +1 -1
  372. package/docs/instructions.mdx +45 -12
  373. package/docs/meta.json +24 -13
  374. package/docs/patterns/dynamic-scheduling.md +1 -1
  375. package/docs/patterns/meta.json +1 -0
  376. package/docs/patterns/multi-tenant-approvals.md +1 -1
  377. package/docs/patterns/multi-tenant-auth.md +1 -1
  378. package/docs/patterns/multi-tenant-memory.md +4 -3
  379. package/docs/{guides → protocols}/acp.md +1 -1
  380. package/docs/protocols/meta.json +5 -0
  381. package/docs/reference/cli.md +34 -34
  382. package/docs/reference/meta.json +1 -1
  383. package/docs/reference/typescript-api.md +4 -2
  384. package/docs/{subagents.mdx → subagents/index.mdx} +2 -2
  385. package/docs/subagents/meta.json +5 -0
  386. package/docs/{guides/dynamic-workflows.md → subagents/workflow-tool.md} +6 -6
  387. package/docs/tools/human-in-the-loop.md +1 -1
  388. package/docs/tools/meta.json +1 -0
  389. package/docs/tools/overview.mdx +1 -1
  390. package/docs/tutorial/connect-a-warehouse.mdx +1 -1
  391. package/docs/tutorial/meta.json +1 -0
  392. package/docs/tutorial/remember-definitions.mdx +2 -2
  393. package/docs/tutorial/ship-it.mdx +2 -2
  394. package/package.json +10 -4
  395. package/dist/src/compiled/_chunks/workflow/dist-C8PhDW9B.js +0 -1
  396. package/dist/src/compiled/_chunks/workflow/functions-xMPAeWFr.js +0 -1
  397. package/dist/src/compiled/_chunks/workflow/node-Smb57EnG.js +0 -40
  398. package/dist/src/compiled/_chunks/workflow/resume-hook-BrduAuFX.js +0 -1
  399. package/dist/src/compiled/_chunks/workflow/run-CX7_sJnW.js +0 -1
  400. package/dist/src/compiled/_chunks/workflow/sleep-tsb2HjWK.js +0 -1
  401. package/dist/src/compiled/_chunks/workflow/undici-BNc_0O4m.js +0 -95
  402. package/dist/src/compiled/_chunks/workflow/wait-until-BYKVqrwc.js +0 -15
  403. package/dist/src/harness/instrumentation-config.js +0 -1
  404. package/dist/src/harness/instrumentation-lifecycle.d.ts +0 -171
  405. package/dist/src/harness/instrumentation-lifecycle.js +0 -1
  406. package/dist/src/harness/instrumentation-native-events.js +0 -1
  407. package/dist/src/harness/otel-integration.d.ts +0 -12
  408. package/dist/src/harness/otel-integration.js +0 -1
  409. package/docs/installation.mdx +0 -66
  410. package/docs/project-structure.mdx +0 -53
  411. package/docs/reference/project-layout.md +0 -123
  412. /package/dist/src/harness/{instrumentation-runtime-context.d.ts → instrumentation/runtime-context.d.ts} +0 -0
  413. /package/dist/src/harness/{instrumentation-runtime-context.js → instrumentation/runtime-context.js} +0 -0
  414. /package/docs/{guides → protocols}/ucp.mdx +0 -0
@@ -1,2 +1,2 @@
1
- import{createSign}from"node:crypto";import{isObject}from"#shared/guards.js";const installationTokenCache=new Map;async function resolveGitHubAppId(e){let t=e??process.env.GITHUB_APP_ID;if(t===void 0||t===``)throw Error(`githubChannel: GITHUB_APP_ID is required.`);let n=typeof t==`function`?await t():t;return String(n)}async function resolveGitHubPrivateKey(e){let t=e??process.env.GITHUB_APP_PRIVATE_KEY;if(!t)throw Error(`githubChannel: GITHUB_APP_PRIVATE_KEY is required.`);return normalizeGitHubPrivateKey(typeof t==`function`?await t():t)}async function resolveGitHubWebhookSecret(e){let t=e??process.env.GITHUB_WEBHOOK_SECRET;if(!t)throw Error(`githubChannel: GITHUB_WEBHOOK_SECRET is required.`);return typeof t==`function`?await t():t}function normalizeGitHubPrivateKey(e){return e.replace(/\\n/gu,`
2
- `)}async function createGitHubAppJwt(t){let n=await resolveGitHubAppId(t.appId),r=await resolveGitHubPrivateKey(t.privateKey),i=Math.floor((t.now?.getTime()??Date.now())/1e3),a={alg:`RS256`,typ:`JWT`},o={exp:i+600,iat:i-60,iss:n},s=`${base64UrlJson(a)}.${base64UrlJson(o)}`;return`${s}.${createSign(`RSA-SHA256`).update(s).sign(r,`base64url`)}`}async function resolveGitHubInstallationToken(e){let t=e.credentials?.installationToken;if(t!==void 0)return typeof t==`function`?await t():t;if(e.installationId===void 0)throw Error(`githubChannel: installationId is required for authenticated GitHub API calls.`);return createGitHubInstallationToken({api:e.api,appId:e.credentials?.appId,installationId:e.installationId,privateKey:e.credentials?.privateKey})}async function createGitHubInstallationToken(e){let r=await resolveGitHubAppId(e.appId),i=e.api?.apiBaseUrl??`https://api.github.com`,a=`${i}:${r}:${e.installationId}`,o=installationTokenCache.get(a);if(o!==void 0&&Date.now()<o.expiresAtMs-6e4)return o.token;let s=await createGitHubAppJwt({appId:r,privateKey:e.privateKey}),c=await(e.api?.fetch??fetch)(`${i}/app/installations/${e.installationId}/access_tokens`,{headers:{accept:`application/vnd.github+json`,authorization:`Bearer ${s}`,"x-github-api-version":`2022-11-28`},method:`POST`}),l=await parseJsonBody(c);if(!c.ok)throw Error(`githubChannel: create installation token failed with HTTP ${c.status}.`);if(!isObject(l)||typeof l.token!=`string`)throw Error(`githubChannel: installation token response did not include a token.`);let u=parseExpiryMs(l.expires_at);return installationTokenCache.set(a,{expiresAtMs:u,token:l.token}),l.token}function clearGitHubInstallationTokenCache(){installationTokenCache.clear()}function seedGitHubInstallationTokenForTests(e){let t=e.apiBaseUrl??`https://api.github.com`,r=e.appId??`test-app`;installationTokenCache.set(`${t}:${r}:${e.installationId}`,{expiresAtMs:Date.now()+3600*1e3,token:e.token})}function base64UrlJson(e){return Buffer.from(JSON.stringify(e)).toString(`base64url`)}async function parseJsonBody(e){let t=await e.text();if(!t)return null;try{return JSON.parse(t)}catch{return t}}function parseExpiryMs(e){if(typeof e==`string`){let t=Date.parse(e);if(Number.isFinite(t))return t}return Date.now()+3600*1e3}export{clearGitHubInstallationTokenCache,createGitHubAppJwt,createGitHubInstallationToken,normalizeGitHubPrivateKey,resolveGitHubAppId,resolveGitHubInstallationToken,resolveGitHubPrivateKey,resolveGitHubWebhookSecret,seedGitHubInstallationTokenForTests};
1
+ import{createSign}from"node:crypto";import{createLogger}from"#internal/logging.js";import{isObject}from"#shared/guards.js";const log=createLogger(`github.auth`),installationTokenCache=new Map;async function resolveGitHubAppId(e){let t=e??process.env.GITHUB_APP_ID;if(t===void 0||t===``)throw Error(`githubChannel: GITHUB_APP_ID is required.`);let n=typeof t==`function`?await t():t;return String(n)}async function resolveGitHubPrivateKey(e){let t=e??process.env.GITHUB_APP_PRIVATE_KEY;if(!t)throw Error(`githubChannel: GITHUB_APP_PRIVATE_KEY is required.`);return normalizeGitHubPrivateKey(typeof t==`function`?await t():t)}async function resolveGitHubWebhookSecret(e){let t=e??process.env.GITHUB_WEBHOOK_SECRET;if(!t)throw Error(`githubChannel: GITHUB_WEBHOOK_SECRET is required.`);return typeof t==`function`?await t():t}function createGitHubBotNameResolver(e){let t;return async()=>{if(t!==void 0)return t;let n=e.botName??e.credentials?.appSlug??process.env.GITHUB_APP_SLUG;if(n!==void 0){if(typeof n==`string`)return t=normalizeBotName(n),t;try{return t=normalizeBotName(await n()),t}catch(e){log.warn(`githubChannel: botName resolver failed; retrying on the next event`,{error:e});return}}}}function normalizeBotName(e){let t=e.trim();return t.length>0?t:void 0}function normalizeGitHubPrivateKey(e){return e.replace(/\\n/gu,`
2
+ `)}async function createGitHubAppJwt(t){let n=await resolveGitHubAppId(t.appId),r=await resolveGitHubPrivateKey(t.privateKey),i=Math.floor((t.now?.getTime()??Date.now())/1e3),a={alg:`RS256`,typ:`JWT`},o={exp:i+600,iat:i-60,iss:n},s=`${base64UrlJson(a)}.${base64UrlJson(o)}`;return`${s}.${createSign(`RSA-SHA256`).update(s).sign(r,`base64url`)}`}async function resolveGitHubInstallationToken(e){let t=e.credentials?.installationToken;if(t!==void 0)return typeof t==`function`?await t():t;if(e.installationId===void 0)throw Error(`githubChannel: installationId is required for authenticated GitHub API calls.`);return createGitHubInstallationToken({api:e.api,appId:e.credentials?.appId,installationId:e.installationId,privateKey:e.credentials?.privateKey})}async function createGitHubInstallationToken(e){let t=await resolveGitHubAppId(e.appId),r=e.api?.apiBaseUrl??`https://api.github.com`,a=`${r}:${t}:${e.installationId}`,o=installationTokenCache.get(a);if(o!==void 0&&Date.now()<o.expiresAtMs-6e4)return o.token;let s=await createGitHubAppJwt({appId:t,privateKey:e.privateKey}),c=await(e.api?.fetch??fetch)(`${r}/app/installations/${e.installationId}/access_tokens`,{headers:{accept:`application/vnd.github+json`,authorization:`Bearer ${s}`,"x-github-api-version":`2022-11-28`},method:`POST`}),l=await parseJsonBody(c);if(!c.ok)throw Error(`githubChannel: create installation token failed with HTTP ${c.status}.`);if(!isObject(l)||typeof l.token!=`string`)throw Error(`githubChannel: installation token response did not include a token.`);let u=parseExpiryMs(l.expires_at);return installationTokenCache.set(a,{expiresAtMs:u,token:l.token}),l.token}function clearGitHubInstallationTokenCache(){installationTokenCache.clear()}function seedGitHubInstallationTokenForTests(e){let t=e.apiBaseUrl??`https://api.github.com`,n=e.appId??`test-app`;installationTokenCache.set(`${t}:${n}:${e.installationId}`,{expiresAtMs:Date.now()+3600*1e3,token:e.token})}function base64UrlJson(e){return Buffer.from(JSON.stringify(e)).toString(`base64url`)}async function parseJsonBody(e){let t=await e.text();if(!t)return null;try{return JSON.parse(t)}catch{return t}}function parseExpiryMs(e){if(typeof e==`string`){let t=Date.parse(e);if(Number.isFinite(t))return t}return Date.now()+3600*1e3}export{clearGitHubInstallationTokenCache,createGitHubAppJwt,createGitHubBotNameResolver,createGitHubInstallationToken,normalizeGitHubPrivateKey,resolveGitHubAppId,resolveGitHubInstallationToken,resolveGitHubPrivateKey,resolveGitHubWebhookSecret,seedGitHubInstallationTokenForTests};
@@ -1,6 +1,6 @@
1
1
  import type { SessionAuthContext } from "#channel/types.js";
2
2
  import type { GitHubApiOptions } from "#public/channels/github/api.js";
3
- import type { GitHubChannelCredentials } from "#public/channels/github/auth.js";
3
+ import type { GitHubBotNameResolver, GitHubChannelCredentials } from "#public/channels/github/auth.js";
4
4
  import { type GitHubComment } from "#public/channels/github/inbound.js";
5
5
  import type { GitHubChannelEvents, GitHubInboundContext, GitHubInboundResult, GitHubProgressConfig } from "#public/channels/github/githubChannel.js";
6
6
  /**
@@ -12,13 +12,14 @@ import type { GitHubChannelEvents, GitHubInboundContext, GitHubInboundResult, Gi
12
12
  export declare function defaultGitHubAuth(ctx: GitHubInboundContext): SessionAuthContext;
13
13
  /** Options used by the built-in GitHub comment dispatch hook. */
14
14
  export interface GitHubDefaultDispatchOptions {
15
- readonly botName?: string;
15
+ readonly botName?: GitHubBotNameResolver;
16
16
  }
17
17
  /** Default comment hook: dispatch only when the comment `@mention`s the bot. */
18
- export declare function defaultOnComment(ctx: GitHubInboundContext, comment: GitHubComment, options: GitHubDefaultDispatchOptions): GitHubInboundResult;
18
+ export declare function defaultOnComment(ctx: GitHubInboundContext, comment: GitHubComment, options: GitHubDefaultDispatchOptions): Promise<GitHubInboundResult>;
19
19
  /** Options used by built-in GitHub event handlers. */
20
20
  export interface GitHubDefaultEventOptions {
21
21
  readonly api?: GitHubApiOptions;
22
+ readonly botName?: GitHubBotNameResolver;
22
23
  readonly credentials?: GitHubChannelCredentials;
23
24
  readonly progress?: GitHubProgressConfig;
24
25
  }
@@ -1,3 +1,6 @@
1
- import{createLogger,extractErrorId,formatErrorHint,logError}from"#internal/logging.js";import{checkoutGitHubRepository}from"#public/channels/github/checkout.js";import{shouldDispatchGitHubComment}from"#public/channels/github/inbound.js";import{splitGitHubCommentBody}from"#public/channels/github/limits.js";const log=createLogger(`github.defaults`);function defaultGitHubAuth(e){let{sender:t}=e;return{attributes:{conversation_kind:e.conversation.kind,delivery_id:e.delivery.id,installation_id:String(e.github.installationId??``),issue_number:String(e.conversation.issueNumber??``),pull_request_number:String(e.conversation.pullRequestNumber??``),repository:e.repository.fullName,repository_id:String(e.repository.id),user_login:t.login,user_type:t.type},authenticator:`github-webhook`,issuer:`github:${e.repository.owner}`,principalId:`github:${t.id}`,principalType:t.type===`Bot`?`service`:`user`,subject:t.login}}function defaultOnComment(e,t,n){return shouldDispatchGitHubComment({author:t.author,body:t.body,botName:n.botName})?{auth:defaultGitHubAuth(e)}:null}function createDefaultEvents(e={}){return{async"turn.started"(t,n,i){if(e.progress?.reactions!==!1)try{await n.thread.react(`eyes`)}catch(e){logError(log,`GitHub reaction failed — swallowed`,e)}await checkoutRepositoryForTurn(n,i,e)},async"message.completed"(e,t,n){e.finishReason===`tool-calls`||!e.message||await postCommentChunks(t,e.message)},async"session.failed"(e,r){let i=formatErrorHint(e),a=extractErrorId(e.details);await postFailure(r,[`This session could not recover from an error${i}.`,``,`Start a new comment to continue.`,...a?[``,`Error id: ${a}`]:[]].join(`
1
+ import{createLogger,extractErrorId,formatErrorHint,logError}from"#internal/logging.js";import{checkoutGitHubRepository}from"#public/channels/github/checkout.js";import{shouldDispatchGitHubComment}from"#public/channels/github/inbound.js";import{splitGitHubCommentBody}from"#public/channels/github/limits.js";const log=createLogger(`github.defaults`);function defaultGitHubAuth(e){let{sender:t}=e;return{attributes:{conversation_kind:e.conversation.kind,delivery_id:e.delivery.id,installation_id:String(e.github.installationId??``),issue_number:String(e.conversation.issueNumber??``),pull_request_number:String(e.conversation.pullRequestNumber??``),repository:e.repository.fullName,repository_id:String(e.repository.id),user_login:t.login,user_type:t.type},authenticator:`github-webhook`,issuer:`github:${e.repository.owner}`,principalId:`github:${t.id}`,principalType:t.type===`Bot`?`service`:`user`,subject:t.login}}async function defaultOnComment(e,t,n){return shouldDispatchGitHubComment({author:t.author,body:t.body,botName:await n.botName?.()})?{auth:defaultGitHubAuth(e)}:null}function createDefaultEvents(e={}){return{async"turn.started"(t,n,i){if(e.progress?.reactions!==!1)try{await n.thread.react(`eyes`)}catch(e){logError(log,`GitHub reaction failed — swallowed`,e)}await checkoutRepositoryForTurn(n,i,e)},async"message.completed"(e,t,n){e.finishReason===`tool-calls`||!e.message||await postCommentChunks(t,e.message)},async"input.requested"(t,n,r){if(t.requests.length===0)return;let i=t.requests.map(renderInputRequest),a=renderReplyInstruction(t.requests,await e.botName?.());a!==void 0&&i.push(a),await postCommentChunks(n,i.join(`
2
+
3
+ `))},async"session.failed"(e,r){let i=formatErrorHint(e),a=extractErrorId(e.details);await postFailure(r,[`This session could not recover from an error${i}.`,``,`Start a new comment to continue.`,...a?[``,`Error id: ${a}`]:[]].join(`
2
4
  `))},async"turn.failed"(e,r,i){let a=formatErrorHint(e),o=extractErrorId(e.details);await postFailure(r,[`I hit an error while handling your request${a}.`,``,`Please try again, rephrase, or reach out if it keeps failing.`,...o?[``,`Error id: ${o}`]:[]].join(`
3
- `))}}}async function checkoutRepositoryForTurn(e,t,n){let{state:a}=e;try{let e=await checkoutGitHubRepository(await t.getSandbox(),{api:n.api,baseRef:a.baseRef,baseSha:a.baseSha,credentials:n.credentials,defaultBranch:a.defaultBranch,headRef:a.headRef,headSha:a.headSha,includeBase:a.pullRequestNumber!==null,installationId:a.installationId,owner:a.owner,pullRequestNumber:a.pullRequestNumber,repo:a.repo});a.checkoutPath=e.path,a.headSha=e.sha,a.baseRef=e.baseRef}catch(e){logError(log,`GitHub checkout failed — swallowed`,e)}}async function postCommentChunks(e,t){for(let n of splitGitHubCommentBody(t))await e.thread.post(n)}async function postFailure(e,t){await postCommentChunks(e,t)}export{createDefaultEvents,defaultGitHubAuth,defaultOnComment};
5
+ `))}}}function renderInputRequest(e){let t=[e.prompt];return e.options!==void 0&&e.options.length>0&&t.push(``,...e.options.map((e,t)=>{let n=e.description?` - ${e.description}`:``;return`${t+1}. ${e.label}${n}`})),e.allowFreeform===!0&&t.push(``,`You can also reply with a custom answer.`),t.join(`
6
+ `)}function renderReplyInstruction(e,t){let n=t?.trim();return n?`Answer by mentioning me in a reply, e.g. \`@${n} ${e.find(e=>(e.options?.length??0)>0)?.options?.[0]?.label??`<your answer>`}\`.`:void 0}async function checkoutRepositoryForTurn(e,t,n){let{state:a}=e;try{let e=await checkoutGitHubRepository(await t.getSandbox(),{api:n.api,baseRef:a.baseRef,baseSha:a.baseSha,credentials:n.credentials,defaultBranch:a.defaultBranch,headRef:a.headRef,headSha:a.headSha,includeBase:a.pullRequestNumber!==null,installationId:a.installationId,owner:a.owner,pullRequestNumber:a.pullRequestNumber,repo:a.repo});a.checkoutPath=e.path,a.headSha=e.sha,a.baseRef=e.baseRef}catch(e){logError(log,`GitHub checkout failed — swallowed`,e)}}async function postCommentChunks(e,t){for(let n of splitGitHubCommentBody(t))await e.thread.post(n)}async function postFailure(e,t){await postCommentChunks(e,t)}export{createDefaultEvents,defaultGitHubAuth,defaultOnComment};
@@ -1,10 +1,11 @@
1
1
  import type { ChannelFrom } from "#channel/channel-operations.js";
2
+ import type { GitHubBotNameResolver } from "#public/channels/github/auth.js";
2
3
  import { type GitHubCheckRunWebhookEvent, type GitHubCheckSuiteWebhookEvent, type GitHubIssueCommentEvent, type GitHubIssueWebhookEvent, type GitHubPullRequestReviewCommentEvent, type GitHubPullRequestWebhookEvent, type GitHubWorkflowRunWebhookEvent } from "#public/channels/github/inbound.js";
3
4
  import { type GitHubChannelState } from "#public/channels/github/state.js";
4
5
  import type { GitHubChannelConfig } from "#public/channels/github/githubChannel.js";
5
6
  /** Dispatches a bot-directed issue or PR timeline comment into the runtime. */
6
7
  export declare function dispatchIssueComment(input: {
7
- readonly botName: string | undefined;
8
+ readonly botName: GitHubBotNameResolver;
8
9
  readonly config: GitHubChannelConfig;
9
10
  readonly event: GitHubIssueCommentEvent;
10
11
  readonly handler: NonNullable<GitHubChannelConfig["onComment"]>;
@@ -12,7 +13,7 @@ export declare function dispatchIssueComment(input: {
12
13
  }): Promise<void>;
13
14
  /** Dispatches a bot-directed inline pull-request review comment. */
14
15
  export declare function dispatchPullRequestReviewComment(input: {
15
- readonly botName: string | undefined;
16
+ readonly botName: GitHubBotNameResolver;
16
17
  readonly config: GitHubChannelConfig;
17
18
  readonly event: GitHubPullRequestReviewCommentEvent;
18
19
  readonly handler: NonNullable<GitHubChannelConfig["onComment"]>;
@@ -1 +1 @@
1
- import{createLogger,logError}from"#internal/logging.js";import{extractGitHubCommentTrigger,formatGitHubContextBlock}from"#public/channels/github/inbound.js";import{buildGitHubBinding}from"#public/channels/github/binding.js";import{buildGitHubPullRequestContext,mergeGitHubContext}from"#public/channels/github/pr-context.js";import{continuationTokenFromState,stateFromCiEvent,stateFromIssueCommentEvent,stateFromIssueEvent,stateFromPullRequestEvent,stateFromPullRequestReviewCommentEvent}from"#public/channels/github/state.js";const log=createLogger(`github.dispatch`);async function dispatchIssueComment(e){if(isIgnoredInboundComment(e.event.comment.body,e.event.comment.author,e.botName))return;let t=buildInboundContext(e.config,e.event);await dispatchCommentTurn({body:e.event.comment.body,botName:e.botName,commentUrl:e.event.comment.htmlUrl,event:e.event,handlerResult:()=>e.handler(t,toGitHubComment(e.event.comment)),config:e.config,from:e.from,state:stateFromIssueCommentEvent(e.event)})}async function dispatchPullRequestReviewComment(e){if(isIgnoredInboundComment(e.event.comment.body,e.event.comment.author,e.botName))return;let t=buildInboundContext(e.config,e.event);await dispatchCommentTurn({body:e.event.comment.body,botName:e.botName,commentUrl:e.event.comment.htmlUrl,event:e.event,handlerResult:()=>e.handler(t,toGitHubComment(e.event.comment)),config:e.config,from:e.from,state:stateFromPullRequestReviewCommentEvent(e.event)})}async function dispatchIssue(e){let t=buildInboundContext(e.config,e.event);await dispatchWebhookEventTurn({config:e.config,event:e.event,handlerResult:()=>e.handler(t,e.event.issue),message:formatIssueEventMessage(e.event),from:e.from,state:stateFromIssueEvent(e.event)})}async function dispatchPullRequest(e){let t=buildInboundContext(e.config,e.event);await dispatchWebhookEventTurn({config:e.config,event:e.event,handlerResult:()=>e.handler(t,e.event.pullRequest),message:formatPullRequestEventMessage(e.event),from:e.from,state:stateFromPullRequestEvent(e.event)})}async function dispatchCheckSuite(e){await dispatchCiEvent({...e,ci:e.event.checkSuite,handlerResult:t=>e.handler(t,e.event.checkSuite),label:`Check suite`})}async function dispatchCheckRun(e){await dispatchCiEvent({...e,ci:e.event.checkRun,handlerResult:t=>e.handler(t,e.event.checkRun),label:`Check run`})}async function dispatchWorkflowRun(e){await dispatchCiEvent({...e,ci:e.event.workflowRun,handlerResult:t=>e.handler(t,e.event.workflowRun),label:`Workflow run`})}async function dispatchCiEvent(e){let t=stateFromCiEvent(e.event),n=buildInboundContext(e.config,e.event);if(t.pullRequestNumber===null){await runInboundHandler({event:e.event,handlerResult:()=>e.handlerResult(n)})!=null&&log.warn(`GitHub CI event cannot dispatch without an associated pull request`,{deliveryId:e.event.delivery.id,event:e.event.kind});return}await dispatchWebhookEventTurn({config:e.config,event:e.event,handlerResult:()=>e.handlerResult(n),message:formatCiEventMessage(e.label,e.ci),from:e.from,state:t})}async function dispatchWebhookEventTurn(e){let t=await runInboundHandler({event:e.event,handlerResult:e.handlerResult});t!=null&&await sendGitHubTurn({auth:t.auth,event:e.event,message:e.message,context:mergeGitHubContext({github:await buildPullRequestContext(e.config,e.state,e.event.delivery.id),hook:t.context}),from:e.from,state:e.state})}async function dispatchCommentTurn(e){let t=await runInboundHandler({event:e.event,handlerResult:e.handlerResult});if(t==null)return;let r=extractGitHubCommentTrigger({body:e.body,botName:e.botName})?.message??e.body.trim();await sendGitHubTurn({auth:t.auth,commentUrl:e.commentUrl,event:e.event,message:r,context:mergeGitHubContext({github:await buildPullRequestContext(e.config,e.state,e.event.delivery.id),hook:t.context}),from:e.from,state:e.state})}async function runInboundHandler(e){try{return await e.handlerResult()}catch(n){logError(log,`GitHub inbound handler failed`,n,{deliveryId:e.event.delivery.id});return}}async function sendGitHubTurn(e){let n=formatGitHubContextBlock({deliveryId:e.event.delivery.id,commentUrl:e.commentUrl,headSha:e.state.headSha,issueNumber:e.state.issueNumber,pullRequestNumber:e.state.pullRequestNumber,repository:e.event.repository,sender:e.event.sender});try{await e.from(continuationTokenFromState(e.state)).send(e.message,{auth:e.auth,context:[n,...e.context??[]],state:e.state})}catch(n){logError(log,e.logMessage??`GitHub delivery failed`,n,{deliveryId:e.event.delivery.id})}}async function buildPullRequestContext(e,n,r){try{return await buildGitHubPullRequestContext({api:e.api,baseSha:n.baseSha,config:e.pullRequestContext,credentials:e.credentials,headSha:n.headSha,installationId:n.installationId??void 0,owner:n.owner,pullRequestNumber:n.pullRequestNumber,repo:n.repo})}catch(e){logError(log,`GitHub pull-request context failed — swallowed`,e,{deliveryId:r});return}}function buildInboundContext(e,t){let n=buildGitHubBinding({config:e,state:t.kind===`check_suite`||t.kind===`check_run`||t.kind===`workflow_run`?stateFromCiEvent(t):t.kind===`issue_comment`?stateFromIssueCommentEvent(t):t.kind===`issues`?stateFromIssueEvent(t):t.kind===`pull_request`?stateFromPullRequestEvent(t):stateFromPullRequestReviewCommentEvent(t)});return{conversation:t.conversation,delivery:t.delivery,github:n.github,repository:t.repository,sender:t.sender,thread:n.thread}}function toGitHubComment(e){return{author:e.author,body:e.body,htmlUrl:e.htmlUrl,id:e.id,raw:e.raw,url:e.url}}function formatIssueEventMessage(e){let t=readString(e.issue.raw.title);return`Issue ${e.issue.action}: #${e.issue.issueNumber}${t?` ${t}`:``}`}function formatPullRequestEventMessage(e){let t=readString(e.pullRequest.raw.title);return`Pull request ${e.pullRequest.action}: #${e.pullRequest.pullRequestNumber}${t?` ${t}`:``}`}function formatCiEventMessage(e,t){let n=t.conclusion??t.status;return`${e} ${t.action}: ${ciEventId(t)}${n?` (${n})`:``}`}function ciEventId(e){return`checkSuiteId`in e?e.checkSuiteId:`checkRunId`in e?e.checkRunId:e.workflowRunId}function isIgnoredInboundComment(e,t,n){if(e.includes(`<!-- eve:github:`)||t?.type===`Bot`)return!0;let r=n?`${n}[bot]`.toLowerCase():``;return r.length>0&&t?.login.toLowerCase()===r}function readString(e){return typeof e==`string`&&e.trim().length>0?e.trim():void 0}export{dispatchCheckRun,dispatchCheckSuite,dispatchIssue,dispatchIssueComment,dispatchPullRequest,dispatchPullRequestReviewComment,dispatchWorkflowRun};
1
+ import{createLogger,logError}from"#internal/logging.js";import{extractGitHubCommentTrigger,formatGitHubContextBlock}from"#public/channels/github/inbound.js";import{buildGitHubBinding}from"#public/channels/github/binding.js";import{buildGitHubPullRequestContext,mergeGitHubContext}from"#public/channels/github/pr-context.js";import{continuationTokenFromState,stateFromCiEvent,stateFromIssueCommentEvent,stateFromIssueEvent,stateFromPullRequestEvent,stateFromPullRequestReviewCommentEvent}from"#public/channels/github/state.js";const log=createLogger(`github.dispatch`);async function dispatchIssueComment(e){let t=await e.botName();if(isIgnoredInboundComment(e.event.comment.body,e.event.comment.author,t))return;let n=buildInboundContext(e.config,e.event);await dispatchCommentTurn({body:e.event.comment.body,botName:t,commentUrl:e.event.comment.htmlUrl,event:e.event,handlerResult:()=>e.handler(n,toGitHubComment(e.event.comment)),config:e.config,from:e.from,state:stateFromIssueCommentEvent(e.event)})}async function dispatchPullRequestReviewComment(e){let t=await e.botName();if(isIgnoredInboundComment(e.event.comment.body,e.event.comment.author,t))return;let n=buildInboundContext(e.config,e.event);await dispatchCommentTurn({body:e.event.comment.body,botName:t,commentUrl:e.event.comment.htmlUrl,event:e.event,handlerResult:()=>e.handler(n,toGitHubComment(e.event.comment)),config:e.config,from:e.from,state:stateFromPullRequestReviewCommentEvent(e.event)})}async function dispatchIssue(e){let t=buildInboundContext(e.config,e.event);await dispatchWebhookEventTurn({config:e.config,event:e.event,handlerResult:()=>e.handler(t,e.event.issue),message:formatIssueEventMessage(e.event),from:e.from,state:stateFromIssueEvent(e.event)})}async function dispatchPullRequest(e){let t=buildInboundContext(e.config,e.event);await dispatchWebhookEventTurn({config:e.config,event:e.event,handlerResult:()=>e.handler(t,e.event.pullRequest),message:formatPullRequestEventMessage(e.event),from:e.from,state:stateFromPullRequestEvent(e.event)})}async function dispatchCheckSuite(e){await dispatchCiEvent({...e,ci:e.event.checkSuite,handlerResult:t=>e.handler(t,e.event.checkSuite),label:`Check suite`})}async function dispatchCheckRun(e){await dispatchCiEvent({...e,ci:e.event.checkRun,handlerResult:t=>e.handler(t,e.event.checkRun),label:`Check run`})}async function dispatchWorkflowRun(e){await dispatchCiEvent({...e,ci:e.event.workflowRun,handlerResult:t=>e.handler(t,e.event.workflowRun),label:`Workflow run`})}async function dispatchCiEvent(e){let t=stateFromCiEvent(e.event),n=buildInboundContext(e.config,e.event);if(t.pullRequestNumber===null){await runInboundHandler({event:e.event,handlerResult:()=>e.handlerResult(n)})!=null&&log.warn(`GitHub CI event cannot dispatch without an associated pull request`,{deliveryId:e.event.delivery.id,event:e.event.kind});return}await dispatchWebhookEventTurn({config:e.config,event:e.event,handlerResult:()=>e.handlerResult(n),message:formatCiEventMessage(e.label,e.ci),from:e.from,state:t})}async function dispatchWebhookEventTurn(e){let t=await runInboundHandler({event:e.event,handlerResult:e.handlerResult});t!=null&&await sendGitHubTurn({auth:t.auth,event:e.event,message:e.message,context:mergeGitHubContext({github:await buildPullRequestContext(e.config,e.state,e.event.delivery.id),hook:t.context}),from:e.from,state:e.state})}async function dispatchCommentTurn(e){let t=await runInboundHandler({event:e.event,handlerResult:e.handlerResult});if(t==null)return;let r=extractGitHubCommentTrigger({body:e.body,botName:e.botName})?.message??e.body.trim();await sendGitHubTurn({auth:t.auth,commentUrl:e.commentUrl,event:e.event,message:r,context:mergeGitHubContext({github:await buildPullRequestContext(e.config,e.state,e.event.delivery.id),hook:t.context}),from:e.from,state:e.state})}async function runInboundHandler(e){try{return await e.handlerResult()}catch(n){logError(log,`GitHub inbound handler failed`,n,{deliveryId:e.event.delivery.id});return}}async function sendGitHubTurn(e){let n=formatGitHubContextBlock({deliveryId:e.event.delivery.id,commentUrl:e.commentUrl,headSha:e.state.headSha,issueNumber:e.state.issueNumber,pullRequestNumber:e.state.pullRequestNumber,repository:e.event.repository,sender:e.event.sender});try{await e.from(continuationTokenFromState(e.state)).send(e.message,{auth:e.auth,context:[n,...e.context??[]],state:e.state})}catch(n){logError(log,e.logMessage??`GitHub delivery failed`,n,{deliveryId:e.event.delivery.id})}}async function buildPullRequestContext(e,n,r){try{return await buildGitHubPullRequestContext({api:e.api,baseSha:n.baseSha,config:e.pullRequestContext,credentials:e.credentials,headSha:n.headSha,installationId:n.installationId??void 0,owner:n.owner,pullRequestNumber:n.pullRequestNumber,repo:n.repo})}catch(e){logError(log,`GitHub pull-request context failed — swallowed`,e,{deliveryId:r});return}}function buildInboundContext(e,t){let n=buildGitHubBinding({config:e,state:t.kind===`check_suite`||t.kind===`check_run`||t.kind===`workflow_run`?stateFromCiEvent(t):t.kind===`issue_comment`?stateFromIssueCommentEvent(t):t.kind===`issues`?stateFromIssueEvent(t):t.kind===`pull_request`?stateFromPullRequestEvent(t):stateFromPullRequestReviewCommentEvent(t)});return{conversation:t.conversation,delivery:t.delivery,github:n.github,repository:t.repository,sender:t.sender,thread:n.thread}}function toGitHubComment(e){return{author:e.author,body:e.body,htmlUrl:e.htmlUrl,id:e.id,raw:e.raw,url:e.url}}function formatIssueEventMessage(e){let t=readString(e.issue.raw.title);return`Issue ${e.issue.action}: #${e.issue.issueNumber}${t?` ${t}`:``}`}function formatPullRequestEventMessage(e){let t=readString(e.pullRequest.raw.title);return`Pull request ${e.pullRequest.action}: #${e.pullRequest.pullRequestNumber}${t?` ${t}`:``}`}function formatCiEventMessage(e,t){let n=t.conclusion??t.status;return`${e} ${t.action}: ${ciEventId(t)}${n?` (${n})`:``}`}function ciEventId(e){return`checkSuiteId`in e?e.checkSuiteId:`checkRunId`in e?e.checkRunId:e.workflowRunId}function isIgnoredInboundComment(e,t,n){if(e.includes(`<!-- eve:github:`)||t?.type===`Bot`)return!0;let r=n?`${n}[bot]`.toLowerCase():``;return r.length>0&&t?.login.toLowerCase()===r}function readString(e){return typeof e==`string`&&e.trim().length>0?e.trim():void 0}export{dispatchCheckRun,dispatchCheckSuite,dispatchIssue,dispatchIssueComment,dispatchPullRequest,dispatchPullRequestReviewComment,dispatchWorkflowRun};
@@ -4,7 +4,7 @@ import type { ChannelContinuationOps } from "#public/definitions/channel.js";
4
4
  import type { UnstampedMessageStreamEvent } from "#protocol/message.js";
5
5
  import { type GitHubHandle, type GitHubThread } from "#public/channels/github/binding.js";
6
6
  import { type GitHubApiOptions } from "#public/channels/github/api.js";
7
- import type { GitHubChannelCredentials } from "#public/channels/github/auth.js";
7
+ import { type GitHubBotName, type GitHubChannelCredentials } from "#public/channels/github/auth.js";
8
8
  import { type GitHubCheckRunEvent, type GitHubCheckSuiteEvent, type GitHubComment, type GitHubConversationRef, type GitHubDelivery, type GitHubIssueEvent, type GitHubPullRequestEvent, type GitHubRepositoryRef, type GitHubUser, type GitHubWorkflowRunEvent } from "#public/channels/github/inbound.js";
9
9
  import { type GitHubChannelState } from "#public/channels/github/state.js";
10
10
  import type { GitHubPullRequestContextConfig } from "#public/channels/github/pr-context.js";
@@ -72,9 +72,9 @@ type GitHubSessionFailedHandler = (data: EventData<"session.failed">, channel: G
72
72
  /**
73
73
  * Event handlers for `githubChannel({ events })`. The channel installs built-in
74
74
  * handlers for `turn.started` (eyes reaction plus repo checkout),
75
- * `message.completed` (posts the reply), and `session.failed`/`turn.failed`
76
- * (posts an error comment). A handler supplied here replaces the built-in for
77
- * that key rather than running alongside it.
75
+ * `message.completed` (posts the reply), `input.requested` (posts the prompt),
76
+ * and `session.failed`/`turn.failed` (posts an error comment). A handler supplied
77
+ * here replaces the built-in for that key rather than running alongside it.
78
78
  */
79
79
  export interface GitHubChannelEvents {
80
80
  readonly "action.partial"?: GitHubEventHandler<"action.partial">;
@@ -96,7 +96,12 @@ export interface GitHubChannelEvents {
96
96
  /** Configuration for {@link githubChannel}. */
97
97
  export interface GitHubChannelConfig {
98
98
  readonly api?: GitHubApiOptions;
99
- readonly botName?: string;
99
+ /**
100
+ * The name the channel answers to in `@mentions`, supplied directly or
101
+ * resolved lazily on first use inside request handling. Falls back to the
102
+ * credentials' `appSlug`, then `GITHUB_APP_SLUG`.
103
+ */
104
+ readonly botName?: GitHubBotName;
100
105
  readonly credentials?: GitHubChannelCredentials;
101
106
  readonly events?: GitHubChannelEvents;
102
107
  readonly progress?: GitHubProgressConfig;
@@ -1 +1 @@
1
- import{createLogger}from"#internal/logging.js";import{readNonEmptyString}from"#shared/guards.js";import{POST,defineChannel}from"#public/definitions/channel.js";import{getGitHubRepository}from"#public/channels/github/api.js";import{parseGitHubWebhookEvent}from"#public/channels/github/inbound.js";import{buildGitHubBinding}from"#public/channels/github/binding.js";import{continuationTokenFromState,conversationFromState,initialGitHubState,stateFromReceiveTarget}from"#public/channels/github/state.js";import{GITHUB_CHANNEL_DEFAULT_ROUTE}from"#public/channels/github/constants.js";import{createDefaultEvents,defaultOnComment}from"#public/channels/github/defaults.js";import{dispatchCheckRun,dispatchCheckSuite,dispatchIssue,dispatchIssueComment,dispatchPullRequest,dispatchPullRequestReviewComment,dispatchWorkflowRun}from"#public/channels/github/dispatch.js";import{verifyGitHubRequest}from"#public/channels/github/verify.js";const log=createLogger(`github.channel`);function githubChannel(e={}){let c=e.botName??process.env.GITHUB_APP_SLUG,d={botName:c},f={...createDefaultEvents({api:e.api,credentials:e.credentials,progress:e.progress}),...e.events};return defineChannel({kindHint:`github`,turnPolicy:e.turnPolicy,state:initialGitHubState(),context(t,n){return rebuildGitHubContext(t,n,e)},routes:[POST(e.route??GITHUB_CHANNEL_DEFAULT_ROUTE,async(t,{from:n,waitUntil:r})=>{let i=await verifyInbound(t,e.credentials);if(i===null)return new Response(`unauthorized`,{status:401});let o=missingGitHubWebhookHeaders(t.headers),s;try{s=parseGitHubWebhookEvent({body:i,contentType:t.headers.get(`content-type`)??void 0,headers:t.headers})}catch(e){return log.warn(`inbound GitHub body is not valid JSON`,{error:e}),jsonOk({ignored:!0,ok:!0})}return s===null?(o.length>0&&log.warn(`GitHub webhook ignored because standard headers were missing`,{missingHeaders:o}),jsonOk({ignored:!0,ok:!0})):(o.length>0&&log.warn(`GitHub webhook missing standard headers; inferred metadata from payload`,{deliveryId:s.delivery.id,event:s.delivery.event,missingHeaders:o,repository:s.repository.fullName}),s.kind===`ping`?jsonOk({ok:!0}):s.kind===`issue_comment`&&s.action===`created`?(r(dispatchIssueComment({botName:c,config:e,event:s,handler:e.onComment??((e,t)=>defaultOnComment(e,t,d)),from:n})),jsonOk({ok:!0})):s.kind===`pull_request_review_comment`&&s.action===`created`?(r(dispatchPullRequestReviewComment({botName:c,config:e,event:s,handler:e.onComment??((e,t)=>defaultOnComment(e,t,d)),from:n})),jsonOk({ok:!0})):s.kind===`issues`&&e.onIssue!==void 0?(r(dispatchIssue({config:e,event:s,handler:e.onIssue,from:n})),jsonOk({ok:!0})):s.kind===`pull_request`&&e.onPullRequest!==void 0?(r(dispatchPullRequest({config:e,event:s,handler:e.onPullRequest,from:n})),jsonOk({ok:!0})):s.kind===`check_suite`&&e.onCheckSuite!==void 0?(r(dispatchCheckSuite({config:e,event:s,handler:e.onCheckSuite,from:n})),jsonOk({ok:!0})):s.kind===`check_run`&&e.onCheckRun!==void 0?(r(dispatchCheckRun({config:e,event:s,handler:e.onCheckRun,from:n})),jsonOk({ok:!0})):s.kind===`workflow_run`&&e.onWorkflowRun!==void 0?(r(dispatchWorkflowRun({config:e,event:s,handler:e.onWorkflowRun,from:n})),jsonOk({ok:!0})):jsonOk({ignored:!0,ok:!0}))})],async receive(n,{from:r}){let a=n.target,c=readNonEmptyString(a.owner),l=readNonEmptyString(a.repo);if(c===void 0||l===void 0)throw Error(`githubChannel().receive requires target.owner and target.repo.`);if([a.issueNumber!==void 0,a.pullRequestNumber!==void 0].filter(Boolean).length!==1)throw Error(`githubChannel().receive requires exactly one of issueNumber or pullRequestNumber.`);let u=stateFromReceiveTarget({target:a,owner:c,repo:l,repositoryId:a.repositoryId??(await getGitHubRepository({api:e.api,credentials:e.credentials,installationId:a.installationId,owner:c,repo:l})).id});if(a.initialMessage!==void 0){let{thread:t}=buildGitHubBinding({config:e,state:u});await t.post(a.initialMessage)}return r(continuationTokenFromState(u)).send(n.message,{auth:n.auth,state:u})},events:f})}function rebuildGitHubContext(e,t,n){let r=buildGitHubBinding({config:n,state:e});return{conversation:conversationFromState(e),github:r.github,repository:r.github.repository,state:e,thread:r.thread}}async function verifyInbound(e,t){try{return await verifyGitHubRequest(e,{webhookSecret:t?.webhookSecret,webhookVerifier:t?.webhookVerifier})}catch(e){return log.warn(`github inbound verification failed`,{error:e}),null}}function missingGitHubWebhookHeaders(e){return[`x-github-event`,`x-github-delivery`].filter(t=>{let n=e.get(t);return n===null||n.trim().length===0})}function jsonOk(e){return new Response(JSON.stringify(e),{headers:{"content-type":`application/json; charset=utf-8`},status:200})}export{githubChannel};
1
+ import{createLogger}from"#internal/logging.js";import{readNonEmptyString}from"#shared/guards.js";import{POST,defineChannel}from"#public/definitions/channel.js";import{createGitHubBotNameResolver}from"#public/channels/github/auth.js";import{getGitHubRepository}from"#public/channels/github/api.js";import{parseGitHubWebhookEvent}from"#public/channels/github/inbound.js";import{buildGitHubBinding}from"#public/channels/github/binding.js";import{continuationTokenFromState,conversationFromState,initialGitHubState,stateFromReceiveTarget}from"#public/channels/github/state.js";import{GITHUB_CHANNEL_DEFAULT_ROUTE}from"#public/channels/github/constants.js";import{createDefaultEvents,defaultOnComment}from"#public/channels/github/defaults.js";import{dispatchCheckRun,dispatchCheckSuite,dispatchIssue,dispatchIssueComment,dispatchPullRequest,dispatchPullRequestReviewComment,dispatchWorkflowRun}from"#public/channels/github/dispatch.js";import{verifyGitHubRequest}from"#public/channels/github/verify.js";const log=createLogger(`github.channel`);function githubChannel(e={}){let c=createGitHubBotNameResolver({botName:e.botName,credentials:e.credentials}),u={botName:c},d={...createDefaultEvents({api:e.api,botName:c,credentials:e.credentials,progress:e.progress}),...e.events};return defineChannel({kindHint:`github`,turnPolicy:e.turnPolicy,state:initialGitHubState(),context(t,n){return rebuildGitHubContext(t,n,e)},routes:[POST(e.route??GITHUB_CHANNEL_DEFAULT_ROUTE,async(t,{from:n,waitUntil:r})=>{let i=await verifyInbound(t,e.credentials);if(i===null)return new Response(`unauthorized`,{status:401});let a=missingGitHubWebhookHeaders(t.headers),s;try{s=parseGitHubWebhookEvent({body:i,contentType:t.headers.get(`content-type`)??void 0,headers:t.headers})}catch(e){return log.warn(`inbound GitHub body is not valid JSON`,{error:e}),jsonOk({ignored:!0,ok:!0})}return s===null?(a.length>0&&log.warn(`GitHub webhook ignored because standard headers were missing`,{missingHeaders:a}),jsonOk({ignored:!0,ok:!0})):(a.length>0&&log.warn(`GitHub webhook missing standard headers; inferred metadata from payload`,{deliveryId:s.delivery.id,event:s.delivery.event,missingHeaders:a,repository:s.repository.fullName}),s.kind===`ping`?jsonOk({ok:!0}):s.kind===`issue_comment`&&s.action===`created`?(r(dispatchIssueComment({botName:c,config:e,event:s,handler:e.onComment??((e,t)=>defaultOnComment(e,t,u)),from:n})),jsonOk({ok:!0})):s.kind===`pull_request_review_comment`&&s.action===`created`?(r(dispatchPullRequestReviewComment({botName:c,config:e,event:s,handler:e.onComment??((e,t)=>defaultOnComment(e,t,u)),from:n})),jsonOk({ok:!0})):s.kind===`issues`&&e.onIssue!==void 0?(r(dispatchIssue({config:e,event:s,handler:e.onIssue,from:n})),jsonOk({ok:!0})):s.kind===`pull_request`&&e.onPullRequest!==void 0?(r(dispatchPullRequest({config:e,event:s,handler:e.onPullRequest,from:n})),jsonOk({ok:!0})):s.kind===`check_suite`&&e.onCheckSuite!==void 0?(r(dispatchCheckSuite({config:e,event:s,handler:e.onCheckSuite,from:n})),jsonOk({ok:!0})):s.kind===`check_run`&&e.onCheckRun!==void 0?(r(dispatchCheckRun({config:e,event:s,handler:e.onCheckRun,from:n})),jsonOk({ok:!0})):s.kind===`workflow_run`&&e.onWorkflowRun!==void 0?(r(dispatchWorkflowRun({config:e,event:s,handler:e.onWorkflowRun,from:n})),jsonOk({ok:!0})):jsonOk({ignored:!0,ok:!0}))})],async receive(n,{from:r}){let i=n.target,o=readNonEmptyString(i.owner),c=readNonEmptyString(i.repo);if(o===void 0||c===void 0)throw Error(`githubChannel().receive requires target.owner and target.repo.`);if([i.issueNumber!==void 0,i.pullRequestNumber!==void 0].filter(Boolean).length!==1)throw Error(`githubChannel().receive requires exactly one of issueNumber or pullRequestNumber.`);let l=stateFromReceiveTarget({target:i,owner:o,repo:c,repositoryId:i.repositoryId??(await getGitHubRepository({api:e.api,credentials:e.credentials,installationId:i.installationId,owner:o,repo:c})).id});if(i.initialMessage!==void 0){let{thread:t}=buildGitHubBinding({config:e,state:l});await t.post(i.initialMessage)}return r(continuationTokenFromState(l)).send(n.message,{auth:n.auth,state:l})},events:d})}function rebuildGitHubContext(e,t,n){let r=buildGitHubBinding({config:n,state:e});return{conversation:conversationFromState(e),github:r.github,repository:r.github.repository,state:e,thread:r.thread}}async function verifyInbound(e,t){try{return await verifyGitHubRequest(e,{webhookSecret:t?.webhookSecret,webhookVerifier:t?.webhookVerifier})}catch(e){return log.warn(`github inbound verification failed`,{error:e}),null}}function missingGitHubWebhookHeaders(e){return[`x-github-event`,`x-github-delivery`].filter(t=>{let n=e.get(t);return n===null||n.trim().length===0})}function jsonOk(e){return new Response(JSON.stringify(e),{headers:{"content-type":`application/json; charset=utf-8`},status:200})}export{githubChannel};
@@ -1,6 +1,6 @@
1
1
  export { GitHubApiError, type GitHubApiMethod, type GitHubApiOptions, type GitHubApiResponse, type GitHubJsonObject, type GitHubPostedComment, type GitHubReactionContent, } from "#public/channels/github/api.js";
2
2
  export { type GitHubHandle, type GitHubThread } from "#public/channels/github/binding.js";
3
- export { type GitHubAppId, type GitHubChannelCredentials, type GitHubInstallationToken, type GitHubPrivateKey, type GitHubWebhookSecret, } from "#public/channels/github/auth.js";
3
+ export { type GitHubAppId, type GitHubBotName, type GitHubChannelCredentials, type GitHubInstallationToken, type GitHubPrivateKey, type GitHubWebhookSecret, } from "#public/channels/github/auth.js";
4
4
  export { defaultGitHubAuth } from "#public/channels/github/defaults.js";
5
5
  export { type GitHubAppRef, type GitHubCheckRunEvent, type GitHubCheckSuiteEvent, type GitHubCiEvent, type GitHubCiPayload, type GitHubComment, type GitHubConversationKind, type GitHubConversationRef, type GitHubDelivery, type GitHubIssueAction, type GitHubIssueEvent, type GitHubPullRequestAction, type GitHubPullRequestEvent, type GitHubRepositoryRef, type GitHubUser, type GitHubWorkflowRunEvent, } from "#public/channels/github/inbound.js";
6
6
  export { githubChannel, type GitHubChannel, type GitHubChannelConfig, type GitHubChannelEvents, type GitHubEventContext, type GitHubInboundContext, type GitHubInboundResult, type GitHubInboundResultOrPromise, type GitHubProgressConfig, type GitHubReceiveTarget, } from "#public/channels/github/githubChannel.js";
@@ -1,4 +1,4 @@
1
- import{createLogger,extractErrorId,formatErrorHint}from"#internal/logging.js";import{SLACK_MAX_BLOCKS_PER_MESSAGE,truncateMessageText,truncateTypingStatus}from"#public/channels/slack/limits.js";import{describeActionRequests}from"#public/channels/slack/action-status.js";import{buildSlackAuthContext,slackUserIdFromAuthContext}from"#public/channels/slack/auth.js";import{buildAuthCompletedText,buildAuthEphemeralBlocks,buildAuthRequiredPublicText,formatConnectionDisplayName}from"#public/channels/slack/connections.js";import{renderInputRequestPostParts}from"#public/channels/slack/hitl.js";const log=createLogger(`slack.defaults`);function defaultSlackAuth(e,t){let n=e.author;return n?buildSlackAuthContext({channelId:t.slack.channelId,fullName:n.fullName,isBot:n.isBot,teamId:e.teamId,threadTs:t.slack.threadTs,userId:n.userId,userName:n.userName}):null}async function defaultOnAppMention(e,t){return await e.thread.startTyping(`Thinking...`),{auth:defaultSlackAuth(t,e)}}async function defaultOnDirectMessage(e,t){return await e.thread.startTyping(`Thinking...`),{auth:defaultSlackAuth(t,e)}}function firstNonEmptyLine(e){for(let t of e.split(/\r?\n/u)){let e=t.trim();if(e.length>0)return e}}function defaultInputRequestedHandler(){return async(e,t,n)=>{for(let n of buildInputRequestPosts(e.requests))await t.thread.post(n)}}function buildInputRequestPosts(e){let t=[],n=[];for(let r of e){let e=renderInputRequestPostParts(r);e.details&&t.push(e.details),n.push(e.controls)}return[...groupInputRequestPostParts(t),...groupInputRequestPostParts(n)]}function groupInputRequestPostParts(e){let t=[];for(let n of e){let e=t.at(-1);e&&e.blocks.length+n.blocks.length<=SLACK_MAX_BLOCKS_PER_MESSAGE?(e.blocks.push(...n.blocks),e.fallbacks.push(n.text)):t.push({blocks:[...n.blocks],fallbacks:[n.text]})}return t.map(e=>({blocks:e.blocks,text:truncateMessageText(e.fallbacks.join(`
2
- `))}))}const defaultEvents={async"turn.started"(e,t,n){t.state.pendingToolCallMessage=null,t.state.lastReasoningTypingAtMs=null,t.state.lastReasoningTypingStatus=null,await t.thread.startTyping(`Working...`)},async"reasoning.appended"(e,t,n){let r=firstNonEmptyLine(e.reasoningSoFar);if(r===void 0)return;let i=truncateTypingStatus(r),o=t.state.lastReasoningTypingStatus,s=o!=null&&i.startsWith(o)&&i.length>=o.length+4,c=Date.now(),l=t.state.lastReasoningTypingAtMs;if(!s&&l!=null){let e=c-l;if(e>=0&&e<5e3)return}await t.thread.startTyping(i),t.state.lastReasoningTypingAtMs=c,t.state.lastReasoningTypingStatus=i},async"actions.requested"(e,t,n){let r=t.state.pendingToolCallMessage;if(t.state.pendingToolCallMessage=null,r){await t.thread.startTyping(truncateTypingStatus(r));return}await t.thread.startTyping(truncateTypingStatus(describeActionRequests(e.actions)))},async"message.completed"(e,t,n){if(e.finishReason===`tool-calls`){t.state.pendingToolCallMessage=e.message?firstNonEmptyLine(e.message)??null:null;return}if(t.state.pendingToolCallMessage=null,!e.message){await t.thread.startTyping();return}await t.thread.post(e.message)},async"turn.failed"(e,r,i){let a=formatErrorHint(e),o=extractErrorId(e.details);await r.thread.post([`I hit an error while handling your request${a}.`,``,`Please try again, rephrase, or reach out if it keeps failing.`,...o?[``,`_Error id: \`${o}\`_`]:[]].join(`
1
+ import{createLogger,extractErrorId,formatErrorHint}from"#internal/logging.js";import{SLACK_MAX_BLOCKS_PER_MESSAGE,truncateMessageText,truncateTypingStatus}from"#public/channels/slack/limits.js";import{describeActionRequests}from"#public/channels/slack/action-status.js";import{buildSlackAuthContext,slackUserIdFromAuthContext}from"#public/channels/slack/auth.js";import{buildAuthCompletedText,buildAuthEphemeralBlocks,buildAuthRequiredPublicText,formatConnectionDisplayName}from"#public/channels/slack/connections.js";import{buildAnsweredBlocks,renderInputRequestPostParts}from"#public/channels/slack/hitl.js";const log=createLogger(`slack.defaults`);function blockContainsRequestAction(e,t){if(typeof e!=`object`||!e)return!1;let n=e,r=`eve_input:${t}`;return[n.actions,n.elements].some(e=>Array.isArray(e)&&e.some(e=>{if(typeof e!=`object`||!e)return!1;let t=e.action_id;return typeof t==`string`&&t.startsWith(r)}))}function defaultSlackAuth(e,t){let n=e.author;return n?buildSlackAuthContext({channelId:t.slack.channelId,fullName:n.fullName,isBot:n.isBot,teamId:e.teamId,threadTs:t.slack.threadTs,userId:n.userId,userName:n.userName}):null}async function defaultOnAppMention(e,t){return await e.thread.startTyping(`Thinking...`),{auth:defaultSlackAuth(t,e)}}async function defaultOnDirectMessage(e,t){return await e.thread.startTyping(`Thinking...`),{auth:defaultSlackAuth(t,e)}}function firstNonEmptyLine(e){for(let t of e.split(/\r?\n/u)){let e=t.trim();if(e.length>0)return e}}function defaultInputRequestedHandler(){return async(e,t,n)=>{for(let n of buildInputRequestPosts(e.requests)){let e=await t.thread.post({blocks:n.blocks,text:n.text});if(!e.id)continue;let r={...t.state.pendingApprovalCards};for(let t of n.requests)t.kind===`tool-approval`&&(r[t.requestId]={messageBlocks:n.blocks,messageTs:e.id});t.state.pendingApprovalCards=r}}}function buildInputRequestPosts(e){let t=[],n=[];for(let r of e){let e=renderInputRequestPostParts(r);e.details&&t.push({...e.details,request:r}),n.push({...e.controls,request:r})}return[...groupInputRequestPostParts(t),...groupInputRequestPostParts(n)]}function groupInputRequestPostParts(e){let t=[];for(let n of e){let e=t.at(-1);e&&e.blocks.length+n.blocks.length<=SLACK_MAX_BLOCKS_PER_MESSAGE?(e.blocks.push(...n.blocks),e.fallbacks.push(n.text),e.requests.push(n.request)):t.push({blocks:[...n.blocks],fallbacks:[n.text],requests:[n.request]})}return t.map(e=>({blocks:e.blocks,requests:e.requests,text:truncateMessageText(e.fallbacks.join(`
2
+ `))}))}const defaultEvents={async"approval.candidate"(e,t,n){let r=t.state.pendingApprovalCandidateUsers?.[e.candidateId];if(e.outcome===`pending`&&r!==void 0){await t.thread.postEphemeral(r,`Checking whether you can approve this action…`);return}r!==void 0&&(e.outcome===`rejected`||e.outcome===`failed`)&&await t.thread.postEphemeral(r,e.reason??`We couldn’t verify your approval. Please try again.`)},async"approval.settled"(e,t,n){let r=t.state.pendingApprovalCards??{},i=r[e.requestId];if(i===void 0||t.state.channelId===null)return;let a=e.outcome===`approved`?`Approve`:`Cancel`,o=i.messageBlocks.flatMap(t=>{if(!blockContainsRequestAction(t,e.requestId))return[t];if(typeof t!=`object`||!t)return[];let n=t;if(n.type!==`card`)return buildAnsweredBlocks({answerLabel:a,promptBlocks:[],userId:i.userId});let{actions:r,...o}=n;return buildAnsweredBlocks({answerLabel:a,promptBlocks:[o],userId:i.userId})});await t.slack.request(`chat.update`,{blocks:o,channel:t.state.channelId,text:`Answered: ${a}`,ts:i.messageTs});let s={...r};delete s[e.requestId],t.state.pendingApprovalCards=s},async"turn.started"(e,t,n){t.state.pendingToolCallMessage=null,t.state.lastReasoningTypingAtMs=null,t.state.lastReasoningTypingStatus=null,await t.thread.startTyping(`Working...`)},async"reasoning.appended"(e,t,n){let r=firstNonEmptyLine(e.reasoningSoFar);if(r===void 0)return;let i=truncateTypingStatus(r),o=t.state.lastReasoningTypingStatus,s=o!=null&&i.startsWith(o)&&i.length>=o.length+4,c=Date.now(),l=t.state.lastReasoningTypingAtMs;if(!s&&l!=null){let e=c-l;if(e>=0&&e<5e3)return}await t.thread.startTyping(i),t.state.lastReasoningTypingAtMs=c,t.state.lastReasoningTypingStatus=i},async"actions.requested"(e,t,n){let r=t.state.pendingToolCallMessage;if(t.state.pendingToolCallMessage=null,r){await t.thread.startTyping(truncateTypingStatus(r));return}await t.thread.startTyping(truncateTypingStatus(describeActionRequests(e.actions)))},async"message.completed"(e,t,n){if(e.finishReason===`tool-calls`){t.state.pendingToolCallMessage=e.message?firstNonEmptyLine(e.message)??null:null;return}if(t.state.pendingToolCallMessage=null,!e.message){await t.thread.startTyping();return}await t.thread.post(e.message)},async"turn.failed"(e,r,i){let a=formatErrorHint(e),o=extractErrorId(e.details);await r.thread.post([`I hit an error while handling your request${a}.`,``,`Please try again, rephrase, or reach out if it keeps failing.`,...o?[``,`_Error id: \`${o}\`_`]:[]].join(`
3
3
  `))},async"session.failed"(e,r){let i=formatErrorHint(e),a=extractErrorId(e.details);await r.thread.post([`This session couldn't recover from an error${i}.`,``,`Start a new thread to continue — I can't pick this one back up.`,...a?[``,`_Error id: \`${a}\`_`]:[]].join(`
4
- `))},async"authorization.required"(e,t,n){let r=e.authorization?.displayName??formatConnectionDisplayName(e.name),i=slackUserIdFromAuthContext(n.session.auth.current)??t.state.triggeringUserId??null,a=e.authorization?.url,o=t.state.pendingAuthMessageTs??{};if(o[e.name]===void 0){let n=buildAuthRequiredPublicText({displayName:r,hasUser:i!==null});try{let r=await t.thread.post(n);r.id&&(t.state.pendingAuthMessageTs={...o,[e.name]:r.id})}catch(t){log.error(`Slack auth public message delivery failed`,{name:e.name,error:t})}}if(i&&a){let n=e.authorization?.userCode;try{await t.thread.postEphemeral(i,{blocks:buildAuthEphemeralBlocks({displayName:r,url:a,userCode:n}),text:n?`Sign in with ${r}: ${a} (code: ${n})`:`Sign in with ${r}: ${a}`})}catch(t){log.error(`Slack auth ephemeral delivery failed`,{name:e.name,error:t})}}},async"authorization.completed"(e,t,n){let r=e.authorization?.displayName??formatConnectionDisplayName(e.name);e.outcome===`authorized`&&await t.thread.startTyping(`Connected to ${r}. Resuming...`);let i=t.state.pendingAuthMessageTs??{},a=i[e.name];if(a===void 0)return;let o=buildAuthCompletedText({displayName:r,outcome:e.outcome,reason:e.reason});try{await t.slack.request(`chat.update`,{channel:t.slack.channelId,ts:a,text:o})}catch(t){log.error(`Slack auth status edit failed`,{name:e.name,error:t})}let s={...i};delete s[e.name],t.state.pendingAuthMessageTs=s}};export{defaultEvents,defaultInputRequestedHandler,defaultOnAppMention,defaultOnDirectMessage,defaultSlackAuth};
4
+ `))},async"authorization.required"(e,t,n){let r=e.authorization?.displayName??formatConnectionDisplayName(e.name),i=e.candidateId===void 0?slackUserIdFromAuthContext(n.session.auth.current)??t.state.triggeringUserId??null:t.state.pendingApprovalCandidateUsers?.[e.candidateId]??null,a=e.authorization?.url,o=t.state.pendingAuthMessageTs??{};if(e.candidateId===void 0&&o[e.name]===void 0){let n=buildAuthRequiredPublicText({displayName:r,hasUser:i!==null});try{let r=await t.thread.post(n);r.id&&(t.state.pendingAuthMessageTs={...o,[e.name]:r.id})}catch(t){log.error(`Slack auth public message delivery failed`,{name:e.name,error:t})}}if(i&&a){let n=e.authorization?.userCode;try{await t.thread.postEphemeral(i,{blocks:buildAuthEphemeralBlocks({displayName:r,url:a,userCode:n}),text:n?`Sign in with ${r}: ${a} (code: ${n})`:`Sign in with ${r}: ${a}`})}catch(t){log.error(`Slack auth ephemeral delivery failed`,{name:e.name,error:t})}}},async"authorization.completed"(e,t,n){let r=e.authorization?.displayName??formatConnectionDisplayName(e.name);e.outcome===`authorized`&&e.candidateId===void 0&&await t.thread.startTyping(`Connected to ${r}. Resuming...`);let i=t.state.pendingAuthMessageTs??{},a=i[e.name];if(a===void 0)return;let o=buildAuthCompletedText({displayName:r,outcome:e.outcome,reason:e.reason});try{await t.slack.request(`chat.update`,{channel:t.slack.channelId,ts:a,text:o})}catch(t){log.error(`Slack auth status edit failed`,{name:e.name,error:t})}let s={...i};delete s[e.name],t.state.pendingAuthMessageTs=s}};export{defaultEvents,defaultInputRequestedHandler,defaultOnAppMention,defaultOnDirectMessage,defaultSlackAuth};
@@ -1 +1 @@
1
- import{createLogger}from"#internal/logging.js";import{SLACK_CARD_SUBTEXT_MAX_LENGTH,truncateCardSubtext}from"#public/channels/slack/limits.js";import{buildSlackBinding,resolveSlackBotToken,slackContinuationToken}from"#public/channels/slack/api.js";import{buildSlackAuthContext}from"#public/channels/slack/auth.js";import{HITL_FREEFORM_MODAL_ACTION_ID,HITL_FREEFORM_MODAL_BLOCK_ID,HITL_FREEFORM_MODAL_CALLBACK_ID,buildAnsweredBlocks,buildFreeformModalView,deriveHitlResponse,freeformRequestIdFromActionId,isFreeformAction,isHitlAction}from"#public/channels/slack/hitl.js";import{parseSlackWebhookBody}from"#compiled/@chat-adapter/slack/webhook.js";import{bindSlackSessionOperations}from"#public/channels/slack/session-operations.js";const log=createLogger(`slack.interactions`);function parseBlockActionsPayload(e){if(isSharedBlockActionsPayload(e))return parseSharedBlockActionsPayload(e);let t=e,n=t.actions;if(!Array.isArray(n))return null;let r=t.channel?.id,i=t.message,a=i?.thread_ts??i?.ts;if(!r||!a)return null;let o=t.team,s=t.user,c=o?.id??s.team_id,l={id:s.id,username:s.username,name:s.name},u=i?.blocks??[];return{actions:n.map(e=>({actionId:String(e.action_id??``),value:e.value==null?void 0:String(e.value),blockId:e.block_id==null?void 0:String(e.block_id),selectedOptionValue:extractSelectedOptionValue(e),messageTs:i?.ts,label:extractActionLabel(e),user:l})),channelId:r,threadTs:a,teamId:c,messageBlocks:u}}function isSharedBlockActionsPayload(e){return e.kind===`block_actions`&&Array.isArray(e.actions)}function parseSharedBlockActionsPayload(e){return!e.channelId||!e.threadTs?null:{actions:e.actions.map(t=>({actionId:t.actionId,value:t.value,blockId:t.blockId,selectedOptionValue:t.selectedOptionValue,messageTs:e.messageTs,label:t.label,user:{id:t.user?.id??e.userId,username:t.user?.username,name:t.user?.name}})),channelId:e.channelId,threadTs:e.threadTs,teamId:e.teamId,messageBlocks:e.messageBlocks??[]}}function extractSelectedOptionValue(e){let t=e.selected_option;return typeof t?.value==`string`?t.value:void 0}function extractActionLabel(e){let t=e.selected_option?.text?.text;if(typeof t==`string`&&t.length>0)return t;let n=e.text?.text;if(typeof n==`string`&&n.length>0)return n}function findPromptBlock(e){return findPromptBlocks(e)[0]}function findPromptBlocks(e){let t=[];for(let n of e){if(typeof n!=`object`||!n)continue;let e=n.type;if(e===`actions`)break;(e===`section`||e===`context`||e===`divider`||e===`image`)&&t.push(n)}return t}function readPromptTextFromBlocks(e){let t=findPromptBlock(e)?.text?.text;return typeof t==`string`&&t.length>0?t:void 0}function buildAnsweredHitlMessageBlocks(e){let t=findActionBlockIndex(e.messageBlocks,e.actionId);if(t===-1)return buildAnsweredBlocks({promptBlocks:findPromptBlocks(e.messageBlocks),answerLabel:e.answerLabel,userId:e.userId});let n=e.messageBlocks[t],r=answeredBlocksFromActionBlock({answerLabel:e.answerLabel,block:n,userId:e.userId})??buildAnsweredBlocks({promptBlocks:promptBlocksFromActionBlock(n),answerLabel:e.answerLabel,userId:e.userId});return[...e.messageBlocks.slice(0,t),...r,...e.messageBlocks.slice(t+1)]}function findActionBlockIndex(e,t){return e.findIndex(e=>blockContainsActionId(e,t))}function blockContainsActionId(e,t){return isObjectRecord(e)?actionsContainActionId(e.elements,t)||actionsContainActionId(e.actions,t):!1}function actionsContainActionId(e,t){return Array.isArray(e)?e.some(e=>isObjectRecord(e)&&e.action_id===t):!1}function isObjectRecord(e){return typeof e==`object`&&!!e}function answeredBlocksFromActionBlock(e){if(!isObjectRecord(e.block)||e.block.type!==`card`)return;let{actions:t,subtext:n,...r}=e.block,i={...r,subtext:{type:`mrkdwn`,text:formatAnsweredCardSubtext(e),verbatim:!1}};return hasCardContent(i)?[i]:void 0}function formatAnsweredCardSubtext(e){let r=e.userId.length>0?` by <@${e.userId}>`:``,i=SLACK_CARD_SUBTEXT_MAX_LENGTH-20-1-r.length;return truncateCardSubtext(`:white_check_mark: *${truncateWithEllipsis(e.answerLabel,i)}*${r}`)}function truncateWithEllipsis(e,t){if(t<=0)return``;if(e.length<=t)return e;let n=Math.max(0,t-3);return`${e.slice(0,n).trimEnd()}...`}function promptBlocksFromActionBlock(e){if(!isObjectRecord(e)||e.type!==`card`)return[];let{actions:t,...n}=e;return hasCardContent(n)?[n]:[]}function hasCardContent(e){return e.body!==void 0||e.title!==void 0||e.hero_image!==void 0}async function handleInteractionPost(e,t,n){let i=new Response(`ok`,{status:200}),s;try{s=parseSlackWebhookBody(e,{contentType:`application/x-www-form-urlencoded`})}catch{return log.warn(`failed to parse Slack interaction payload`),i}if(s.kind===`view_submission`)return handleViewSubmission(s,t,n);if(s.kind!==`block_actions`)return i;let c=parseBlockActionsPayload(s);if(!c)return i;let l=c.actions.find(e=>isFreeformAction(e.actionId));if(l)return await openFreeformModal({payload:s.raw,interaction:c,freeformAction:l,deps:n}),i;let u=slackContinuationToken(c.channelId,c.threadTs),d=c.actions.map(deriveHitlResponse).filter(e=>e!==null);if(d.length>0){let e=c.actions[0]?.user;if(!e)return i;t.waitUntil(t.from(u).respond(d,{auth:buildSlackAuthContext({channelId:c.channelId,teamId:c.teamId,threadTs:c.threadTs,userId:e.id,userName:e.username??e.name})}).catch(e=>{log.error(`HITL interaction delivery failed`,{error:e})})),t.waitUntil(updateAnsweredHitlCard(c,n).catch(e=>{log.error(`HITL answered-card update failed`,{error:e})}))}let p=n.config.onInteraction;if(p){let e=c.actions.filter(e=>!isHitlAction(e.actionId));if(e.length>0){let i=e[0].user,{thread:a,slack:s}=buildSlackBinding({botToken:n.config.credentials?.botToken,channelId:c.channelId,threadTs:c.threadTs,teamId:c.teamId}),l={...bindSlackSessionOperations({address:u,defaultAuth:buildSlackAuthContext({channelId:c.channelId,teamId:c.teamId,threadTs:c.threadTs,userId:i.id,userName:i.username??i.name}),from:t.from,resolveSession:t.resolveSession,state:{channelId:c.channelId,teamId:c.teamId??null,threadTs:c.threadTs,triggeringUserId:i.id}}),thread:a,slack:s};for(let n of e)t.waitUntil(Promise.resolve(p(n,l)).catch(e=>{log.error(`custom interaction handler failed`,{error:e})}))}}return i}async function openFreeformModal(e){let t=e.payload.trigger_id;if(typeof t!=`string`||t.length===0){log.warn(`freeform button click missing trigger_id — cannot open modal`);return}let n=freeformRequestIdFromActionId(e.freeformAction.actionId)??e.freeformAction.value;if(!n){log.warn(`freeform button click missing requestId`);return}let r=e.freeformAction.messageTs;if(!r){log.warn(`freeform button click missing messageTs`);return}let o=buildFreeformModalView({metadata:{continuationToken:slackContinuationToken(e.interaction.channelId,e.interaction.threadTs),channelId:e.interaction.channelId,threadTs:e.interaction.threadTs,messageTs:r,requestId:n},prompt:readPromptTextFromBlocks(e.interaction.messageBlocks)}),s=await resolveSlackBotToken(e.deps.config.credentials?.botToken),c=await fetch(`https://slack.com/api/views.open`,{method:`POST`,headers:{authorization:`Bearer ${s}`,"content-type":`application/json; charset=utf-8`},body:JSON.stringify({trigger_id:t,view:o})});c.ok||log.error(`Slack views.open returned non-2xx`,{status:c.status})}async function handleViewSubmission(e,t,n){let r=new Response(null,{status:200});if(e.callbackId!==HITL_FREEFORM_MODAL_CALLBACK_ID)return r;let i;try{i=JSON.parse(e.privateMetadata??``)}catch{return log.warn(`freeform view_submission carries invalid private_metadata`),r}if(!i.continuationToken||!i.requestId||!i.messageTs||!i.channelId||!i.threadTs)return r;let a=e.values?.find(e=>e.blockId===HITL_FREEFORM_MODAL_BLOCK_ID&&e.actionId===HITL_FREEFORM_MODAL_ACTION_ID)?.value??``;if(a.length===0)return r;let u=e.user,d=e.userId,f=u?.teamId??e.teamId??null;return t.waitUntil(t.from(i.continuationToken).respond([{requestId:i.requestId,text:a}],{auth:buildSlackAuthContext({channelId:i.channelId,teamId:f,threadTs:i.threadTs,userId:d,userName:u?.username??u?.name})}).catch(e=>{log.error(`freeform answer delivery failed`,{error:e})})),t.waitUntil(updateAnsweredFreeformCard({channelId:i.channelId,messageTs:i.messageTs,answerLabel:a,userId:d??void 0,deps:n}).catch(e=>{log.error(`freeform answered-card update failed`,{error:e})})),r}async function updateAnsweredHitlCard(e,t){let n=e.actions.find(e=>isHitlAction(e.actionId));if(!n||!n.messageTs)return;let r=n.label??n.selectedOptionValue??n.value;if(!r)return;let a=buildAnsweredHitlMessageBlocks({actionId:n.actionId,answerLabel:r,messageBlocks:e.messageBlocks,userId:n.user.id}),o=await resolveSlackBotToken(t.config.credentials?.botToken),s=await fetch(`https://slack.com/api/chat.update`,{method:`POST`,headers:{authorization:`Bearer ${o}`,"content-type":`application/json; charset=utf-8`},body:JSON.stringify({channel:e.channelId,ts:n.messageTs,blocks:a,text:`Answered: ${r}`})});if(!s.ok)throw Error(`Slack chat.update returned HTTP ${s.status}`)}async function updateAnsweredFreeformCard(e){let t=buildAnsweredBlocks({promptBlocks:[],answerLabel:e.answerLabel,userId:e.userId}),n=await resolveSlackBotToken(e.deps.config.credentials?.botToken),r=await fetch(`https://slack.com/api/chat.update`,{method:`POST`,headers:{authorization:`Bearer ${n}`,"content-type":`application/json; charset=utf-8`},body:JSON.stringify({channel:e.channelId,ts:e.messageTs,blocks:t,text:`Answered: ${e.answerLabel}`})});if(!r.ok)throw Error(`Slack chat.update returned HTTP ${r.status}`)}export{handleInteractionPost,parseBlockActionsPayload};
1
+ import{createLogger}from"#internal/logging.js";import{SLACK_CARD_SUBTEXT_MAX_LENGTH,truncateCardSubtext}from"#public/channels/slack/limits.js";import{buildSlackBinding,resolveSlackBotToken,slackContinuationToken}from"#public/channels/slack/api.js";import{buildSlackAuthContext}from"#public/channels/slack/auth.js";import{HITL_FREEFORM_MODAL_ACTION_ID,HITL_FREEFORM_MODAL_BLOCK_ID,HITL_FREEFORM_MODAL_CALLBACK_ID,buildAnsweredBlocks,buildFreeformModalView,deriveHitlResponse,freeformRequestIdFromActionId,isFreeformAction,isHitlAction}from"#public/channels/slack/hitl.js";import{parseSlackWebhookBody}from"#compiled/@chat-adapter/slack/webhook.js";import{bindSlackSessionOperations}from"#public/channels/slack/session-operations.js";const log=createLogger(`slack.interactions`);function parseBlockActionsPayload(e){if(isSharedBlockActionsPayload(e))return parseSharedBlockActionsPayload(e);let t=e,n=t.actions;if(!Array.isArray(n))return null;let r=t.channel?.id,i=t.message,a=i?.thread_ts??i?.ts;if(!r||!a)return null;let o=t.team,s=t.user,c=o?.id??s.team_id,l={id:s.id,username:s.username,name:s.name},u=i?.blocks??[];return{actions:n.map(e=>({actionId:String(e.action_id??``),value:e.value==null?void 0:String(e.value),blockId:e.block_id==null?void 0:String(e.block_id),selectedOptionValue:extractSelectedOptionValue(e),messageTs:i?.ts,label:extractActionLabel(e),user:l})),channelId:r,threadTs:a,teamId:c,messageBlocks:u}}function isSharedBlockActionsPayload(e){return e.kind===`block_actions`&&Array.isArray(e.actions)}function parseSharedBlockActionsPayload(e){return!e.channelId||!e.threadTs?null:{actions:e.actions.map(t=>({actionId:t.actionId,value:t.value,blockId:t.blockId,selectedOptionValue:t.selectedOptionValue,messageTs:e.messageTs,label:t.label,user:{id:t.user?.id??e.userId,username:t.user?.username,name:t.user?.name}})),channelId:e.channelId,threadTs:e.threadTs,teamId:e.teamId,messageBlocks:e.messageBlocks??[]}}function extractSelectedOptionValue(e){let t=e.selected_option;return typeof t?.value==`string`?t.value:void 0}function extractActionLabel(e){let t=e.selected_option?.text?.text;if(typeof t==`string`&&t.length>0)return t;let n=e.text?.text;if(typeof n==`string`&&n.length>0)return n}function findPromptBlock(e){return findPromptBlocks(e)[0]}function findPromptBlocks(e){let t=[];for(let n of e){if(typeof n!=`object`||!n)continue;let e=n.type;if(e===`actions`)break;(e===`section`||e===`context`||e===`divider`||e===`image`)&&t.push(n)}return t}function readPromptTextFromBlocks(e){let t=findPromptBlock(e)?.text?.text;return typeof t==`string`&&t.length>0?t:void 0}function buildAnsweredHitlMessageBlocks(e){let t=findActionBlockIndex(e.messageBlocks,e.actionId);if(t===-1)return buildAnsweredBlocks({promptBlocks:findPromptBlocks(e.messageBlocks),answerLabel:e.answerLabel,userId:e.userId});let n=e.messageBlocks[t],r=answeredBlocksFromActionBlock({answerLabel:e.answerLabel,block:n,userId:e.userId})??buildAnsweredBlocks({promptBlocks:promptBlocksFromActionBlock(n),answerLabel:e.answerLabel,userId:e.userId});return[...e.messageBlocks.slice(0,t),...r,...e.messageBlocks.slice(t+1)]}function findActionBlockIndex(e,t){return e.findIndex(e=>blockContainsActionId(e,t))}function blockContainsActionId(e,t){return isObjectRecord(e)?actionsContainActionId(e.elements,t)||actionsContainActionId(e.actions,t):!1}function actionsContainActionId(e,t){return Array.isArray(e)?e.some(e=>isObjectRecord(e)&&e.action_id===t):!1}function isObjectRecord(e){return typeof e==`object`&&!!e}function answeredBlocksFromActionBlock(e){if(!isObjectRecord(e.block)||e.block.type!==`card`)return;let{actions:t,subtext:n,...r}=e.block,i={...r,subtext:{type:`mrkdwn`,text:formatAnsweredCardSubtext(e),verbatim:!1}};return hasCardContent(i)?[i]:void 0}function formatAnsweredCardSubtext(e){let r=e.userId.length>0?` by <@${e.userId}>`:``,i=SLACK_CARD_SUBTEXT_MAX_LENGTH-20-1-r.length;return truncateCardSubtext(`:white_check_mark: *${truncateWithEllipsis(e.answerLabel,i)}*${r}`)}function truncateWithEllipsis(e,t){if(t<=0)return``;if(e.length<=t)return e;let n=Math.max(0,t-3);return`${e.slice(0,n).trimEnd()}...`}function promptBlocksFromActionBlock(e){if(!isObjectRecord(e)||e.type!==`card`)return[];let{actions:t,...n}=e;return hasCardContent(n)?[n]:[]}function hasCardContent(e){return e.body!==void 0||e.title!==void 0||e.hero_image!==void 0}async function handleInteractionPost(e,t,n){let i=new Response(`ok`,{status:200}),s;try{s=parseSlackWebhookBody(e,{contentType:`application/x-www-form-urlencoded`})}catch{return log.warn(`failed to parse Slack interaction payload`),i}if(s.kind===`view_submission`)return handleViewSubmission(s,t,n);if(s.kind!==`block_actions`)return i;let c=parseBlockActionsPayload(s);if(!c)return i;let l=c.actions.find(e=>isFreeformAction(e.actionId));if(l)return await openFreeformModal({payload:s.raw,interaction:c,freeformAction:l,deps:n}),i;let u=slackContinuationToken(c.channelId,c.threadTs),d=c.actions.map(deriveHitlResponse).filter(e=>e!==null);if(d.length>0){let e=c.actions[0]?.user;if(!e)return i;t.waitUntil(t.from(u).respond(d,{auth:buildSlackAuthContext({channelId:c.channelId,teamId:c.teamId,threadTs:c.threadTs,userId:e.id,userName:e.username??e.name})}).catch(e=>{log.error(`HITL interaction delivery failed`,{error:e})})),t.waitUntil(updateAnsweredHitlCard(c,n).catch(e=>{log.error(`HITL answered-card update failed`,{error:e})}))}let p=n.config.onInteraction;if(p){let e=c.actions.filter(e=>!isHitlAction(e.actionId));if(e.length>0){let i=e[0].user,{thread:a,slack:s}=buildSlackBinding({botToken:n.config.credentials?.botToken,channelId:c.channelId,threadTs:c.threadTs,teamId:c.teamId}),l={...bindSlackSessionOperations({address:u,defaultAuth:buildSlackAuthContext({channelId:c.channelId,teamId:c.teamId,threadTs:c.threadTs,userId:i.id,userName:i.username??i.name}),from:t.from,resolveSession:t.resolveSession,state:{channelId:c.channelId,teamId:c.teamId??null,threadTs:c.threadTs,triggeringUserId:i.id}}),thread:a,slack:s};for(let n of e)t.waitUntil(Promise.resolve(p(n,l)).catch(e=>{log.error(`custom interaction handler failed`,{error:e})}))}}return i}async function openFreeformModal(e){let t=e.payload.trigger_id;if(typeof t!=`string`||t.length===0){log.warn(`freeform button click missing trigger_id — cannot open modal`);return}let n=freeformRequestIdFromActionId(e.freeformAction.actionId)??e.freeformAction.value;if(!n){log.warn(`freeform button click missing requestId`);return}let r=e.freeformAction.messageTs;if(!r){log.warn(`freeform button click missing messageTs`);return}let o=buildFreeformModalView({metadata:{continuationToken:slackContinuationToken(e.interaction.channelId,e.interaction.threadTs),channelId:e.interaction.channelId,threadTs:e.interaction.threadTs,messageTs:r,requestId:n},prompt:readPromptTextFromBlocks(e.interaction.messageBlocks)}),s=await resolveSlackBotToken(e.deps.config.credentials?.botToken),c=await fetch(`https://slack.com/api/views.open`,{method:`POST`,headers:{authorization:`Bearer ${s}`,"content-type":`application/json; charset=utf-8`},body:JSON.stringify({trigger_id:t,view:o})});c.ok||log.error(`Slack views.open returned non-2xx`,{status:c.status})}async function handleViewSubmission(e,t,n){let r=new Response(null,{status:200});if(e.callbackId!==HITL_FREEFORM_MODAL_CALLBACK_ID)return r;let i;try{i=JSON.parse(e.privateMetadata??``)}catch{return log.warn(`freeform view_submission carries invalid private_metadata`),r}if(!i.continuationToken||!i.requestId||!i.messageTs||!i.channelId||!i.threadTs)return r;let a=e.values?.find(e=>e.blockId===HITL_FREEFORM_MODAL_BLOCK_ID&&e.actionId===HITL_FREEFORM_MODAL_ACTION_ID)?.value??``;if(a.length===0)return r;let u=e.user,d=e.userId,f=u?.teamId??e.teamId??null;return t.waitUntil(t.from(i.continuationToken).respond([{requestId:i.requestId,text:a}],{auth:buildSlackAuthContext({channelId:i.channelId,teamId:f,threadTs:i.threadTs,userId:d,userName:u?.username??u?.name})}).then(()=>updateAnsweredFreeformCard({channelId:i.channelId,messageTs:i.messageTs,answerLabel:a,userId:d??void 0,deps:n})).catch(e=>{log.error(`freeform answer delivery or answered-card update failed`,{error:e})})),r}async function updateAnsweredHitlCard(e,t){let n=e.actions.find(e=>isHitlAction(e.actionId));if(!n||!n.messageTs)return;let r=n.label??n.selectedOptionValue??n.value;if(!r)return;let a=buildAnsweredHitlMessageBlocks({actionId:n.actionId,answerLabel:r,messageBlocks:e.messageBlocks,userId:n.user.id}),o=await resolveSlackBotToken(t.config.credentials?.botToken),s=await fetch(`https://slack.com/api/chat.update`,{method:`POST`,headers:{authorization:`Bearer ${o}`,"content-type":`application/json; charset=utf-8`},body:JSON.stringify({channel:e.channelId,ts:n.messageTs,blocks:a,text:`Answered: ${r}`})});if(!s.ok)throw Error(`Slack chat.update returned HTTP ${s.status}`)}async function updateAnsweredFreeformCard(e){let t=buildAnsweredBlocks({promptBlocks:[],answerLabel:e.answerLabel,userId:e.userId}),n=await resolveSlackBotToken(e.deps.config.credentials?.botToken),r=await fetch(`https://slack.com/api/chat.update`,{method:`POST`,headers:{authorization:`Bearer ${n}`,"content-type":`application/json; charset=utf-8`},body:JSON.stringify({channel:e.channelId,ts:e.messageTs,blocks:t,text:`Answered: ${e.answerLabel}`})});if(!r.ok)throw Error(`Slack chat.update returned HTTP ${r.status}`)}export{handleInteractionPost,parseBlockActionsPayload};
@@ -1,7 +1,7 @@
1
1
  import type { UserContent } from "ai";
2
2
  import type { ChannelResolveSession, ChannelSource } from "#channel/channel-operations.js";
3
3
  import type { Session } from "#channel/session.js";
4
- import type { SessionAuthContext, TurnPolicy } from "#channel/types.js";
4
+ import type { SessionAuthContext } from "#channel/types.js";
5
5
  import type { CardElement } from "#compiled/chat/index.js";
6
6
  import type { SessionContext } from "#public/definitions/callback-context.js";
7
7
  import type { ChannelContinuationOps } from "#public/definitions/channel.js";
@@ -90,6 +90,11 @@ type SlackSessionFailedHandler = (data: EventData<"session.failed">, channel: Sl
90
90
  * step boundaries. Anything written here must round-trip through
91
91
  * `JSON.stringify` / `JSON.parse`.
92
92
  */
93
+ export interface SlackPendingApprovalCard {
94
+ readonly messageBlocks: readonly unknown[];
95
+ readonly messageTs: string;
96
+ readonly userId?: string;
97
+ }
93
98
  export interface SlackChannelState {
94
99
  /** Slack channel id seeded by the inbound mention. */
95
100
  channelId: string | null;
@@ -127,6 +132,9 @@ export interface SlackChannelState {
127
132
  * resolution outcome.
128
133
  */
129
134
  pendingAuthMessageTs?: Record<string, string>;
135
+ pendingApprovalCards?: Record<string, SlackPendingApprovalCard>;
136
+ pendingApprovalCandidateUsers?: Record<string, string>;
137
+ approvalResponderUsers?: Record<string, string>;
130
138
  }
131
139
  /**
132
140
  * Per-session metadata attached to tracing spans, projected by the
@@ -330,6 +338,8 @@ export type SlackInboundResultOrPromise = SlackMentionResultOrPromise;
330
338
  * context and exposes the ID as `data.sessionId`.
331
339
  */
332
340
  export interface SlackChannelEvents {
341
+ readonly "approval.candidate"?: SlackEventHandler<"approval.candidate">;
342
+ readonly "approval.settled"?: SlackEventHandler<"approval.settled">;
333
343
  readonly "turn.started"?: SlackEventHandler<"turn.started">;
334
344
  readonly "actions.requested"?: SlackEventHandler<"actions.requested">;
335
345
  readonly "action.partial"?: SlackEventHandler<"action.partial">;
@@ -370,8 +380,6 @@ export interface SlackChannelConfig {
370
380
  readonly botName?: string;
371
381
  /** Override the default webhook route path (`/eve/v1/slack`). */
372
382
  readonly route?: string;
373
- /** Policy for accepted messages that arrive while a turn is active. */
374
- readonly turnPolicy?: TurnPolicy;
375
383
  /**
376
384
  * Inbound upload policy applied to file attachments before they reach
377
385
  * the harness. Violating attachments are dropped with a warning so the
@@ -1 +1 @@
1
- import{markEventHandled}from"./utils.js";import{createLogger,logError}from"#internal/logging.js";import{POST,defineChannel}from"#public/definitions/channel.js";import{mergeUploadPolicy}from"#public/channels/upload-policy.js";import{buildSlackBinding,buildSlackWorkspaceHandle,slackContinuationToken}from"#public/channels/slack/api.js";import{buildSlackAuthContext,slackUserIdFromAuthContext}from"#public/channels/slack/auth.js";import{defaultEvents,defaultInputRequestedHandler,defaultOnAppMention,defaultOnDirectMessage}from"#public/channels/slack/defaults.js";import{loadThreadContextMessages}from"#public/channels/slack/thread.js";import{parseSlackWebhookBody}from"#compiled/@chat-adapter/slack/webhook.js";import{bindSlackSessionOperations}from"#public/channels/slack/session-operations.js";import{buildSlackTurnMessage,collectInboundFileParts,createSlackFetchFile}from"#public/channels/slack/attachments.js";import{parseMessageEvent,parseSlackEventEnvelope,slackEventBotUserId,slackMessageFromWebhookPayload}from"#public/channels/slack/inbound.js";import{formatSlackInboundMessage,formatSlackThreadContext}from"#public/channels/slack/model-context.js";import{SLACK_CHANNEL_DEFAULT_ROUTE}from"#public/channels/slack/constants.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){let{thread:r,slack:i}=buildSlackBinding({botToken:n?.botToken,channelId:e.channelId??``,threadTs:e.threadTs??``,teamId:e.teamId??void 0,onThreadTsChanged(n){e.threadTs=n,e.channelId&&t.continuation?.rekey(slackContinuationToken(e.channelId,n))}});return{thread:r,slack:i,state:e}}function slackChannel(e={}){let t=mergeUploadPolicy(e.uploadPolicy),n=createSlackFetchFile({botToken:e.credentials?.botToken}),o=e.events?.[`authorization.required`],s=e.events?.[`turn.started`]??defaultEvents[`turn.started`],c={...defaultEvents,...e.events,async"turn.started"(e,t,n){let r=slackUserIdFromAuthContext(n.session.auth.current);r!==void 0&&(t.state.triggeringUserId=r),await s(e,t,n)},"input.requested":e.events?.[`input.requested`]??defaultInputRequestedHandler(),"authorization.required":o===void 0?defaultEvents[`authorization.required`]:constrainAuthorizationRequired(o)},l=new Set;return defineChannel({kindHint:`slack`,turnPolicy:e.turnPolicy,state:{channelId:null,threadTs:null,teamId:null,triggeringUserId:null,pendingToolCallMessage:null,lastReasoningTypingAtMs:null,lastReasoningTypingStatus:null,pendingAuthMessageTs:{}},fetchFile:n,metadata(e){return{channelId:e.channelId,teamId:e.teamId,threadTs:e.threadTs,triggeringUserId:e.triggeringUserId??null}},context(t,n){return rebuildSlackContext(t,n,e.credentials)},routes:[POST(e.route??SLACK_CHANNEL_DEFAULT_ROUTE,async(n,r)=>{let{waitUntil:i}=r,{from:a,resolveSession:o}=r,s=await verifyInbound(n,e.credentials);return s===null?new Response(`unauthorized`,{status:401}):shouldDropSlackHttpTimeoutRetry(n.headers)?new Response(`ok`):(n.headers.get(`content-type`)??``).includes(`application/x-www-form-urlencoded`)?handleInteractionPost(s,{from:a,resolveSession:o,waitUntil:i},{config:e}):handleEventPost({body:s,from:a,resolveSession:o,waitUntil:i,config:e,uploadPolicy:t,handledEvents:l,headers:n.headers})})],receive(t,{from:n}){return receiveOnSlack(t,{from:n,credentials:e.credentials})},events:c})}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=n.initialMessage;if(a&&i.length>0)throw Error("slackChannel().receive: `threadTs` and `initialMessage` are mutually exclusive.");let s=i;if(a){let{thread:e}=buildSlackBinding({botToken:t.credentials?.botToken,channelId:r,threadTs:``,teamId:t.teamId}),n={card:a.card};a.fallbackText!==void 0&&(n.fallbackText=a.fallbackText),s=(await e.post(n)).id}let l=s||crypto.randomUUID();return t.from(slackContinuationToken(r,l)).send(e.message,{auth:e.auth,state:{channelId:r,threadTs:s||null,teamId:t.teamId??null,triggeringUserId:t.triggeringUserId??null}})}function constrainAuthorizationRequired(e){return(t,n,r)=>e(t,{postEphemeral:(e,t)=>n.thread.postEphemeral(e,t),postDirectMessage:(e,t)=>n.thread.postDirectMessage(e,t),state:n.state},r)}function shouldDropSlackHttpTimeoutRetry(e){return Number(e.get(`x-slack-retry-num`)??`0`)>=1&&e.get(`x-slack-retry-reason`)===`http_timeout`}async function handleEventPost(t){let{config:n}=t,r,i;try{r=parseSlackWebhookBody(t.body,{headers:t.headers}),i=parseSlackEventEnvelope(t.body)}catch(e){return log.warn(`inbound webhook body is not valid JSON`,{error:e}),new Response(`ok`)}if(r.kind===`url_verification`)return new Response(r.challenge,{status:200,headers:{"content-type":`text/plain`}});if(i===null)return new Response(`ok`);let a=typeof i.api_app_id==`string`?i.api_app_id:void 0,o=slackEventBotUserId(i),dispatch=null,s=null;if(r.kind===`app_mention`||r.kind===`direct_message`){let e=r.kind,i=slackMessageFromWebhookPayload(r);if(i!==null&&!isSelfAuthoredSlackMessage({appId:a,botUserId:o},i)){let dispatchMessageWith=r=>()=>dispatchSlackMessage({appId:a,botUserId:o,from:t.from,resolveSession:t.resolveSession,credentials:n.credentials,handler:r,kind:e,message:i,threadContext:n.threadContext,uploadPolicy:t.uploadPolicy}),r=(e===`app_mention`?n.onAppMention:n.onDirectMessage)??n.onMessage;r===void 0?s=dispatchMessageWith(e===`app_mention`?defaultOnAppMention:defaultOnDirectMessage):dispatch=()=>dispatchSlackMessage({appId:a,botUserId:o,from:t.from,resolveSession:t.resolveSession,credentials:n.credentials,handler:r,kind:e,message:i,threadContext:n.threadContext,uploadPolicy:t.uploadPolicy})}}if(dispatch===null&&n.onMessage!==void 0){let e=parseMessageEvent(i);e!==null&&!isSelfAuthoredSlackMessage({appId:a,botUserId:o},e)&&(o===void 0||!e.text.includes(`<@${o}`))&&(dispatch=()=>dispatchSlackMessage({appId:a,botUserId:o,from:t.from,resolveSession:t.resolveSession,credentials:n.credentials,handler:n.onMessage,kind:`channel_message`,message:e,threadContext:n.threadContext,uploadPolicy:t.uploadPolicy}))}let c=n.onEvent;if(dispatch===null&&c!==void 0&&(dispatch=()=>dispatchSlackEvent({from:t.from,resolveSession:t.resolveSession,credentials:n.credentials,envelope:i,handler:c})),dispatch??=s,dispatch===null)return new Response(`ok`);let l=i.event_id;if(l){if(t.handledEvents.has(l))return log.warn(`received a duplicate event`,{event_id:l,event_time:i.event_time,retry_num:r.retry?.num??`(null)`,retry_reason:r.retry?.reason??`(null)`}),new Response(`ok`);markEventHandled(l,t.handledEvents)}return t.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:r,slack:i}=buildSlackBinding({appId:e.appId,botToken:e.credentials?.botToken,botUserId:e.botUserId,channelId:e.message.channelId,threadTs:e.message.threadTs,teamId:e.message.teamId}),a=e.message.author,s=bindSlackSessionOperations({address:t,defaultAuth:a===void 0?null:buildSlackAuthContext({channelId:e.message.channelId,fullName:a.fullName,isBot:a.isBot,teamId:e.message.teamId,threadTs:e.message.threadTs,userId:a.userId,userName:a.userName}),from:e.from,resolveSession:e.resolveSession,state:{channelId:e.message.channelId,teamId:e.message.teamId??null,threadTs:e.message.threadTs,triggeringUserId:a?.userId??null}}),u={...s,isBotMentioned:()=>e.kind===`app_mention`||e.botUserId!==void 0&&e.message.text.includes(`<@${e.botUserId}`),isSubscribed:async()=>await s.resolveSession()!==void 0,slack:i,thread:r},d;try{d=await e.handler(u,e.message)}catch(t){logError(log,`${e.kind} handler failed`,t,{channelId:e.message.channelId});return}d!=null&&await deliverSlackMessage({credentials:e.credentials,kind:e.kind,message:e.message,result:d,sessionOperations:s,thread:r,threadContext:e.threadContext,uploadPolicy:e.uploadPolicy})}async function dispatchSlackEvent(e){let t=e.envelope.event.team_id,r=typeof t==`string`?t:typeof e.envelope.team_id==`string`?e.envelope.team_id:void 0,i=[],sourceFor=t=>e.from(slackContinuationToken(t.channelId,t.threadTs)),a={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:(e,{auth:t,target:n})=>sourceFor(n).respond(e,{auth:t}),send:(t,{auth:n,target:i})=>receiveOnSlack({auth:n,message:t,target:i},{from:e.from,credentials:e.credentials,teamId:r,...typeof e.envelope.event.user==`string`?{triggeringUserId:e.envelope.event.user}:{}}),slack:buildSlackWorkspaceHandle({botToken:e.credentials?.botToken,teamId:r}),waitUntil(e){i.push(e)}};try{await e.handler(a,e.envelope.event)}catch(t){logError(log,`event handler failed`,t,{eventId:e.envelope.event_id,eventType:e.envelope.event.type})}await Promise.allSettled(i)}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:r}=e;try{let n=formatSlackThreadContext(e.threadContext===void 0?[]:await loadThreadContextMessages(r,t,e.threadContext)),i=await collectInboundFileParts({mention:t,thread:r,policy:e.uploadPolicy}),a=formatSlackInboundMessage({channelId:t.channelId,fullName:t.author?.fullName,teamId:t.teamId,threadTs:t.threadTs,userId:t.author?.userId??``,userName:t.author?.userName},t),o=buildSlackTurnMessage(n===void 0?a:`${n}\n\n${a}`,i),s=e.result.context??[],c=s.length===0?{auth:e.result.auth,title:t.markdown}:{auth:e.result.auth,context:s,title:t.markdown};await e.sessionOperations.send(o,c)}catch(r){logError(log,`${e.kind} delivery failed`,r,{channelId:t.channelId})}}export{constrainAuthorizationRequired,slackChannel};
1
+ import{markEventHandled}from"./utils.js";import{createLogger,logError}from"#internal/logging.js";import{defaultDeliverResult}from"#channel/adapter.js";import{POST,defineChannel}from"#public/definitions/channel.js";import{mergeUploadPolicy}from"#public/channels/upload-policy.js";import{buildSlackBinding,buildSlackWorkspaceHandle,slackContinuationToken}from"#public/channels/slack/api.js";import{buildSlackAuthContext,slackUserIdFromAuthContext}from"#public/channels/slack/auth.js";import{defaultEvents,defaultInputRequestedHandler,defaultOnAppMention,defaultOnDirectMessage}from"#public/channels/slack/defaults.js";import{loadThreadContextMessages}from"#public/channels/slack/thread.js";import{parseSlackWebhookBody}from"#compiled/@chat-adapter/slack/webhook.js";import{bindSlackSessionOperations}from"#public/channels/slack/session-operations.js";import{buildSlackTurnMessage,collectInboundFileParts,createSlackFetchFile}from"#public/channels/slack/attachments.js";import{parseMessageEvent,parseSlackEventEnvelope,slackEventBotUserId,slackMessageFromWebhookPayload}from"#public/channels/slack/inbound.js";import{formatSlackInboundMessage,formatSlackThreadContext}from"#public/channels/slack/model-context.js";import{SLACK_CHANNEL_DEFAULT_ROUTE}from"#public/channels/slack/constants.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){let{thread:r,slack:i}=buildSlackBinding({botToken:n?.botToken,channelId:e.channelId??``,threadTs:e.threadTs??``,teamId:e.teamId??void 0,onThreadTsChanged(n){e.threadTs=n,e.channelId&&t.continuation?.rekey(slackContinuationToken(e.channelId,n))}});return{thread:r,slack:i,state:e}}function slackChannel(e={}){let t=mergeUploadPolicy(e.uploadPolicy),n=createSlackFetchFile({botToken:e.credentials?.botToken}),s=e.events?.[`authorization.required`],c=e.events?.[`approval.candidate`]??defaultEvents[`approval.candidate`],l=e.events?.[`turn.started`]??defaultEvents[`turn.started`],u={...defaultEvents,...e.events,async"approval.candidate"(e,t,n){let r=t.state.approvalResponderUsers?.[e.responderPrincipalId];if(e.outcome===`pending`&&r!==void 0&&(t.state.pendingApprovalCandidateUsers={...t.state.pendingApprovalCandidateUsers,[e.candidateId]:r}),await c(e,t,n),e.outcome!==`pending`){let n={...t.state.pendingApprovalCandidateUsers};delete n[e.candidateId],t.state.pendingApprovalCandidateUsers=n}},async"turn.started"(e,t,n){let r=slackUserIdFromAuthContext(n.session.auth.current);r!==void 0&&(t.state.triggeringUserId=r),await l(e,t,n)},"input.requested":e.events?.[`input.requested`]??defaultInputRequestedHandler(),"authorization.required":s===void 0?defaultEvents[`authorization.required`]:constrainAuthorizationRequired(s)},f=new Set;return defineChannel({kindHint:`slack`,state:{channelId:null,threadTs:null,teamId:null,triggeringUserId:null,pendingToolCallMessage:null,lastReasoningTypingAtMs:null,lastReasoningTypingStatus:null,pendingAuthMessageTs:{},pendingApprovalCards:{},pendingApprovalCandidateUsers:{},approvalResponderUsers:{}},fetchFile:n,metadata(e){return{channelId:e.channelId,teamId:e.teamId,threadTs:e.threadTs,triggeringUserId:e.triggeringUserId??null}},context(t,n){return rebuildSlackContext(t,n,e.credentials)},deliver(e,t){let n=e.pendingApprovalCards;typeof n==`object`&&n&&(t.state.pendingApprovalCards={...t.state.pendingApprovalCards,...n});let i=e.approvalResponderUsers;return typeof i==`object`&&i&&(t.state.approvalResponderUsers={...t.state.approvalResponderUsers,...i}),defaultDeliverResult(e)},routes:[POST(e.route??SLACK_CHANNEL_DEFAULT_ROUTE,async(n,r)=>{let{waitUntil:i}=r,{from:a,resolveSession:o}=r,s=await verifyInbound(n,e.credentials);return s===null?new Response(`unauthorized`,{status:401}):shouldDropSlackHttpTimeoutRetry(n.headers)?new Response(`ok`):(n.headers.get(`content-type`)??``).includes(`application/x-www-form-urlencoded`)?handleInteractionPost(s,{from:a,resolveSession:o,waitUntil:i},{config:e}):handleEventPost({body:s,from:a,resolveSession:o,waitUntil:i,config:e,uploadPolicy:t,handledEvents:f,headers:n.headers})})],receive(t,{from:n}){return receiveOnSlack(t,{from:n,credentials:e.credentials})},events:u})}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=n.initialMessage;if(a&&i.length>0)throw Error("slackChannel().receive: `threadTs` and `initialMessage` are mutually exclusive.");let o=i;if(a){let{thread:e}=buildSlackBinding({botToken:t.credentials?.botToken,channelId:r,threadTs:``,teamId:t.teamId}),n={card:a.card};a.fallbackText!==void 0&&(n.fallbackText=a.fallbackText),o=(await e.post(n)).id}let c=o||crypto.randomUUID();return t.from(slackContinuationToken(r,c)).send(e.message,{auth:e.auth,state:{channelId:r,threadTs:o||null,teamId:t.teamId??null,triggeringUserId:t.triggeringUserId??null}})}function constrainAuthorizationRequired(e){return(t,n,r)=>e(t,{postEphemeral:(e,t)=>n.thread.postEphemeral(e,t),postDirectMessage:(e,t)=>n.thread.postDirectMessage(e,t),state:n.state},r)}function shouldDropSlackHttpTimeoutRetry(e){return Number(e.get(`x-slack-retry-num`)??`0`)>=1&&e.get(`x-slack-retry-reason`)===`http_timeout`}async function handleEventPost(t){let{config:n}=t,r,i;try{r=parseSlackWebhookBody(t.body,{headers:t.headers}),i=parseSlackEventEnvelope(t.body)}catch(e){return log.warn(`inbound webhook body is not valid JSON`,{error:e}),new Response(`ok`)}if(r.kind===`url_verification`)return new Response(r.challenge,{status:200,headers:{"content-type":`text/plain`}});if(i===null)return new Response(`ok`);let a=typeof i.api_app_id==`string`?i.api_app_id:void 0,o=slackEventBotUserId(i),dispatch=null,s=null;if(r.kind===`app_mention`||r.kind===`direct_message`){let e=r.kind,i=slackMessageFromWebhookPayload(r);if(i!==null&&!isSelfAuthoredSlackMessage({appId:a,botUserId:o},i)){let dispatchMessageWith=r=>()=>dispatchSlackMessage({appId:a,botUserId:o,from:t.from,resolveSession:t.resolveSession,credentials:n.credentials,handler:r,kind:e,message:i,threadContext:n.threadContext,uploadPolicy:t.uploadPolicy}),r=(e===`app_mention`?n.onAppMention:n.onDirectMessage)??n.onMessage;r===void 0?s=dispatchMessageWith(e===`app_mention`?defaultOnAppMention:defaultOnDirectMessage):dispatch=()=>dispatchSlackMessage({appId:a,botUserId:o,from:t.from,resolveSession:t.resolveSession,credentials:n.credentials,handler:r,kind:e,message:i,threadContext:n.threadContext,uploadPolicy:t.uploadPolicy})}}if(dispatch===null&&n.onMessage!==void 0){let e=parseMessageEvent(i);e!==null&&!isSelfAuthoredSlackMessage({appId:a,botUserId:o},e)&&(o===void 0||!e.text.includes(`<@${o}`))&&(dispatch=()=>dispatchSlackMessage({appId:a,botUserId:o,from:t.from,resolveSession:t.resolveSession,credentials:n.credentials,handler:n.onMessage,kind:`channel_message`,message:e,threadContext:n.threadContext,uploadPolicy:t.uploadPolicy}))}let c=n.onEvent;if(dispatch===null&&c!==void 0&&(dispatch=()=>dispatchSlackEvent({from:t.from,resolveSession:t.resolveSession,credentials:n.credentials,envelope:i,handler:c})),dispatch??=s,dispatch===null)return new Response(`ok`);let l=i.event_id;if(l){if(t.handledEvents.has(l))return log.warn(`received a duplicate event`,{event_id:l,event_time:i.event_time,retry_num:r.retry?.num??`(null)`,retry_reason:r.retry?.reason??`(null)`}),new Response(`ok`);markEventHandled(l,t.handledEvents)}return t.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:r,slack:i}=buildSlackBinding({appId:e.appId,botToken:e.credentials?.botToken,botUserId:e.botUserId,channelId:e.message.channelId,threadTs:e.message.threadTs,teamId:e.message.teamId}),a=e.message.author,o=bindSlackSessionOperations({address:t,defaultAuth:a===void 0?null:buildSlackAuthContext({channelId:e.message.channelId,fullName:a.fullName,isBot:a.isBot,teamId:e.message.teamId,threadTs:e.message.threadTs,userId:a.userId,userName:a.userName}),from:e.from,resolveSession:e.resolveSession,state:{channelId:e.message.channelId,teamId:e.message.teamId??null,threadTs:e.message.threadTs,triggeringUserId:a?.userId??null}}),c={...o,isBotMentioned:()=>e.kind===`app_mention`||e.botUserId!==void 0&&e.message.text.includes(`<@${e.botUserId}`),isSubscribed:async()=>await o.resolveSession()!==void 0,slack:i,thread:r},d;try{d=await e.handler(c,e.message)}catch(t){logError(log,`${e.kind} handler failed`,t,{channelId:e.message.channelId});return}d!=null&&await deliverSlackMessage({credentials:e.credentials,kind:e.kind,message:e.message,result:d,sessionOperations:o,thread:r,threadContext:e.threadContext,uploadPolicy:e.uploadPolicy})}async function dispatchSlackEvent(e){let t=e.envelope.event.team_id,r=typeof t==`string`?t:typeof e.envelope.team_id==`string`?e.envelope.team_id:void 0,i=[],sourceFor=t=>e.from(slackContinuationToken(t.channelId,t.threadTs)),a={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:(e,{auth:t,target:n})=>sourceFor(n).respond(e,{auth:t}),send:(t,{auth:n,target:i})=>receiveOnSlack({auth:n,message:t,target:i},{from:e.from,credentials:e.credentials,teamId:r,...typeof e.envelope.event.user==`string`?{triggeringUserId:e.envelope.event.user}:{}}),slack:buildSlackWorkspaceHandle({botToken:e.credentials?.botToken,teamId:r}),waitUntil(e){i.push(e)}};try{await e.handler(a,e.envelope.event)}catch(t){logError(log,`event handler failed`,t,{eventId:e.envelope.event_id,eventType:e.envelope.event.type})}await Promise.allSettled(i)}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:r}=e;try{let n=formatSlackThreadContext(e.threadContext===void 0?[]:await loadThreadContextMessages(r,t,e.threadContext)),i=await collectInboundFileParts({mention:t,thread:r,policy:e.uploadPolicy}),a=formatSlackInboundMessage({channelId:t.channelId,fullName:t.author?.fullName,teamId:t.teamId,threadTs:t.threadTs,userId:t.author?.userId??``,userName:t.author?.userName},t),o=buildSlackTurnMessage(n===void 0?a:`${n}\n\n${a}`,i),s=e.result.context??[],c=s.length===0?{auth:e.result.auth,title:t.markdown}:{auth:e.result.auth,context:s,title:t.markdown};await e.sessionOperations.send(o,c)}catch(r){logError(log,`${e.kind} delivery failed`,r,{channelId:t.channelId})}}export{constrainAuthorizationRequired,slackChannel};
@@ -1,17 +1,14 @@
1
+ import type { SessionAuthContext } from "#channel/types.js";
2
+ import type { SessionParent, SessionTurn } from "#context/keys.js";
3
+ import type { ToolAuthOptions, ToolAuthProvider } from "#public/definitions/tool.js";
1
4
  import type { SessionContext } from "#public/definitions/callback-context.js";
5
+ import type { TokenResult } from "#runtime/connections/types.js";
2
6
  type ApprovalToolInput<TInput> = TInput extends object ? Readonly<TInput> : TInput;
3
7
  /**
4
- * Context passed to an {@link Approval} function.
8
+ * Context passed to an {@link ApprovalPolicy} function.
5
9
  *
6
10
  * Extends {@link SessionContext} so approval policies can make decisions from
7
11
  * the active session, current caller, and turn.
8
- *
9
- * `approvedTools` is the set of tool names (or compound approval keys)
10
- * already approved at least once in the current session. `toolName` is the
11
- * runtime name of the tool being evaluated. `toolInput` is the raw input the
12
- * model passed, available for input-aware decisions. `callId` is the id of
13
- * the call being evaluated — the same `callId` carried by the call's stream
14
- * events and its `execute` context.
15
12
  */
16
13
  export interface ApprovalContext<TInput = Record<string, unknown>> extends SessionContext {
17
14
  readonly approvedTools: ReadonlySet<string>;
@@ -19,12 +16,7 @@ export interface ApprovalContext<TInput = Record<string, unknown>> extends Sessi
19
16
  readonly toolInput?: ApprovalToolInput<TInput>;
20
17
  readonly toolName: string;
21
18
  }
22
- /**
23
- * Approval decision returned by an {@link Approval} function.
24
- *
25
- * AI SDK 7 statuses are accepted directly. For compatibility, `true` maps to
26
- * `"user-approval"` and `false` maps to `"not-applicable"`.
27
- */
19
+ /** Request-time approval decision returned by an {@link ApprovalPolicy}. */
28
20
  export type ApprovalStatus = undefined | boolean | "not-applicable" | "approved" | "denied" | "user-approval" | {
29
21
  readonly type: "not-applicable";
30
22
  readonly reason?: never;
@@ -38,6 +30,55 @@ export type ApprovalStatus = undefined | boolean | "not-applicable" | "approved"
38
30
  readonly type: "user-approval";
39
31
  readonly reason?: never;
40
32
  };
41
- /** Shared approval policy used by authored tools and connections. */
42
- export type Approval<TInput = Record<string, unknown>> = (ctx: ApprovalContext<TInput>) => ApprovalStatus | Promise<ApprovalStatus>;
33
+ /** Request-time approval policy shared by authored tools and connections. */
34
+ export type ApprovalPolicy<TInput = Record<string, unknown>> = (ctx: ApprovalContext<TInput>) => ApprovalStatus | Promise<ApprovalStatus>;
35
+ /** Stable tool request passed to a response authorizer. */
36
+ export interface ApprovalRequest<TInput = Record<string, unknown>> {
37
+ readonly callId: string;
38
+ readonly requestId: string;
39
+ readonly toolInput?: ApprovalToolInput<TInput>;
40
+ readonly toolName: string;
41
+ }
42
+ /** Read-only session identity and lineage available to a response authorizer. */
43
+ export interface ApprovalResponseSession {
44
+ readonly id: string;
45
+ readonly initiator: SessionAuthContext | null;
46
+ readonly parent?: SessionParent;
47
+ readonly turn: SessionTurn;
48
+ }
49
+ /** Narrow authorization capability available while validating a responder. */
50
+ export interface ApprovalResponseAuth {
51
+ getToken(provider: ToolAuthProvider, options?: ToolAuthOptions): Promise<TokenResult>;
52
+ requireAuth(provider: ToolAuthProvider, options?: ToolAuthOptions): never;
53
+ }
54
+ /** Submitted decision passed to an approval response policy. */
55
+ export interface ApprovalResponse {
56
+ readonly decision: "approve";
57
+ }
58
+ /** Context passed to an approval response policy. */
59
+ export interface ApprovalResponseContext<TInput = Record<string, unknown>> {
60
+ readonly auth: ApprovalResponseAuth;
61
+ readonly request: ApprovalRequest<TInput>;
62
+ readonly response: ApprovalResponse;
63
+ readonly responder: SessionAuthContext;
64
+ readonly session: ApprovalResponseSession;
65
+ }
66
+ /** Response policy decision. Rejection keeps the shared request pending. */
67
+ export type ApprovalResponseDecision = {
68
+ readonly status: "allowed";
69
+ } | {
70
+ readonly reason: string;
71
+ readonly status: "rejected";
72
+ };
73
+ /** Decides whether an authenticated responder may approve one request. */
74
+ export type ApprovalResponsePolicy<TInput = Record<string, unknown>> = (ctx: ApprovalResponseContext<TInput>) => ApprovalResponseDecision | Promise<ApprovalResponseDecision>;
75
+ /** Approval definition with request- and response-time policy. */
76
+ export interface ApprovalConfiguration<TInput = Record<string, unknown>> {
77
+ readonly request: ApprovalPolicy<TInput>;
78
+ readonly response?: ApprovalResponsePolicy<TInput>;
79
+ }
80
+ /** Shared approval definition used by authored tools and connections. */
81
+ export type Approval<TInput = Record<string, unknown>> = ApprovalPolicy<TInput> | ApprovalConfiguration<TInput>;
82
+ /** Returns the request-time policy from either approval authoring shape. */
83
+ export declare function resolveApprovalPolicy<TInput>(approval: Approval<TInput>): ApprovalPolicy<TInput>;
43
84
  export {};
@@ -1 +1 @@
1
- export{};
1
+ function resolveApprovalPolicy(e){return typeof e==`function`?e:e.request}export{resolveApprovalPolicy};
@@ -3,7 +3,6 @@ import { type ChannelCorsOptions } from "#channel/cors.js";
3
3
  import type { ChannelFrom, ChannelReceiveContext, ChannelResolveSession, ChannelRespondOptions, ChannelSendOptions, ChannelSource } from "#channel/channel-operations.js";
4
4
  import type { RouteDefinition } from "#channel/routes.js";
5
5
  import type { Session } from "#channel/session.js";
6
- import type { TurnPolicy } from "#channel/types.js";
7
6
  import type { UnstampedMessageStreamEvent } from "#protocol/message.js";
8
7
  import type { SessionContext } from "#public/definitions/callback-context.js";
9
8
  import type { GenericChannelDefinition, GenericReceiveInput } from "#shared/channel-definition.js";
@@ -111,6 +110,8 @@ type ChannelSessionFailedHandler<TCtx> = (data: EventData<"session.failed">, cha
111
110
  * and the channel context, with no `ctx`; its data includes `sessionId`.
112
111
  */
113
112
  export interface ChannelEvents<TCtx = void> {
113
+ readonly "approval.candidate"?: ChannelEventHandler<"approval.candidate", TCtx>;
114
+ readonly "approval.settled"?: ChannelEventHandler<"approval.settled", TCtx>;
114
115
  readonly "context.cleared"?: ChannelEventHandler<"context.cleared", TCtx>;
115
116
  readonly "compaction.requested"?: ChannelEventHandler<"compaction.requested", TCtx>;
116
117
  readonly "compaction.completed"?: ChannelEventHandler<"compaction.completed", TCtx>;
@@ -161,7 +162,6 @@ export interface Channel<TState = undefined, TReceiveTarget = Record<string, unk
161
162
  readonly routes: readonly RouteDefinition<TState>[];
162
163
  readonly cors?: ChannelCorsOptions;
163
164
  readonly receive?: (input: ReceiveInput<TReceiveTarget>, ctx: ChannelReceiveContext<TState>) => Promise<Session>;
164
- readonly turnPolicy?: TurnPolicy;
165
165
  }
166
166
  /**
167
167
  * Extracts the metadata projection type (`TMetadata`) from a {@link Channel}.
@@ -1 +1 @@
1
- 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,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(t){let n=buildAdapter(t),i=normalizeChannelCors(t.cors);return{__kind:CHANNEL_SENTINEL,routes:t.routes,adapter:n,cors:i,receive:t.receive,turnPolicy:t.turnPolicy}}const eventTypes=Object.keys({"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,"input.requested":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 r=e.state!=null,a=e.context!=null,o=e.fetchFile!==void 0,s=e.metadata,c=r||a||s!==void 0,l={},u=!1,d=e.events;for(let e of eventTypes){let t=d?.[e];t&&(u=!0,l[e]=(r,i)=>{let{session:a,...o}=i,s={...o,continuation:a?.continuation===void 0?void 0:{token:a.continuation.token,rekey:e=>a.continuation?.rekey(e)}};if(e===`session.failed`)return t(r,s);let c=buildCallbackContext();return t(r,s,c)})}return!c&&!u&&!o?{kind:e.kindHint??HTTP_ADAPTER_KIND}:{kind:e.kindHint??`defineChannel`,state:r?{...e.state}:{},fetchFile:e.fetchFile,instrumentation:s===void 0?void 0:{metadata(e){return s(e)}},createAdapterContext(t){let n=t.state,r=t.session;return{...a?e.context(n,r):{},state:n,ctx:t.ctx,session:r}},deliver(e){return defaultDeliverResult(e)},...l}}export{DELETE,GET,PATCH,POST,PUT,WS,defineChannel,disableRoute,isDisabledRouteSentinel};
1
+ 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,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(t){let n=buildAdapter(t),i=normalizeChannelCors(t.cors);return{__kind:CHANNEL_SENTINEL,routes:t.routes,adapter:n,cors:i,receive:t.receive}}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,"input.requested":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 r=e.state!=null,a=e.context!=null,o=e.fetchFile!==void 0,s=e.metadata,c=r||a||s!==void 0,l={},u=!1,d=e.events;for(let e of eventTypes){let t=d?.[e];t&&(u=!0,l[e]=(r,i)=>{let{session:a,...o}=i,s={...o,continuation:a?.continuation===void 0?void 0:{token:a.continuation.token,rekey:e=>a.continuation?.rekey(e)}};if(e===`session.failed`)return t(r,s);let c=buildCallbackContext();return t(r,s,c)})}return!c&&!u&&!o?{kind:e.kindHint??HTTP_ADAPTER_KIND}:{kind:e.kindHint??`defineChannel`,state:r?{...e.state}:{},fetchFile:e.fetchFile,instrumentation:s===void 0?void 0:{metadata(e){return s(e)}},createAdapterContext(t){let n=t.state,r=t.session;return{...a?e.context(n,r):{},state:n,ctx:t.ctx,session:r}},deliver(n,r){return e.deliver===void 0?defaultDeliverResult(n):e.deliver(n,r)},...l}}export{DELETE,GET,PATCH,POST,PUT,WS,defineChannel,disableRoute,isDisabledRouteSentinel};
@@ -1,7 +1,7 @@
1
- import type { MessageStreamEvent } from "../../protocol/message.js";
1
+ import type { HandleMessageStreamEvent } from "../../protocol/message.js";
2
2
  import type { SessionContext } from "./callback-context.js";
3
3
  import type { ExactDefinition } from "./exact.js";
4
- type ProtocolEvent<TType extends MessageStreamEvent["type"]> = Extract<MessageStreamEvent, {
4
+ type ProtocolEvent<TType extends HandleMessageStreamEvent["type"]> = Extract<HandleMessageStreamEvent, {
5
5
  type: TType;
6
6
  }>;
7
7
  /**
@@ -14,6 +14,8 @@ type ProtocolEvent<TType extends MessageStreamEvent["type"]> = Extract<MessageSt
14
14
  export interface HookEventMap {
15
15
  readonly "action.partial": ProtocolEvent<"action.partial">;
16
16
  readonly "action.result": ProtocolEvent<"action.result">;
17
+ readonly "approval.candidate": ProtocolEvent<"approval.candidate">;
18
+ readonly "approval.settled": ProtocolEvent<"approval.settled">;
17
19
  readonly "actions.requested": ProtocolEvent<"actions.requested">;
18
20
  readonly "authorization.completed": ProtocolEvent<"authorization.completed">;
19
21
  readonly "authorization.required": ProtocolEvent<"authorization.required">;
@@ -1,15 +1,25 @@
1
+ import { type DynamicResolveContext, type DynamicSentinel } from "#shared/dynamic-tool-definition.js";
1
2
  import type { ExactDefinition } from "#public/definitions/exact.js";
2
3
  import type { PublicInstructionsDefinition } from "#shared/instructions-definition.js";
3
4
  export type InstructionsDefinition = Readonly<PublicInstructionsDefinition>;
4
5
  /**
5
- * Defines an instructions prompt in TypeScript from a `{ markdown }`
6
- * definition.
6
+ * Defines instructions in TypeScript from a `{ content, role? }`
7
+ * definition. Omitted `role` defaults to `"system"`.
7
8
  *
8
9
  * Use it to return instructions from a `defineDynamic` resolver in
9
- * `agent/instructions/`; the returned markdown lowers to a single
10
- * `{ role: "system" }` message. For a fixed prompt with no resolver,
10
+ * `agent/instructions/`. For a fixed prompt with no resolver,
11
11
  * author `instructions.md` instead. The result is branded so the dynamic
12
12
  * instruction lifecycle can validate that a resolver return came through
13
13
  * this helper.
14
14
  */
15
15
  export declare function defineInstructions<TInstructions extends InstructionsDefinition>(definition: ExactDefinition<TInstructions, InstructionsDefinition>): TInstructions;
16
+ export type DynamicInstructionsResult = InstructionsDefinition | null;
17
+ export type DynamicInstructionsEvents = {
18
+ readonly [K in "session.started" | "turn.started"]?: (event: unknown, ctx: DynamicResolveContext) => DynamicInstructionsResult | Promise<DynamicInstructionsResult>;
19
+ };
20
+ /**
21
+ * Defines a runtime instructions resolver for session and turn boundaries.
22
+ */
23
+ export declare function defineDynamic<const TEvents extends DynamicInstructionsEvents>(definition: {
24
+ readonly events: ExactDefinition<TEvents, DynamicInstructionsEvents>;
25
+ }): DynamicSentinel<DynamicInstructionsResult>;
@@ -1 +1 @@
1
- import{INSTRUCTIONS_BRAND}from"#shared/dynamic-tool-definition.js";function defineInstructions(e){return Object.assign(e,{[INSTRUCTIONS_BRAND]:!0}),e}export{defineInstructions};
1
+ import{DYNAMIC_SENTINEL_KIND,INSTRUCTIONS_BRAND}from"#shared/dynamic-tool-definition.js";import{stampDefinitionKey}from"#public/tool-result-narrowing.js";function defineInstructions(e){return Object.assign(e,{[INSTRUCTIONS_BRAND]:!0}),e}function defineDynamic(t){let n={kind:DYNAMIC_SENTINEL_KIND,events:t.events};return stampDefinitionKey(n,`dynamic-instructions:${Object.keys(t.events).join(`,`)}`),n}export{defineDynamic,defineInstructions};