experimental-ash 0.27.0 → 0.28.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (353) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/dist/docs/internals/hooks.md +1 -1
  3. package/dist/docs/public/channels/README.md +50 -2
  4. package/dist/docs/public/channels/discord.md +15 -7
  5. package/dist/docs/public/channels/teams.md +121 -0
  6. package/dist/docs/public/channels/telegram.md +201 -0
  7. package/dist/docs/public/typescript-api.md +41 -1
  8. package/dist/src/channel/adapter.js +1 -1
  9. package/dist/src/channel/compiled-channel.js +1 -1
  10. package/dist/src/channel/http.js +1 -1
  11. package/dist/src/channel/schedule.js +1 -1
  12. package/dist/src/channel/send.js +1 -1
  13. package/dist/src/channel/session-callback.js +1 -1
  14. package/dist/src/channel/session.js +1 -1
  15. package/dist/src/cli/commands/channels.js +1 -1
  16. package/dist/src/cli/dev/environment.js +1 -1
  17. package/dist/src/cli/dev/input-requests.js +1 -1
  18. package/dist/src/cli/dev/repl.js +1 -1
  19. package/dist/src/cli/dev/terminal.js +1 -1
  20. package/dist/src/cli/dev/url.js +1 -1
  21. package/dist/src/compiler/artifacts.js +1 -1
  22. package/dist/src/compiler/manifest.js +1 -1
  23. package/dist/src/compiler/model-catalog.js +1 -1
  24. package/dist/src/compiler/module-map.js +1 -1
  25. package/dist/src/compiler/normalize-subagent.js +1 -1
  26. package/dist/src/compiler/remote-agent-node.js +1 -1
  27. package/dist/src/compiler/workspace-resources.js +1 -1
  28. package/dist/src/context/accessors.js +1 -1
  29. package/dist/src/context/container.js +1 -1
  30. package/dist/src/context/hook-lifecycle.d.ts +3 -3
  31. package/dist/src/context/hook-lifecycle.js +1 -1
  32. package/dist/src/context/key.js +1 -1
  33. package/dist/src/context/keys.d.ts +31 -10
  34. package/dist/src/context/keys.js +1 -1
  35. package/dist/src/context/node.js +1 -1
  36. package/dist/src/context/providers/connection.js +1 -1
  37. package/dist/src/context/providers/sandbox.js +1 -1
  38. package/dist/src/context/providers/session.js +1 -1
  39. package/dist/src/context/run-step.js +1 -1
  40. package/dist/src/context/serialize.js +1 -1
  41. package/dist/src/discover/connections.js +1 -1
  42. package/dist/src/discover/diagnostics.js +1 -1
  43. package/dist/src/discover/discover-subagent.js +1 -1
  44. package/dist/src/discover/filesystem.js +1 -1
  45. package/dist/src/discover/grammar.js +1 -1
  46. package/dist/src/discover/lib.js +1 -1
  47. package/dist/src/discover/manifest.js +1 -1
  48. package/dist/src/discover/sandbox.js +1 -1
  49. package/dist/src/discover/schedules.js +1 -1
  50. package/dist/src/discover/skills.js +1 -1
  51. package/dist/src/evals/runner/discover.js +1 -1
  52. package/dist/src/evals/runner/execute-suite.js +1 -1
  53. package/dist/src/evals/runner/reporters/braintrust.js +1 -1
  54. package/dist/src/evals/scores/index.js +1 -1
  55. package/dist/src/execution/await-authorization-orchestrator.js +1 -1
  56. package/dist/src/execution/connection-auth-steps.js +1 -1
  57. package/dist/src/execution/runtime-context.d.ts +1 -1
  58. package/dist/src/execution/runtime-context.js +1 -1
  59. package/dist/src/execution/sandbox/bindings/local.js +1 -1
  60. package/dist/src/execution/sandbox/bindings/vercel.js +1 -1
  61. package/dist/src/execution/sandbox/glob-tool.js +1 -1
  62. package/dist/src/execution/sandbox/grep-tool.js +1 -1
  63. package/dist/src/execution/sandbox/read-file-tool.js +1 -1
  64. package/dist/src/execution/sandbox/require-sandbox.js +1 -1
  65. package/dist/src/execution/sandbox/ripgrep-probe.js +1 -1
  66. package/dist/src/execution/sandbox/truncate-output.js +1 -1
  67. package/dist/src/execution/session-callback-step.js +1 -1
  68. package/dist/src/execution/session.js +1 -1
  69. package/dist/src/execution/subagent-adapter.js +1 -1
  70. package/dist/src/execution/tool-compaction.js +1 -1
  71. package/dist/src/execution/turn-workflow.js +1 -1
  72. package/dist/src/execution/web-fetch/html.js +1 -1
  73. package/dist/src/execution/web-fetch/tool.js +1 -1
  74. package/dist/src/execution/workflow-entry.js +1 -1
  75. package/dist/src/execution/workflow-runtime.js +1 -1
  76. package/dist/src/execution/workflow-steps.js +1 -1
  77. package/dist/src/harness/attachment-staging.js +1 -1
  78. package/dist/src/harness/compaction.js +2 -2
  79. package/dist/src/harness/emission.js +1 -1
  80. package/dist/src/harness/input-requests.js +1 -1
  81. package/dist/src/harness/instrumentation-config.js +1 -1
  82. package/dist/src/harness/model-call-error.js +1 -1
  83. package/dist/src/harness/otel-integration.js +1 -1
  84. package/dist/src/harness/prompt-cache.js +1 -1
  85. package/dist/src/harness/provider-tools.js +1 -1
  86. package/dist/src/harness/proxy-input-requests.js +1 -1
  87. package/dist/src/harness/runtime-actions.js +1 -1
  88. package/dist/src/harness/step-hooks.js +1 -1
  89. package/dist/src/harness/tool-loop.js +1 -1
  90. package/dist/src/harness/tool-result-pruning.js +1 -1
  91. package/dist/src/internal/application/cache-metadata.js +1 -1
  92. package/dist/src/internal/application/compiled-artifacts.js +1 -1
  93. package/dist/src/internal/application/import-specifier.js +1 -1
  94. package/dist/src/internal/application/package.js +1 -1
  95. package/dist/src/internal/attachments/refs.js +1 -1
  96. package/dist/src/internal/attachments/sandbox-refs.js +1 -1
  97. package/dist/src/internal/attachments/url-refs.js +1 -1
  98. package/dist/src/internal/authored-asset-import-plugin.js +1 -1
  99. package/dist/src/internal/authored-definition/connection.js +1 -1
  100. package/dist/src/internal/authored-module-loader.js +1 -1
  101. package/dist/src/internal/authored-package-tsconfig-paths.js +1 -1
  102. package/dist/src/internal/bundler/nitro-rolldown.js +1 -1
  103. package/dist/src/internal/helpers/markdown.js +2 -2
  104. package/dist/src/internal/json-schema.js +1 -1
  105. package/dist/src/internal/logging.js +1 -1
  106. package/dist/src/internal/nitro/host/channel-routes.js +1 -1
  107. package/dist/src/internal/nitro/host/compiled-sandbox-backend-prune-plugin.js +1 -1
  108. package/dist/src/internal/nitro/host/create-application-nitro.js +1 -1
  109. package/dist/src/internal/nitro/host/dev-authored-source-watcher.js +1 -1
  110. package/dist/src/internal/nitro/host/schedule-task-routes.js +1 -1
  111. package/dist/src/internal/nitro/host/server-external-packages.js +1 -1
  112. package/dist/src/internal/nitro/host/start-development-server.js +1 -1
  113. package/dist/src/internal/nitro/routes/index.js +3 -3
  114. package/dist/src/internal/nitro/routes/workflow-route-helpers.js +1 -1
  115. package/dist/src/internal/node-esm-compat-banner.js +1 -1
  116. package/dist/src/internal/package-name.js +1 -1
  117. package/dist/src/internal/vercel-agent-summary.js +1 -1
  118. package/dist/src/internal/workflow-bundle/ash-service-route-output.js +1 -1
  119. package/dist/src/internal/workflow-bundle/builder-support.js +1 -1
  120. package/dist/src/internal/workflow-bundle/builder.js +2 -2
  121. package/dist/src/internal/workflow-bundle/vercel-workflow-output.js +1 -1
  122. package/dist/src/internal/workflow-bundle/workflow-builders.js +1 -1
  123. package/dist/src/internal/workflow-bundle/workflow-core-shim.js +1 -1
  124. package/dist/src/internal/workflow-bundle/workflow-transformer.js +1 -1
  125. package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/ajv.js +1 -1
  126. package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/compile/codegen/code.js +1 -1
  127. package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/compile/codegen/index.js +2 -2
  128. package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/compile/codegen/scope.js +1 -1
  129. package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/compile/errors.js +1 -1
  130. package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/compile/index.js +1 -1
  131. package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/compile/names.js +1 -1
  132. package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/compile/ref_error.js +1 -1
  133. package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/compile/resolve.js +1 -1
  134. package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/compile/rules.js +1 -1
  135. package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/compile/util.js +1 -1
  136. package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/compile/validate/boolSchema.js +1 -1
  137. package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/compile/validate/dataType.js +2 -2
  138. package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/compile/validate/defaults.js +1 -1
  139. package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/compile/validate/index.js +1 -1
  140. package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/compile/validate/keyword.js +1 -1
  141. package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/compile/validate/subschema.js +1 -1
  142. package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/core.js +1 -1
  143. package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/runtime/equal.js +1 -1
  144. package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/runtime/uri.js +1 -1
  145. package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/applicator/additionalItems.js +1 -1
  146. package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/applicator/additionalProperties.js +1 -1
  147. package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/applicator/allOf.js +1 -1
  148. package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/applicator/contains.js +1 -1
  149. package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/applicator/dependencies.js +2 -2
  150. package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/applicator/if.js +1 -1
  151. package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/applicator/index.js +1 -1
  152. package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/applicator/items.js +1 -1
  153. package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/applicator/items2020.js +1 -1
  154. package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/applicator/not.js +1 -1
  155. package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/applicator/oneOf.js +1 -1
  156. package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/applicator/patternProperties.js +1 -1
  157. package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/applicator/prefixItems.js +1 -1
  158. package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/applicator/properties.js +1 -1
  159. package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/applicator/propertyNames.js +1 -1
  160. package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/applicator/thenElse.js +1 -1
  161. package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/code.js +1 -1
  162. package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/core/index.js +1 -1
  163. package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/core/ref.js +1 -1
  164. package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/discriminator/index.js +1 -1
  165. package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/draft7.js +1 -1
  166. package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/format/format.js +1 -1
  167. package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/validation/const.js +1 -1
  168. package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/validation/enum.js +1 -1
  169. package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/validation/index.js +1 -1
  170. package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/validation/limitItems.js +1 -1
  171. package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/validation/limitLength.js +1 -1
  172. package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/validation/limitNumber.js +1 -1
  173. package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/validation/limitProperties.js +1 -1
  174. package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/validation/multipleOf.js +1 -1
  175. package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/validation/pattern.js +1 -1
  176. package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/validation/required.js +1 -1
  177. package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/validation/uniqueItems.js +1 -1
  178. package/dist/src/node_modules/.pnpm/fast-uri@3.1.2/node_modules/fast-uri/index.js +1 -1
  179. package/dist/src/node_modules/.pnpm/fast-uri@3.1.2/node_modules/fast-uri/lib/schemes.js +1 -1
  180. package/dist/src/node_modules/.pnpm/fast-uri@3.1.2/node_modules/fast-uri/lib/utils.js +1 -1
  181. package/dist/src/node_modules/.pnpm/openai@6.39.0_ws@8.21.0_zod@3.25.76/node_modules/openai/_vendor/partial-json-parser/parser.js +2 -2
  182. package/dist/src/node_modules/.pnpm/openai@6.39.0_ws@8.21.0_zod@3.25.76/node_modules/openai/auth/workload-identity-auth.js +1 -1
  183. package/dist/src/node_modules/.pnpm/openai@6.39.0_ws@8.21.0_zod@3.25.76/node_modules/openai/azure.js +1 -1
  184. package/dist/src/node_modules/.pnpm/openai@6.39.0_ws@8.21.0_zod@3.25.76/node_modules/openai/client.js +2 -2
  185. package/dist/src/node_modules/.pnpm/openai@6.39.0_ws@8.21.0_zod@3.25.76/node_modules/openai/internal/detect-platform.js +1 -1
  186. package/dist/src/node_modules/.pnpm/openai@6.39.0_ws@8.21.0_zod@3.25.76/node_modules/openai/internal/errors.js +1 -1
  187. package/dist/src/node_modules/.pnpm/openai@6.39.0_ws@8.21.0_zod@3.25.76/node_modules/openai/internal/headers.js +1 -1
  188. package/dist/src/node_modules/.pnpm/openai@6.39.0_ws@8.21.0_zod@3.25.76/node_modules/openai/internal/qs/formats.js +1 -1
  189. package/dist/src/node_modules/.pnpm/openai@6.39.0_ws@8.21.0_zod@3.25.76/node_modules/openai/internal/qs/stringify.js +1 -1
  190. package/dist/src/node_modules/.pnpm/openai@6.39.0_ws@8.21.0_zod@3.25.76/node_modules/openai/internal/qs/utils.js +1 -1
  191. package/dist/src/node_modules/.pnpm/openai@6.39.0_ws@8.21.0_zod@3.25.76/node_modules/openai/internal/request-options.js +1 -1
  192. package/dist/src/node_modules/.pnpm/openai@6.39.0_ws@8.21.0_zod@3.25.76/node_modules/openai/internal/to-file.js +1 -1
  193. package/dist/src/node_modules/.pnpm/openai@6.39.0_ws@8.21.0_zod@3.25.76/node_modules/openai/internal/uploads.js +1 -1
  194. package/dist/src/node_modules/.pnpm/openai@6.39.0_ws@8.21.0_zod@3.25.76/node_modules/openai/internal/utils/base64.js +1 -1
  195. package/dist/src/node_modules/.pnpm/openai@6.39.0_ws@8.21.0_zod@3.25.76/node_modules/openai/internal/utils/bytes.js +1 -1
  196. package/dist/src/node_modules/.pnpm/openai@6.39.0_ws@8.21.0_zod@3.25.76/node_modules/openai/internal/utils/env.js +1 -1
  197. package/dist/src/node_modules/.pnpm/openai@6.39.0_ws@8.21.0_zod@3.25.76/node_modules/openai/internal/utils/log.js +1 -1
  198. package/dist/src/node_modules/.pnpm/openai@6.39.0_ws@8.21.0_zod@3.25.76/node_modules/openai/internal/utils/path.js +1 -1
  199. package/dist/src/node_modules/.pnpm/openai@6.39.0_ws@8.21.0_zod@3.25.76/node_modules/openai/internal/utils/sleep.js +1 -1
  200. package/dist/src/node_modules/.pnpm/openai@6.39.0_ws@8.21.0_zod@3.25.76/node_modules/openai/internal/utils/uuid.js +1 -1
  201. package/dist/src/node_modules/.pnpm/openai@6.39.0_ws@8.21.0_zod@3.25.76/node_modules/openai/internal/utils/values.js +1 -1
  202. package/dist/src/node_modules/.pnpm/openai@6.39.0_ws@8.21.0_zod@3.25.76/node_modules/openai/lib/AbstractChatCompletionRunner.js +1 -1
  203. package/dist/src/node_modules/.pnpm/openai@6.39.0_ws@8.21.0_zod@3.25.76/node_modules/openai/lib/Util.js +1 -1
  204. package/dist/src/node_modules/.pnpm/openai@6.39.0_ws@8.21.0_zod@3.25.76/node_modules/openai/lib/chatCompletionUtils.js +1 -1
  205. package/dist/src/node_modules/.pnpm/openai@6.39.0_ws@8.21.0_zod@3.25.76/node_modules/openai/version.js +1 -1
  206. package/dist/src/node_modules/.pnpm/zod-to-json-schema@3.25.2_zod@3.25.76/node_modules/zod-to-json-schema/dist/esm/Options.js +1 -1
  207. package/dist/src/node_modules/.pnpm/zod-to-json-schema@3.25.2_zod@3.25.76/node_modules/zod-to-json-schema/dist/esm/Refs.js +1 -1
  208. package/dist/src/node_modules/.pnpm/zod-to-json-schema@3.25.2_zod@3.25.76/node_modules/zod-to-json-schema/dist/esm/getRelativePath.js +1 -1
  209. package/dist/src/node_modules/.pnpm/zod-to-json-schema@3.25.2_zod@3.25.76/node_modules/zod-to-json-schema/dist/esm/parseDef.js +1 -1
  210. package/dist/src/node_modules/.pnpm/zod-to-json-schema@3.25.2_zod@3.25.76/node_modules/zod-to-json-schema/dist/esm/parsers/catch.js +1 -1
  211. package/dist/src/node_modules/.pnpm/zod-to-json-schema@3.25.2_zod@3.25.76/node_modules/zod-to-json-schema/dist/esm/parsers/date.js +1 -1
  212. package/dist/src/node_modules/.pnpm/zod-to-json-schema@3.25.2_zod@3.25.76/node_modules/zod-to-json-schema/dist/esm/parsers/intersection.js +1 -1
  213. package/dist/src/node_modules/.pnpm/zod-to-json-schema@3.25.2_zod@3.25.76/node_modules/zod-to-json-schema/dist/esm/parsers/optional.js +1 -1
  214. package/dist/src/node_modules/.pnpm/zod-to-json-schema@3.25.2_zod@3.25.76/node_modules/zod-to-json-schema/dist/esm/parsers/pipeline.js +1 -1
  215. package/dist/src/node_modules/.pnpm/zod-to-json-schema@3.25.2_zod@3.25.76/node_modules/zod-to-json-schema/dist/esm/parsers/readonly.js +1 -1
  216. package/dist/src/node_modules/.pnpm/zod-to-json-schema@3.25.2_zod@3.25.76/node_modules/zod-to-json-schema/dist/esm/parsers/string.js +1 -1
  217. package/dist/src/node_modules/.pnpm/zod-to-json-schema@3.25.2_zod@3.25.76/node_modules/zod-to-json-schema/dist/esm/parsers/union.js +1 -1
  218. package/dist/src/node_modules/.pnpm/zod-to-json-schema@3.25.2_zod@3.25.76/node_modules/zod-to-json-schema/dist/esm/selectParser.js +1 -1
  219. package/dist/src/node_modules/.pnpm/zod-to-json-schema@3.25.2_zod@3.25.76/node_modules/zod-to-json-schema/dist/esm/zodToJsonSchema.js +1 -1
  220. package/dist/src/node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/ZodError.js +1 -1
  221. package/dist/src/node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/errors.js +1 -1
  222. package/dist/src/node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/parseUtil.js +1 -1
  223. package/dist/src/node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/util.js +1 -1
  224. package/dist/src/node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/locales/en.js +1 -1
  225. package/dist/src/node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/types.js +1 -1
  226. package/dist/src/packages/ash-scaffold/src/channels.js +2 -2
  227. package/dist/src/packages/ash-scaffold/src/module-files.js +1 -1
  228. package/dist/src/protocol/message.js +1 -1
  229. package/dist/src/protocol/routes.js +1 -1
  230. package/dist/src/public/channels/ash.js +2 -2
  231. package/dist/src/public/channels/auth.js +1 -1
  232. package/dist/src/public/channels/discord/api.js +1 -1
  233. package/dist/src/public/channels/discord/defaults.js +1 -1
  234. package/dist/src/public/channels/discord/discordChannel.js +1 -1
  235. package/dist/src/public/channels/discord/hitl.js +1 -1
  236. package/dist/src/public/channels/discord/inbound.js +1 -1
  237. package/dist/src/public/channels/discord/verify.js +1 -1
  238. package/dist/src/public/channels/discord/verifyInbound.js +1 -1
  239. package/dist/src/public/channels/slack/api.js +1 -1
  240. package/dist/src/public/channels/slack/attachments.js +1 -1
  241. package/dist/src/public/channels/slack/constants.js +1 -1
  242. package/dist/src/public/channels/slack/defaults.js +2 -2
  243. package/dist/src/public/channels/slack/hitl.js +1 -1
  244. package/dist/src/public/channels/slack/interactions.js +1 -1
  245. package/dist/src/public/channels/slack/limits.js +1 -1
  246. package/dist/src/public/channels/slack/mrkdwn.js +1 -1
  247. package/dist/src/public/channels/slack/slackChannel.js +1 -1
  248. package/dist/src/public/channels/slack/verify.js +1 -1
  249. package/dist/src/public/channels/teams/api.d.ts +140 -0
  250. package/dist/src/public/channels/teams/api.js +4 -0
  251. package/dist/src/public/channels/teams/attachments.d.ts +25 -0
  252. package/dist/src/public/channels/teams/attachments.js +1 -0
  253. package/dist/src/public/channels/teams/defaults.d.ts +24 -0
  254. package/dist/src/public/channels/teams/defaults.js +3 -0
  255. package/dist/src/public/channels/teams/hitl.d.ts +36 -0
  256. package/dist/src/public/channels/teams/hitl.js +1 -0
  257. package/dist/src/public/channels/teams/inbound.d.ts +80 -0
  258. package/dist/src/public/channels/teams/inbound.js +3 -0
  259. package/dist/src/public/channels/teams/index.d.ts +8 -0
  260. package/dist/src/public/channels/teams/index.js +1 -0
  261. package/dist/src/public/channels/teams/limits.d.ts +8 -0
  262. package/dist/src/public/channels/teams/limits.js +1 -0
  263. package/dist/src/public/channels/teams/teamsChannel.d.ts +162 -0
  264. package/dist/src/public/channels/teams/teamsChannel.js +1 -0
  265. package/dist/src/public/channels/teams/verify.d.ts +43 -0
  266. package/dist/src/public/channels/teams/verify.js +1 -0
  267. package/dist/src/public/channels/telegram/api.d.ts +107 -0
  268. package/dist/src/public/channels/telegram/api.js +2 -0
  269. package/dist/src/public/channels/telegram/attachments.d.ts +23 -0
  270. package/dist/src/public/channels/telegram/attachments.js +1 -0
  271. package/dist/src/public/channels/telegram/defaults.d.ts +9 -0
  272. package/dist/src/public/channels/telegram/defaults.js +3 -0
  273. package/dist/src/public/channels/telegram/hitl.d.ts +44 -0
  274. package/dist/src/public/channels/telegram/hitl.js +1 -0
  275. package/dist/src/public/channels/telegram/inbound.d.ts +88 -0
  276. package/dist/src/public/channels/telegram/inbound.js +2 -0
  277. package/dist/src/public/channels/telegram/index.d.ts +8 -0
  278. package/dist/src/public/channels/telegram/index.js +1 -0
  279. package/dist/src/public/channels/telegram/telegramChannel.d.ts +126 -0
  280. package/dist/src/public/channels/telegram/telegramChannel.js +1 -0
  281. package/dist/src/public/channels/telegram/verify.d.ts +30 -0
  282. package/dist/src/public/channels/telegram/verify.js +1 -0
  283. package/dist/src/public/channels/twilio/defaults.js +1 -1
  284. package/dist/src/public/channels/twilio/inbound.js +1 -1
  285. package/dist/src/public/channels/twilio/twilioChannel.js +1 -1
  286. package/dist/src/public/channels/twilio/verify.js +1 -1
  287. package/dist/src/public/channels/upload-policy.js +1 -1
  288. package/dist/src/public/definitions/channel.js +1 -1
  289. package/dist/src/public/definitions/tool.js +1 -1
  290. package/dist/src/public/next/index.js +1 -1
  291. package/dist/src/public/next/server.js +1 -1
  292. package/dist/src/public/next/vercel-json.js +1 -1
  293. package/dist/src/public/tool-result-narrowing.js +1 -1
  294. package/dist/src/public/tools/defaults.js +1 -1
  295. package/dist/src/react/use-ash-agent.js +1 -1
  296. package/dist/src/runtime/actions/types.js +1 -1
  297. package/dist/src/runtime/agent/bootstrap-model-utils.js +1 -1
  298. package/dist/src/runtime/agent/bootstrap-model.js +1 -1
  299. package/dist/src/runtime/agent/bootstrap.js +1 -1
  300. package/dist/src/runtime/agent/mock-model-adapter.js +1 -1
  301. package/dist/src/runtime/channels/registry.js +1 -1
  302. package/dist/src/runtime/connections/authorization-tokens.js +1 -1
  303. package/dist/src/runtime/connections/callback-route.js +1 -1
  304. package/dist/src/runtime/connections/principal-context.js +1 -1
  305. package/dist/src/runtime/connections/principal.js +1 -1
  306. package/dist/src/runtime/framework-channels/index.js +1 -1
  307. package/dist/src/runtime/framework-tools/ask-question.js +1 -1
  308. package/dist/src/runtime/framework-tools/bash.js +1 -1
  309. package/dist/src/runtime/framework-tools/connection-search.js +1 -1
  310. package/dist/src/runtime/framework-tools/file-state.js +1 -1
  311. package/dist/src/runtime/framework-tools/glob.js +1 -1
  312. package/dist/src/runtime/framework-tools/grep.js +1 -1
  313. package/dist/src/runtime/framework-tools/index.js +1 -1
  314. package/dist/src/runtime/framework-tools/pending-connection-tool-calls.js +1 -1
  315. package/dist/src/runtime/framework-tools/read-file.js +1 -1
  316. package/dist/src/runtime/framework-tools/skill.js +1 -1
  317. package/dist/src/runtime/framework-tools/todo.js +2 -2
  318. package/dist/src/runtime/framework-tools/web-fetch.js +1 -1
  319. package/dist/src/runtime/framework-tools/web-search.js +1 -1
  320. package/dist/src/runtime/framework-tools/write-file.js +1 -1
  321. package/dist/src/runtime/governance/auth/jwt-ecdsa.js +1 -1
  322. package/dist/src/runtime/governance/auth/oidc.js +1 -1
  323. package/dist/src/runtime/governance/auth/token-claims.js +1 -1
  324. package/dist/src/runtime/graph.js +1 -1
  325. package/dist/src/runtime/input/types.js +1 -1
  326. package/dist/src/runtime/loaders/compile-metadata.js +1 -1
  327. package/dist/src/runtime/loaders/manifest.js +1 -1
  328. package/dist/src/runtime/loaders/module-map.js +1 -1
  329. package/dist/src/runtime/prompt/compose.js +2 -2
  330. package/dist/src/runtime/prompt/connections.js +1 -1
  331. package/dist/src/runtime/resolve-agent-graph.js +1 -1
  332. package/dist/src/runtime/resolve-hook.js +1 -1
  333. package/dist/src/runtime/sandbox/keys.js +1 -1
  334. package/dist/src/runtime/sandbox/registry.js +1 -1
  335. package/dist/src/runtime/schedules/register.js +1 -1
  336. package/dist/src/runtime/session-callback-route.js +1 -1
  337. package/dist/src/runtime/sessions/auth.js +1 -1
  338. package/dist/src/runtime/sessions/compiled-agent-cache.js +1 -1
  339. package/dist/src/runtime/sessions/runtime-context-keys.d.ts +11 -0
  340. package/dist/src/runtime/sessions/runtime-context-keys.js +1 -0
  341. package/dist/src/runtime/sessions/runtime-session.js +1 -1
  342. package/dist/src/runtime/skills/fragment-context.js +1 -1
  343. package/dist/src/runtime/skills/sandbox-access.js +1 -1
  344. package/dist/src/runtime/subagents/registry.js +1 -1
  345. package/dist/src/runtime/workspace/types.js +1 -1
  346. package/dist/src/services/dev-client/request-headers.js +1 -1
  347. package/dist/src/services/dev-client/vercel-auth-error.js +1 -1
  348. package/dist/src/shared/json-schemas.js +1 -1
  349. package/dist/src/shared/json.js +1 -1
  350. package/dist/src/shared/skill-package.js +1 -1
  351. package/package.json +11 -1
  352. package/dist/src/context/seed-keys.d.ts +0 -39
  353. package/dist/src/context/seed-keys.js +0 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,25 @@
1
1
  # experimental-ash
2
2
 
3
+ ## 0.28.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 9be5b5c: Fix `TypeError: Cannot read properties of undefined (reading 'name')` thrown from `resolveRuntimeAgentNode` on Vercel deployments by splitting `#context/keys.ts` along its layering seam and dropping the rolldown setting that hid the bug.
8
+
9
+ A static-import cycle through `BundleKey.codec` (`#context/keys` → `#runtime/sessions/compiled-agent-cache` → `#runtime/resolve-agent-graph` → `#runtime/framework-tools/index` → `#runtime/framework-tools/bash` → `#execution/sandbox/bash-tool` → `#execution/sandbox/require-sandbox` → `#context/keys`) interacted badly with the rolldown build's `topLevelVar: true` setting. When Nitro re-bundled ash's dist into a single concatenated `_libs/experimental-ash.mjs` for a Vercel function, it could land `var BASH_TOOL_DEFINITION = {...}` _after_ the `ALL_FRAMEWORK_TOOLS` array that referenced it. `var` hoisting then silently filled the slot with `undefined` (no TDZ `ReferenceError`), and every downstream `.map(t => t.name)` over that array crashed inside `resolveRuntimeAgentNode`.
10
+
11
+ The structural fix: `#context/keys.ts` was doing two unrelated jobs in one file. The leaf job (declaring `SandboxKey`, `SessionKey`, etc.) is widely imported across the codebase. The heavy job (owning the `ChannelKey` and `BundleKey` codecs that materialize values by calling back into the runtime) drags in the entire runtime layer. Because JS evaluates modules whole, every leaf caller was paying the heavy job's transitive import cost, which is how the cycle got seeded.
12
+
13
+ - Split `#context/keys.ts` into two files. `#context/keys.ts` now only declares leaf context keys (no codec, no runtime imports — safe to import from any tier). `#runtime/sessions/runtime-context-keys.ts` owns `ChannelKey`, `BundleKey`, and `CompiledBundle` next to the modules whose state they carry.
14
+ - Drop `topLevelVar: true` from `packages/ash/scripts/build-rolldown.mjs`. The setting was masking module-evaluation cycles; with `let`/`const` they now surface as a loud `ReferenceError` at module load instead of silent `undefined` reads.
15
+
16
+ ## 0.28.0
17
+
18
+ ### Minor Changes
19
+
20
+ - 2e8ebcb: Add a native Microsoft Teams channel backed by the Bot Framework Activity and Connector protocols, including inbound verification, Teams conversation state, Adaptive Card HITL, proactive receive support, docs, tests, and smoke coverage.
21
+ - 70018bd: Add a native Telegram channel for verified Bot API webhooks, Telegram delivery, HITL interactions, attachments, and proactive sessions.
22
+
3
23
  ## 0.27.0
4
24
 
5
25
  ### Minor Changes
@@ -129,7 +129,7 @@ catches them and emits the recoverable `turn.failed` cascade.
129
129
 
130
130
  ## `SessionPreparedKey`
131
131
 
132
- Lives in `src/context/seed-keys.ts`. JSON-safe boolean, no codec. Set
132
+ Lives in `src/context/keys.ts`. JSON-safe boolean, no codec. Set
133
133
  **before** the `lifecycle.session` chain runs so a thrown hook leaves
134
134
  the flag set — the next turn does not retry. Compaction does not clear
135
135
  the flag.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  title: "Channels"
3
- description: "Deliver your agent over HTTP, Slack, Discord, Twilio, and custom transports."
3
+ description: "Deliver your agent over HTTP, Slack, Discord, Twilio, Telegram, Microsoft Teams, and custom transports."
4
4
  url: /channels
5
5
  ---
6
6
 
@@ -23,7 +23,7 @@ Ash ships the public HTTP protocol as channels:
23
23
  - `ashChannel({ auth })` for the built-in Ash protocol channel
24
24
 
25
25
  Ash also supports authored channels under `agent/channels/` for platform-specific integrations such
26
- as Slack, Discord, Twilio, or custom webhooks.
26
+ as Slack, Discord, Twilio, Telegram, Microsoft Teams, or custom webhooks.
27
27
 
28
28
  ## Filesystem Shape
29
29
 
@@ -279,6 +279,53 @@ resolver when the allowed phone numbers come from dynamic state. Use `allowFrom:
279
279
 
280
280
  See [Twilio channel setup](./twilio.md) for webhook URLs, environment variables, and overrides.
281
281
 
282
+ ## Telegram Channels
283
+
284
+ Telegram channels are authored with `telegramChannel()`:
285
+
286
+ ```ts
287
+ import { telegramChannel } from "experimental-ash/channels/telegram";
288
+
289
+ export default telegramChannel({
290
+ botUsername: "my_bot",
291
+ });
292
+ ```
293
+
294
+ The channel verifies Telegram's `X-Telegram-Bot-Api-Secret-Token` webhook header, accepts updates at
295
+ `/ash/v1/telegram`, dispatches private messages and addressed group messages, and resolves HITL
296
+ inline-keyboard callbacks and ForceReply answers back into Ash input responses. Private chats use
297
+ chat-wide continuation tokens. Group, supergroup, and forum-topic sessions include the chat id,
298
+ optional `message_thread_id`, and a conversation anchor so multiple bot conversations in the same
299
+ chat do not collapse.
300
+
301
+ Default delivery sends plain text through Telegram `sendMessage` with no `parse_mode`, splits text
302
+ at Telegram's 4096-character limit, and uses best-effort `sendChatAction("typing")` progress
303
+ indicators. Photos and documents are exposed as file parts and fetched through Telegram `getFile`
304
+ when the model needs the bytes.
305
+
306
+ See [Telegram channel setup](./telegram.md) for webhook registration, environment variables, group
307
+ privacy notes, HITL behavior, attachments, and proactive sessions.
308
+
309
+ ## Microsoft Teams Channels
310
+
311
+ Teams channels are authored with `teamsChannel()`:
312
+
313
+ ```ts
314
+ import { teamsChannel } from "experimental-ash/channels/teams";
315
+
316
+ export default teamsChannel();
317
+ ```
318
+
319
+ The channel verifies Bot Connector bearer JWTs, accepts Teams Bot Framework Activity POSTs at
320
+ `/ash/v1/teams`, dispatches personal messages and direct bot mentions, renders HITL prompts as
321
+ Adaptive Cards, and sends agent replies through the Bot Framework Connector REST API. Personal chats
322
+ resume by conversation id; channel and group-chat threads resume by conversation id plus root
323
+ activity id.
324
+
325
+ Proactive `receive(teams, args)` sessions require an existing conversation reference
326
+ (`serviceUrl` and `conversationId`). See [Microsoft Teams channel setup](./teams.md) for Azure Bot
327
+ setup, environment variables, proactive handoff, HITL, and file options.
328
+
282
329
  ## Cross-Channel Hand-off
283
330
 
284
331
  Route handlers can start a session on a different channel via `args.receive(channel, ...)`.
@@ -472,6 +519,7 @@ See [Channel file uploads](./attachments.md) for the full guide.
472
519
  ## What To Read Next
473
520
 
474
521
  - [Slack channel setup](./slack.md)
522
+ - [Telegram channel setup](./telegram.md)
475
523
  - [Channel file uploads](./attachments.md)
476
524
  - [Project Layout](../project-layout.md)
477
525
  - [TypeScript API](../typescript-api.md)
@@ -132,19 +132,27 @@ Component and modal submissions resume the parked Ash session automatically.
132
132
 
133
133
  ## Proactive Sessions
134
134
 
135
- Use `receive(discord, args)` from schedules or another channel to start a Discord session:
135
+ Use `receive(discord, { message, args, auth })` from a schedule `run` handler, or
136
+ `args.receive(discord, ...)` from another channel, to start a Discord session:
136
137
 
137
138
  ```ts
138
- import { defineSchedule, receive } from "experimental-ash/schedules";
139
+ import { defineSchedule } from "experimental-ash/schedules";
139
140
  import discord from "../channels/discord.js";
140
141
 
141
142
  export default defineSchedule({
142
143
  cron: "0 9 * * 1-5",
143
- markdown: "Post the daily summary.",
144
- channel: receive(discord, {
145
- channelId: "123456789012345678",
146
- initialMessage: "Daily summary",
147
- }),
144
+ async run({ receive, waitUntil, appAuth }) {
145
+ waitUntil(
146
+ receive(discord, {
147
+ message: "Post the daily summary.",
148
+ args: {
149
+ channelId: "123456789012345678",
150
+ initialMessage: "Daily summary",
151
+ },
152
+ auth: appAuth,
153
+ }),
154
+ );
155
+ },
148
156
  });
149
157
  ```
150
158
 
@@ -0,0 +1,121 @@
1
+ ---
2
+ title: "Microsoft Teams channel setup"
3
+ description: "Create a Microsoft Teams-backed Ash channel with the Bot Framework Activity protocol."
4
+ ---
5
+
6
+ # Microsoft Teams Channel Setup
7
+
8
+ The Teams channel accepts Bot Framework Activity POSTs from Microsoft Teams, verifies Bot
9
+ Connector bearer JWTs, dispatches message activities to Ash, renders HITL prompts as Adaptive
10
+ Cards, and delivers agent responses through the Bot Framework Connector REST API.
11
+
12
+ ## Add The Channel
13
+
14
+ Create `agent/channels/teams.ts`:
15
+
16
+ ```ts
17
+ import { teamsChannel } from "experimental-ash/channels/teams";
18
+
19
+ export default teamsChannel();
20
+ ```
21
+
22
+ Set the credentials Ash needs:
23
+
24
+ ```bash
25
+ MICROSOFT_APP_ID=...
26
+ MICROSOFT_APP_PASSWORD=...
27
+ # Optional for single-tenant bots:
28
+ MICROSOFT_TENANT_ID=...
29
+ ```
30
+
31
+ By default, the channel mounts `POST /ash/v1/teams`. Configure your Azure Bot or Teams app
32
+ messaging endpoint to that public URL.
33
+
34
+ Use `route` when the bot endpoint needs a different path:
35
+
36
+ ```ts
37
+ export default teamsChannel({
38
+ route: "/api/teams/activity",
39
+ });
40
+ ```
41
+
42
+ ## Message Dispatch
43
+
44
+ The default `onMessage` behavior dispatches personal-chat messages and channel/group-chat messages
45
+ that directly mention the bot. Ambient messages delivered through Teams resource-specific consent
46
+ are parsed but ignored unless you override `onMessage`.
47
+
48
+ ```ts
49
+ import { teamsChannel, defaultTeamsAuth } from "experimental-ash/channels/teams";
50
+
51
+ export default teamsChannel({
52
+ onMessage(ctx, message) {
53
+ if (message.scope !== "personal" && !message.isBotMentioned) return null;
54
+ return { auth: defaultTeamsAuth(message) };
55
+ },
56
+ });
57
+ ```
58
+
59
+ Ash strips the bot mention from channel/group prompts, adds a compact `<teams_context>` block, and
60
+ keeps personal chats scoped to one Ash session per Teams conversation. Channel and group-chat
61
+ threads are scoped by the root activity id (`replyToId ?? id`).
62
+
63
+ ## Delivery And HITL
64
+
65
+ Default delivery posts Markdown messages with `textFormat: "markdown"`, splits oversized text, and
66
+ sends typing indicators on turn start and action requests. `input.requested` renders Adaptive Cards:
67
+ buttons/options use `Action.Submit`, select requests use `Input.ChoiceSet`, and freeform requests
68
+ use `Input.Text`.
69
+
70
+ Adaptive Card submit activities are converted into Ash `inputResponses` automatically. Non-HITL
71
+ invoke activities can be handled with `onInvoke(ctx, activity)`.
72
+
73
+ ## Proactive Sessions
74
+
75
+ Use `receive(teams, args)` only when you already have a Teams conversation reference. Teams v1 does
76
+ not create new chats by AAD user id.
77
+
78
+ ```ts
79
+ import { defineSchedule, receive } from "experimental-ash/schedules";
80
+ import teams from "../channels/teams.js";
81
+
82
+ export default defineSchedule({
83
+ cron: "0 9 * * 1-5",
84
+ markdown: "Post the daily summary.",
85
+ channel: receive(teams, {
86
+ serviceUrl: "https://smba.trafficmanager.net/teams",
87
+ conversationId: "19:...",
88
+ conversationType: "channel",
89
+ tenantId: "tenant-id",
90
+ initialMessage: "Daily summary",
91
+ }),
92
+ });
93
+ ```
94
+
95
+ For channel/group-chat proactive sessions without `replyToActivityId`, the first posted message
96
+ becomes the thread anchor and the channel re-keys the Ash continuation token to that activity id.
97
+
98
+ ## Files
99
+
100
+ Text support is enabled by default. Inbound file parts are opt-in:
101
+
102
+ ```ts
103
+ export default teamsChannel({
104
+ files: {
105
+ enabled: true,
106
+ allowedHosts: ["contoso.sharepoint.com"],
107
+ },
108
+ });
109
+ ```
110
+
111
+ This covers personal-scope Teams file download attachments and simple public media URLs. Graph-based
112
+ channel file retrieval and outbound file-consent upload are intentionally outside v1.
113
+
114
+ ## Teams References
115
+
116
+ - [Teams conversational bots](https://learn.microsoft.com/en-us/microsoftteams/platform/bots/build-conversational-capability)
117
+ - [Teams channel and group chat bot conversations](https://learn.microsoft.com/en-us/microsoftteams/platform/bots/how-to/conversations/channel-and-group-conversations)
118
+ - [Bot Connector authentication](https://learn.microsoft.com/en-us/azure/bot-service/rest-api/bot-framework-rest-connector-authentication?view=azure-bot-service-4.0)
119
+ - [Bot Connector REST API reference](https://learn.microsoft.com/sr-latn-rs/azure/bot-service/rest-api/bot-framework-rest-connector-api-reference?view=azure-bot-service-4.0)
120
+ - [Teams proactive messages](https://learn.microsoft.com/en-us/microsoftteams/platform/bots/how-to/conversations/send-proactive-messages)
121
+ - [Teams card actions](https://learn.microsoft.com/en-us/microsoftteams/platform/task-modules-and-cards/cards/cards-actions)
@@ -0,0 +1,201 @@
1
+ ---
2
+ title: "Telegram channel setup"
3
+ description: "Create a Telegram-backed Ash channel for bot webhooks, replies, HITL, and attachments."
4
+ ---
5
+
6
+ # Telegram Channel Setup
7
+
8
+ The Telegram channel accepts Telegram Bot API webhooks. It verifies Telegram's
9
+ `X-Telegram-Bot-Api-Secret-Token` header before parsing the update, dispatches private messages and
10
+ addressed group messages, and sends default replies through `sendMessage`.
11
+
12
+ ## Add The Channel
13
+
14
+ Create `agent/channels/telegram.ts`:
15
+
16
+ ```ts
17
+ import { telegramChannel } from "experimental-ash/channels/telegram";
18
+
19
+ export default telegramChannel({
20
+ botUsername: "my_bot",
21
+ });
22
+ ```
23
+
24
+ Set the credentials Ash needs for inbound verification and outbound replies:
25
+
26
+ ```bash
27
+ TELEGRAM_BOT_TOKEN=123456:...
28
+ TELEGRAM_WEBHOOK_SECRET_TOKEN=...
29
+ ```
30
+
31
+ - `TELEGRAM_BOT_TOKEN` sends replies, typing indicators, callback acknowledgements, and proactive
32
+ messages.
33
+ - `TELEGRAM_WEBHOOK_SECRET_TOKEN` must match the `secret_token` value you register with Telegram's
34
+ `setWebhook`.
35
+
36
+ You can also pass the same values in config:
37
+
38
+ ```ts
39
+ export default telegramChannel({
40
+ botUsername: "my_bot",
41
+ credentials: {
42
+ botToken: process.env.TELEGRAM_BOT_TOKEN,
43
+ webhookSecretToken: process.env.TELEGRAM_WEBHOOK_SECRET_TOKEN,
44
+ },
45
+ });
46
+ ```
47
+
48
+ By default, the channel mounts `POST /ash/v1/telegram`.
49
+
50
+ ## Register The Webhook
51
+
52
+ Register the deployed public URL with Telegram's Bot API:
53
+
54
+ ```bash
55
+ curl -X POST "https://api.telegram.org/bot$TELEGRAM_BOT_TOKEN/setWebhook" \
56
+ -H "Content-Type: application/json" \
57
+ -d '{
58
+ "url": "https://your-app.example.com/ash/v1/telegram",
59
+ "secret_token": "'"$TELEGRAM_WEBHOOK_SECRET_TOKEN"'",
60
+ "allowed_updates": ["message", "callback_query"]
61
+ }'
62
+ ```
63
+
64
+ Webhook setup is external to Ash; the runtime does not call `setWebhook` for you.
65
+
66
+ ## Message Dispatch
67
+
68
+ Private chats dispatch normal text, captions, photos, and documents by default. The default
69
+ `onMessage` derives Telegram user auth, starts a typing indicator, and returns `{ auth }`.
70
+
71
+ Groups and supergroups are gated more narrowly:
72
+
73
+ - bot commands dispatch, including `/ask` and `/ask@my_bot`
74
+ - `@my_bot` mentions dispatch when `botUsername` is configured
75
+ - replies to bot messages dispatch
76
+ - unaddressed group chatter is ignored
77
+
78
+ For Telegram forum topics, the channel includes `message_thread_id` in the continuation token and
79
+ outbound messages so separate topics do not collapse into one session.
80
+
81
+ Override `onMessage` when you need custom auth or additional filtering:
82
+
83
+ ```ts
84
+ import { telegramChannel } from "experimental-ash/channels/telegram";
85
+
86
+ export default telegramChannel({
87
+ botUsername: "my_bot",
88
+ onMessage(ctx, message) {
89
+ if (message.chat.type !== "private" && !message.text.includes("@my_bot")) return null;
90
+ return {
91
+ auth: {
92
+ authenticator: "telegram",
93
+ principalType: "user",
94
+ principalId: message.from?.id ?? message.chat.id,
95
+ attributes: {
96
+ chat_id: message.chat.id,
97
+ chat_type: message.chat.type,
98
+ },
99
+ },
100
+ };
101
+ },
102
+ });
103
+ ```
104
+
105
+ Telegram group privacy is controlled by BotFather. With privacy mode enabled, Telegram only sends
106
+ commands, replies, and service messages to the bot. Disable privacy mode only if your bot should see
107
+ all group messages; Ash still applies the group dispatch gate above.
108
+
109
+ ## Delivery
110
+
111
+ The default `"message.completed"` handler sends plain text with `sendMessage`. Ash does not set
112
+ `parse_mode`, so generated Markdown is delivered as literal text rather than being parsed by
113
+ Telegram. Messages longer than Telegram's 4096-character text limit are split into multiple
114
+ `sendMessage` calls.
115
+
116
+ Default progress handlers call `sendChatAction` with `typing`. Typing failures are logged and
117
+ swallowed because the indicator is only a UX hint.
118
+
119
+ Custom event handlers can use `ctx.telegram`:
120
+
121
+ ```ts
122
+ export default telegramChannel({
123
+ events: {
124
+ async "message.completed"(event, ctx) {
125
+ if (event.finishReason === "tool-calls" || !event.message) return;
126
+ await ctx.telegram.sendMessage(`Result:\n${event.message}`);
127
+ },
128
+ },
129
+ });
130
+ ```
131
+
132
+ ## Human Input
133
+
134
+ Pending Ash input requests render in Telegram:
135
+
136
+ - option requests render as inline keyboard buttons
137
+ - freeform requests render as `ForceReply` prompts
138
+
139
+ Telegram caps `callback_data` at 64 bytes, so Ash stores compact callback ids in durable channel
140
+ state and remaps them to the original Ash input response when the callback query arrives. Freeform
141
+ answers resume when the user replies to the specific prompt message.
142
+
143
+ Callback queries generated by Ash are acknowledged with `answerCallbackQuery` automatically. Other
144
+ callback queries are passed to `onCallbackQuery` when you provide one.
145
+
146
+ ## Attachments
147
+
148
+ Inbound photos and documents become AI SDK file parts with internal `telegram-file:` URLs. When the
149
+ model needs the bytes, the channel calls Telegram `getFile`, downloads the file through the Bot API
150
+ file endpoint, and enforces the channel upload policy.
151
+
152
+ ```ts
153
+ export default telegramChannel({
154
+ uploadPolicy: {
155
+ allowedMediaTypes: ["image/*", "application/pdf"],
156
+ maxBytes: 10 * 1024 * 1024,
157
+ },
158
+ });
159
+ ```
160
+
161
+ V1 supports inbound photos and documents. Polling, inline mode, payments, business-account updates,
162
+ channel posts, stickers, and outbound sandbox-file sharing are not included.
163
+
164
+ ## Proactive Sessions
165
+
166
+ Use `receive(telegram, { message, args, auth })` from a schedule `run` handler, or
167
+ `args.receive(telegram, ...)` from another channel, to start a Telegram session:
168
+
169
+ ```ts
170
+ import { defineSchedule } from "experimental-ash/schedules";
171
+ import telegram from "../channels/telegram.js";
172
+
173
+ export default defineSchedule({
174
+ cron: "0 9 * * 1-5",
175
+ async run({ receive, waitUntil, appAuth }) {
176
+ waitUntil(
177
+ receive(telegram, {
178
+ message: "Post the daily summary.",
179
+ args: {
180
+ chatId: "123456789",
181
+ initialMessage: "Daily summary",
182
+ },
183
+ auth: appAuth,
184
+ }),
185
+ );
186
+ },
187
+ });
188
+ ```
189
+
190
+ `chatId` is required. Pass `messageThreadId` for forum topics. Pass `conversationId` to resume a
191
+ known group conversation, or `initialMessage` to post an anchor message first; those two options are
192
+ mutually exclusive.
193
+
194
+ ## Telegram References
195
+
196
+ - [Telegram Bot API](https://core.telegram.org/bots/api)
197
+ - [setWebhook](https://core.telegram.org/bots/api#setwebhook)
198
+ - [sendMessage](https://core.telegram.org/bots/api#sendmessage)
199
+ - [sendChatAction](https://core.telegram.org/bots/api#sendchataction)
200
+ - [answerCallbackQuery](https://core.telegram.org/bots/api#answercallbackquery)
201
+ - [getFile](https://core.telegram.org/bots/api#getfile)
@@ -30,7 +30,9 @@ for `defineAgent`.
30
30
  - `defineChannel(...)` - HTTP channel entrypoints in `channels/` with `routes`, `state`, `context()`, and typed event handlers (`experimental-ash/channels`)
31
31
  - `defineHook(...)` - lifecycle and stream-event subscriber in `hooks/<slug>.ts` (`experimental-ash/hooks`)
32
32
  - `defineSandbox(...)` - override the agent's single sandbox in `sandbox.ts` (or `sandbox/sandbox.ts` when paired with a `workspace/` folder) (`experimental-ash/sandbox`)
33
- - `defineSchedule(...)` - recurring jobs in `schedules/<name>.ts` or `schedules/<name>.md`; requires `cron` and `markdown`, `channel` is optional (`experimental-ash/schedules`)
33
+ - `defineSchedule(...)` - recurring jobs in `schedules/<name>.ts` or `schedules/<name>.md`;
34
+ TypeScript schedules require `cron` and exactly one of `markdown` or `run`
35
+ (`experimental-ash/schedules`)
34
36
  - `defineSkill(...)` - module-authored skills (`experimental-ash/skills`)
35
37
  - `defineInstructions(...)` - module-authored instructions prompt (`experimental-ash/instructions`)
36
38
  - `defineTool(...)` - typed executable integration in `tools/<name>.ts` (`experimental-ash/tools`)
@@ -109,6 +111,43 @@ Channel and Twilio types exported from `experimental-ash/channels/twilio`:
109
111
  `confidence`, ...)
110
112
  - `verifyTwilioRequest`, `signTwilioRequest` - Ash-owned Twilio webhook signature helpers
111
113
 
114
+ Channel and Telegram types exported from `experimental-ash/channels/telegram`:
115
+
116
+ - `telegramChannel` - Telegram Bot API webhook channel factory for messages, callback queries,
117
+ HITL, attachments, typing indicators, and proactive sessions
118
+ - `telegramContinuationToken` - helper for the channel-local raw token
119
+ (`chatId:messageThreadId:conversationId`)
120
+ - `TelegramChannelConfig` - config type for credentials, route, Bot API overrides, upload policy,
121
+ `botUsername`, hooks, and event handlers
122
+ - `TelegramContext` - pre-dispatch context for `onMessage` and `onCallbackQuery` (`telegram`)
123
+ - `TelegramEventContext` - event-handler context (`telegram`, `session`, plus mutable `state`)
124
+ - `TelegramHandle` - Telegram handle with `request()`, `post()`, `sendMessage()`,
125
+ `startTyping()`, `answerCallbackQuery()`, and `editMessageReplyMarkup()`
126
+ - `TelegramMessage` - parsed inbound message payload (`text`, `caption`, `chat`, `from`,
127
+ `attachments`, reply context, ...)
128
+ - `TelegramCallbackQuery` - parsed callback query payload passed to `onCallbackQuery`
129
+ - `TelegramAttachment` - parsed inbound photo or document metadata
130
+ - `TelegramReceiveArgs` - arguments accepted by proactive `receive(telegram, ...)`
131
+ - `verifyTelegramRequest` - Ash-owned webhook secret-token verification helper
132
+
133
+ Channel and Microsoft Teams types exported from `experimental-ash/channels/teams`:
134
+
135
+ - `teamsChannel` - Teams channel factory for Bot Framework Activity webhooks and Connector delivery
136
+ - `TeamsChannelConfig` - config type for credentials, route, event handlers, message/invoke hooks,
137
+ Adaptive Card version, and opt-in file handling
138
+ - `TeamsContext` - pre-dispatch context for `onMessage` and `onInvoke` (`thread`, `teams`)
139
+ - `TeamsEventContext` - event-handler context (`thread`, `teams`, mutable `state`)
140
+ - `TeamsHandle` - low-level Connector handle with `sendActivity`, `replyToActivity`,
141
+ `updateActivity`, `startTyping`, and `request`
142
+ - `TeamsThread` - conversation-scoped `post`, `update`, `startTyping`, and `mentionUser`
143
+ - `TeamsMessageActivity` / `TeamsInvokeActivity` - parsed inbound Activity payloads
144
+ - `TeamsReceiveArgs` - proactive/cross-channel handoff args requiring `serviceUrl` and
145
+ `conversationId`
146
+ - `teamsContinuationToken` - channel-local Teams continuation-token helper
147
+ - `defaultTeamsAuth` - default Teams actor-to-session-auth projection
148
+ - `verifyTeamsRequest`, `verifyTeamsJwt` - Ash-owned Bot Connector request/JWT verification helpers
149
+ - `sendTeamsActivity`, `replyToTeamsActivity`, `updateTeamsActivity` - Connector REST helpers
150
+
112
151
  Channel types exported from `experimental-ash/channels`:
113
152
 
114
153
  - `defineChannel` - channel primitive with `routes`, `state`, `context()`, and event handlers
@@ -138,6 +177,7 @@ import { defineChannel, POST, GET } from "experimental-ash/channels";
138
177
  import { ashChannel } from "experimental-ash/channels/ash";
139
178
  import { vercelOidc } from "experimental-ash/channels/auth";
140
179
  import { slackChannel } from "experimental-ash/channels/slack";
180
+ import { telegramChannel } from "experimental-ash/channels/telegram";
141
181
  ```
142
182
 
143
183
  Inside a route handler, the helpers object exposes:
@@ -1 +1 @@
1
- import{createLogger}from"#internal/logging.js";var log=createLogger(`channel.adapter`);function defaultDeliverResult(e){if(e.message!==void 0)return{inputResponses:e.inputResponses,message:e.message,modelContext:e.modelContext};if(e.inputResponses!==void 0&&e.inputResponses.length>0)return{inputResponses:e.inputResponses,modelContext:e.modelContext};if(e.modelContext!==void 0&&e.modelContext.length>0)return{modelContext:e.modelContext}}function getAdapterKind(e){return e.kind}async function callAdapterEventHandler(e,t,n){let r=e[t.type];if(r===void 0)return t;try{await r(`data`in t?t.data:void 0,n)}catch(n){log.error(`adapter event handler threw — event swallowed`,{adapterKind:getAdapterKind(e),eventType:t.type,error:n})}return t}export{callAdapterEventHandler,defaultDeliverResult,getAdapterKind};
1
+ import{createLogger}from"#internal/logging.js";const log=createLogger(`channel.adapter`);function defaultDeliverResult(e){if(e.message!==void 0)return{inputResponses:e.inputResponses,message:e.message,modelContext:e.modelContext};if(e.inputResponses!==void 0&&e.inputResponses.length>0)return{inputResponses:e.inputResponses,modelContext:e.modelContext};if(e.modelContext!==void 0&&e.modelContext.length>0)return{modelContext:e.modelContext}}function getAdapterKind(e){return e.kind}async function callAdapterEventHandler(e,t,n){let r=e[t.type];if(r===void 0)return t;try{await r(`data`in t?t.data:void 0,n)}catch(n){log.error(`adapter event handler threw — event swallowed`,{adapterKind:getAdapterKind(e),eventType:t.type,error:n})}return t}export{callAdapterEventHandler,defaultDeliverResult,getAdapterKind};
@@ -1 +1 @@
1
- var CHANNEL_SENTINEL=`ash:channel`;function isCompiledChannel(e){return typeof e==`object`&&!!e&&e.__kind===`ash:channel`}export{CHANNEL_SENTINEL,isCompiledChannel};
1
+ const CHANNEL_SENTINEL=`ash:channel`;function isCompiledChannel(e){return typeof e==`object`&&!!e&&e.__kind===`ash:channel`}export{CHANNEL_SENTINEL,isCompiledChannel};
@@ -1 +1 @@
1
- var HTTP_ADAPTER_KIND=`http`,HTTP_ADAPTER={kind:HTTP_ADAPTER_KIND};export{HTTP_ADAPTER,HTTP_ADAPTER_KIND};
1
+ const HTTP_ADAPTER_KIND=`http`,HTTP_ADAPTER={kind:HTTP_ADAPTER_KIND};export{HTTP_ADAPTER,HTTP_ADAPTER_KIND};
@@ -1 +1 @@
1
- import{createSession}from"#channel/session.js";import{createCrossChannelReceiveFn,toCrossChannelTargets}from"#channel/cross-channel-receive.js";import{expectFunction}from"#internal/authored-module.js";var SCHEDULE_APP_AUTH={attributes:{},authenticator:`app`,principalId:`ash:app`,principalType:`runtime`},SCHEDULE_ADAPTER_KIND=`schedule`,SCHEDULE_ADAPTER={kind:SCHEDULE_ADAPTER_KIND},ScheduleDispatcher=class{runtime;channels;constructor(e){this.runtime=e.runtime,this.channels=e.channels}async trigger(e){let r=[],a=[],o=createCrossChannelReceiveFn(this.runtime,toCrossChannelTargets(this.channels)),s={appAuth:SCHEDULE_APP_AUTH,receive:async(e,t)=>{let n=await o(e,t);return r.push(n),n},waitUntil(e){a.push(e)}};if(e.run)await e.run(s);else if(e.markdown!==void 0){let t=await this.runMarkdown(e.markdown);r.push(t)}else throw Error(`Schedule "${e.scheduleId}" has neither "run" nor "markdown" — at least one must be set.`);return{sessions:r,waitUntilTasks:a}}async runMarkdown(t){let n=await this.runtime.run({adapter:SCHEDULE_ADAPTER,auth:SCHEDULE_APP_AUTH,input:{message:t},mode:`task`});return createSession(n.sessionId,n.continuationToken,this.runtime)}};function expectScheduleRun(e,t,n){let i=e;if(typeof i!=`object`||!i)throw Error(`Schedule export "${n??`default`}" from "${t}" must be an object.`);return expectFunction(i.run,`Expected the schedule export "${n??`default`}" from "${t}" to export a \`run\` handler function.`)}export{SCHEDULE_ADAPTER,SCHEDULE_ADAPTER_KIND,SCHEDULE_APP_AUTH,ScheduleDispatcher,expectScheduleRun};
1
+ import{createSession}from"#channel/session.js";import{createCrossChannelReceiveFn,toCrossChannelTargets}from"#channel/cross-channel-receive.js";import{expectFunction}from"#internal/authored-module.js";const SCHEDULE_APP_AUTH={attributes:{},authenticator:`app`,principalId:`ash:app`,principalType:`runtime`},SCHEDULE_ADAPTER_KIND=`schedule`,SCHEDULE_ADAPTER={kind:SCHEDULE_ADAPTER_KIND};var ScheduleDispatcher=class{runtime;channels;constructor(e){this.runtime=e.runtime,this.channels=e.channels}async trigger(e){let r=[],a=[],o=createCrossChannelReceiveFn(this.runtime,toCrossChannelTargets(this.channels)),s={appAuth:SCHEDULE_APP_AUTH,receive:async(e,t)=>{let n=await o(e,t);return r.push(n),n},waitUntil(e){a.push(e)}};if(e.run)await e.run(s);else if(e.markdown!==void 0){let t=await this.runMarkdown(e.markdown);r.push(t)}else throw Error(`Schedule "${e.scheduleId}" has neither "run" nor "markdown" — at least one must be set.`);return{sessions:r,waitUntilTasks:a}}async runMarkdown(t){let n=await this.runtime.run({adapter:SCHEDULE_ADAPTER,auth:SCHEDULE_APP_AUTH,input:{message:t},mode:`task`});return createSession(n.sessionId,n.continuationToken,this.runtime)}};function expectScheduleRun(e,t,n){let i=e;if(typeof i!=`object`||!i)throw Error(`Schedule export "${n??`default`}" from "${t}" must be an object.`);return expectFunction(i.run,`Expected the schedule export "${n??`default`}" from "${t}" to export a \`run\` handler function.`)}export{SCHEDULE_ADAPTER,SCHEDULE_ADAPTER_KIND,SCHEDULE_APP_AUTH,ScheduleDispatcher,expectScheduleRun};
@@ -1 +1 @@
1
- import{createSession}from"#channel/session.js";import{createErrorId,createLogger}from"#internal/logging.js";import{isRuntimeNoActiveSessionError}from"#execution/runtime-errors.js";import{serializeUrlFilePart}from"#internal/attachments/url-refs.js";import{toErrorMessage}from"#shared/errors.js";var log=createLogger(`channel.send`);function createSendFn(n,r,i){return async(a,o)=>{let s=o.auth,c=o.callback,l=o.mode??`conversation`,u=o.state,d=o.continuationToken,f=`${i}:${d}`,{message:p,inputResponses:m,modelContext:h}=normalizeSendInput(a),g=serializeUrlFilePartsInMessage(p);try{let{sessionId:t}=await n.deliver({auth:s,continuationToken:f,payload:{inputResponses:m,message:g,modelContext:h}});return createSession(t,d,n)}catch(e){isRuntimeNoActiveSessionError(e)||log.warn(`deliver failed, falling back to starting a new session`,{continuationToken:f,errorId:createErrorId(),message:toErrorMessage(e)})}if(m&&m.length>0)throw Error(`Cannot deliver inputResponses — the target session was not found via continuation token.`);let _=u?{...r,state:{...r.state,...u}}:r;return createSession((await n.run({adapter:_,auth:s,capabilities:l===`conversation`?{requestInput:!0}:void 0,callback:c,continuationToken:f,input:{message:g??``,modelContext:h},mode:l})).sessionId,d,n)}}function serializeUrlFilePartsInMessage(e){if(e===void 0||typeof e==`string`)return e;let t=!1,n=e.map(e=>e.type===`file`&&e.data instanceof URL&&e.data.protocol!==`data:`?(t=!0,{...e,data:serializeUrlFilePart(e.data)}):e);return t?n:e}function normalizeSendInput(e){return typeof e==`string`||Array.isArray(e)?{message:e}:e}export{createSendFn};
1
+ import{createSession}from"#channel/session.js";import{createErrorId,createLogger}from"#internal/logging.js";import{isRuntimeNoActiveSessionError}from"#execution/runtime-errors.js";import{serializeUrlFilePart}from"#internal/attachments/url-refs.js";import{toErrorMessage}from"#shared/errors.js";const log=createLogger(`channel.send`);function createSendFn(n,r,i){return async(a,o)=>{let s=o.auth,c=o.callback,l=o.mode??`conversation`,u=o.state,d=o.continuationToken,f=`${i}:${d}`,{message:p,inputResponses:m,modelContext:h}=normalizeSendInput(a),g=serializeUrlFilePartsInMessage(p);try{let{sessionId:t}=await n.deliver({auth:s,continuationToken:f,payload:{inputResponses:m,message:g,modelContext:h}});return createSession(t,d,n)}catch(e){isRuntimeNoActiveSessionError(e)||log.warn(`deliver failed, falling back to starting a new session`,{continuationToken:f,errorId:createErrorId(),message:toErrorMessage(e)})}if(m&&m.length>0)throw Error(`Cannot deliver inputResponses — the target session was not found via continuation token.`);let _=u?{...r,state:{...r.state,...u}}:r;return createSession((await n.run({adapter:_,auth:s,capabilities:l===`conversation`?{requestInput:!0}:void 0,callback:c,continuationToken:f,input:{message:g??``,modelContext:h},mode:l})).sessionId,d,n)}}function serializeUrlFilePartsInMessage(e){if(e===void 0||typeof e==`string`)return e;let t=!1,n=e.map(e=>e.type===`file`&&e.data instanceof URL&&e.data.protocol!==`data:`?(t=!0,{...e,data:serializeUrlFilePart(e.data)}):e);return t?n:e}function normalizeSendInput(e){return typeof e==`string`||Array.isArray(e)?{message:e}:e}export{createSendFn};
@@ -1 +1 @@
1
- import{z}from"#compiled/zod/index.js";import{createAshCallbackRoutePath}from"#protocol/routes.js";var sessionCallbackSchema=z.object({callId:z.string().min(1),subagentName:z.string().min(1),token:z.string().min(1),url:z.string().min(1)}).strict().superRefine((e,t)=>{let n;try{n=new URL(e.url)}catch{t.addIssue({code:`custom`,message:`Callback url must be absolute.`,path:[`url`]});return}readCallbackUrlToken(n)!==e.token&&t.addIssue({code:`custom`,message:`Callback url token must match callback token.`,path:[`url`]})});function parseSessionCallback(e){let t=sessionCallbackSchema.safeParse(e);return t.success?{callback:t.data,ok:!0}:{cause:t.error,message:formatSessionCallbackParseError(t.error),ok:!1}}function readCallbackUrlToken(e){let n=createAshCallbackRoutePath(``);if(!e.pathname.startsWith(n))return null;let r=e.pathname.slice(n.length);if(r.length===0||r.includes(`/`))return null;try{return decodeURIComponent(r)}catch{return null}}function formatSessionCallbackParseError(e){return`Invalid callback metadata: ${e.issues.map(e=>`${e.path.length===0?`callback`:`callback.${e.path.join(`.`)}`}: ${e.message}`).join(`; `)}`}export{parseSessionCallback};
1
+ import{z}from"#compiled/zod/index.js";import{createAshCallbackRoutePath}from"#protocol/routes.js";const sessionCallbackSchema=z.object({callId:z.string().min(1),subagentName:z.string().min(1),token:z.string().min(1),url:z.string().min(1)}).strict().superRefine((e,t)=>{let n;try{n=new URL(e.url)}catch{t.addIssue({code:`custom`,message:`Callback url must be absolute.`,path:[`url`]});return}readCallbackUrlToken(n)!==e.token&&t.addIssue({code:`custom`,message:`Callback url token must match callback token.`,path:[`url`]})});function parseSessionCallback(e){let t=sessionCallbackSchema.safeParse(e);return t.success?{callback:t.data,ok:!0}:{cause:t.error,message:formatSessionCallbackParseError(t.error),ok:!1}}function readCallbackUrlToken(e){let n=createAshCallbackRoutePath(``);if(!e.pathname.startsWith(n))return null;let r=e.pathname.slice(n.length);if(r.length===0||r.includes(`/`))return null;try{return decodeURIComponent(r)}catch{return null}}function formatSessionCallbackParseError(e){return`Invalid callback metadata: ${e.issues.map(e=>`${e.path.length===0?`callback`:`callback.${e.path.join(`.`)}`}: ${e.message}`).join(`; `)}`}export{parseSessionCallback};
@@ -1 +1 @@
1
- import{AuthKey,ContinuationTokenKey,InitiatorAuthKey,SessionIdKey}from"#context/seed-keys.js";function createSession(e,t,n){return{id:e,continuationToken:t,async getEventStream(t){return n.getEventStream(e,t)}}}function createGetSessionFn(e){return t=>createSession(t,``,e)}function buildSessionHandle(i){return{get id(){return i.get(SessionIdKey)??``},get continuationToken(){return i.get(ContinuationTokenKey)??``},get auth(){return i.get(AuthKey)??null},get initiatorAuth(){return i.get(InitiatorAuthKey)??null},setContinuationToken(e){let n=i.get(ContinuationTokenKey)??``,r=namespaceContinuationToken(n,e);n!==r&&i.set(ContinuationTokenKey,r)}}}function namespaceContinuationToken(e,t){let n=e.indexOf(`:`);if(n<=0)throw Error(`Cannot set session continuation token without an existing namespaced continuation token. Start the session with a placeholder continuationToken.`);return`${e.slice(0,n+1)}${t}`}export{buildSessionHandle,createGetSessionFn,createSession};
1
+ import{AuthKey,ContinuationTokenKey,InitiatorAuthKey,SessionIdKey}from"#context/keys.js";function createSession(e,t,n){return{id:e,continuationToken:t,async getEventStream(t){return n.getEventStream(e,t)}}}function createGetSessionFn(e){return t=>createSession(t,``,e)}function buildSessionHandle(i){return{get id(){return i.get(SessionIdKey)??``},get continuationToken(){return i.get(ContinuationTokenKey)??``},get auth(){return i.get(AuthKey)??null},get initiatorAuth(){return i.get(InitiatorAuthKey)??null},setContinuationToken(e){let n=i.get(ContinuationTokenKey)??``,r=namespaceContinuationToken(n,e);n!==r&&i.set(ContinuationTokenKey,r)}}}function namespaceContinuationToken(e,t){let n=e.indexOf(`:`);if(n<=0)throw Error(`Cannot set session continuation token without an existing namespaced continuation token. Start the session with a placeholder continuationToken.`);return`${e.slice(0,n+1)}${t}`}export{buildSessionHandle,createGetSessionFn,createSession};
@@ -1,3 +1,3 @@
1
- import{isAshProject}from"../../packages/ash-scaffold/src/project.js";import{SLACK_CHANNEL_DEFAULT_ROUTE,ensureChannel,listAuthoredChannels}from"../../packages/ash-scaffold/src/channels.js";import"../../packages/ash-scaffold/src/index.js";import{relative}from"node:path";import{createInterface}from"node:readline/promises";var NOT_AN_AGENT_MESSAGE="No Ash agent in this directory. Run `pnpm create experimental-ash-agent`, then run this command from inside the new project.",KNOWN_CHANNEL_KINDS=[`slack`];function isChannelKind(e){return KNOWN_CHANNEL_KINDS.includes(e)}function parseChannelKind(e){if(!isChannelKind(e))throw Error(`Unknown channel kind "${e}". Known: ${KNOWN_CHANNEL_KINDS.join(`, `)}.`);return e}async function promptChannelKind(){if(!process.stdin.isTTY||!process.stdout.isTTY)throw Error("Pass a channel kind: `ash channels add slack`.");let e=createInterface({input:process.stdin,output:process.stdout});try{let t=(await e.question(`Channel to add (slack): `)).trim();return t.length===0?`slack`:parseChannelKind(t)}finally{e.close()}}function renderSlackNextSteps(e){return[`Next steps:`,` pnpm i`,` vercel deploy --prod`,` # If Connect returns a different UID, use it below and in agent/channels/slack.ts.`,` vercel connect create slack --name ${e} --triggers`,` vercel connect detach slack/${e} --yes`,` vercel connect attach slack/${e} --triggers --trigger-path ${SLACK_CHANNEL_DEFAULT_ROUTE} --yes`].join(`
1
+ import{isAshProject}from"../../packages/ash-scaffold/src/project.js";import{SLACK_CHANNEL_DEFAULT_ROUTE,ensureChannel,listAuthoredChannels}from"../../packages/ash-scaffold/src/channels.js";import"../../packages/ash-scaffold/src/index.js";import{relative}from"node:path";import{createInterface}from"node:readline/promises";const NOT_AN_AGENT_MESSAGE="No Ash agent in this directory. Run `pnpm create experimental-ash-agent`, then run this command from inside the new project.",KNOWN_CHANNEL_KINDS=[`slack`];function isChannelKind(e){return KNOWN_CHANNEL_KINDS.includes(e)}function parseChannelKind(e){if(!isChannelKind(e))throw Error(`Unknown channel kind "${e}". Known: ${KNOWN_CHANNEL_KINDS.join(`, `)}.`);return e}async function promptChannelKind(){if(!process.stdin.isTTY||!process.stdout.isTTY)throw Error("Pass a channel kind: `ash channels add slack`.");let e=createInterface({input:process.stdin,output:process.stdout});try{let t=(await e.question(`Channel to add (slack): `)).trim();return t.length===0?`slack`:parseChannelKind(t)}finally{e.close()}}function renderSlackNextSteps(e){return[`Next steps:`,` pnpm i`,` vercel deploy --prod`,` # If Connect returns a different UID, use it below and in agent/channels/slack.ts.`,` vercel connect create slack --name ${e} --triggers`,` vercel connect detach slack/${e} --yes`,` vercel connect attach slack/${e} --triggers --trigger-path ${SLACK_CHANNEL_DEFAULT_ROUTE} --yes`].join(`
2
2
  `)}function renderExistingSlackChannelNextSteps(e){return[`Next steps:`,` Review ${e} for the configured Slack connector UID.`,` Run Vercel Connect commands only for the UID already used by that file.`].join(`
3
3
  `)}function formatProjectPath(e,t){let n=relative(e,t);return n.length===0||n.startsWith(`..`)?t:n}function logPackageJsonMutations(e,t,n){for(let r of n.packageJsonUpdated)e.log(`Updated ${formatProjectPath(t,r.path)} with ${r.dependencies.join(`, `)}.`)}function assertUnhandledChannelMutation(e){throw Error(`Unhandled channel mutation result: ${JSON.stringify(e)}`)}async function runChannelsAddCommand(t,r,i){if(!await isAshProject(r)){t.error(NOT_AN_AGENT_MESSAGE),process.exitCode=1;return}try{let e=i.kind===void 0?await promptChannelKind():parseChannelKind(i.kind),a=await ensureChannel({projectRoot:r,kind:e,force:i.options.force});switch(logPackageJsonMutations(t,r,a),a.action){case`created`:t.log(`Scaffolded channel: ${e}`),t.log(renderSlackNextSteps(a.slackConnectorSlug));break;case`overwritten`:t.log(`Overwrote channel: ${e}`),t.log(renderSlackNextSteps(a.slackConnectorSlug));break;case`skipped`:{let n=a.filesSkipped[0];t.log(`Channel "${e}" already exists; left existing files unchanged.`),t.log(renderExistingSlackChannelNextSteps(formatProjectPath(r,n)));break}default:assertUnhandledChannelMutation(a)}}catch(e){t.error(e instanceof Error?e.message:String(e)),process.exitCode=1}}async function runChannelsListCommand(t,n,i){if(!await isAshProject(n)){t.error(NOT_AN_AGENT_MESSAGE),process.exitCode=1;return}let a=await listAuthoredChannels(n);if(i.json){t.log(JSON.stringify({channels:a},null,2));return}if(a.length===0){t.log("No channels defined. Run `ash channels add slack` to add one.");return}for(let e of a)t.log(e)}export{runChannelsAddCommand,runChannelsListCommand};
@@ -1 +1 @@
1
- import{join,resolve}from"node:path";import{readFileSync}from"node:fs";import{parseEnv}from"node:util";import{isObject}from"#shared/guards.js";var DEVELOPMENT_ENV_FILE_NAMES=[`.env.development.local`,`.env.local`,`.env.development`,`.env`];function isMissingEnvironmentFileError(e){return isObject(e)&&e.code===`ENOENT`}var developmentEnvironmentLoaders=new Map;function getDevelopmentEnvironmentFilePaths(n){let r=resolve(n);return DEVELOPMENT_ENV_FILE_NAMES.map(t=>join(r,t))}function loadDevelopmentEnvironmentFiles(e){getDevelopmentEnvironmentLoader(e).reload()}function getDevelopmentEnvironmentLoader(e){let n=resolve(e),r=developmentEnvironmentLoaders.get(n);if(r!==void 0)return r;let i=createDevelopmentEnvironmentLoader(n);return developmentEnvironmentLoaders.set(n,i),i}function createDevelopmentEnvironmentLoader(e){let t=new Set(Object.keys(process.env)),n=new Map;return{reload(){let r=readDevelopmentEnvironmentValues(e);for(let[e,i]of n)r.has(e)||t.has(e)||(process.env[e]===i&&delete process.env[e],n.delete(e));for(let[e,i]of r)t.has(e)||(process.env[e]=i,n.set(e,i))}}}function readDevelopmentEnvironmentValues(t){let i=new Map;for(let o of[...DEVELOPMENT_ENV_FILE_NAMES].reverse())try{let a=parseEnv(readFileSync(join(t,o),`utf8`));for(let[e,t]of Object.entries(a))t!==void 0&&i.set(e,t)}catch(e){if(!isMissingEnvironmentFileError(e))throw e}return i}export{DEVELOPMENT_ENV_FILE_NAMES,getDevelopmentEnvironmentFilePaths,loadDevelopmentEnvironmentFiles};
1
+ import{join,resolve}from"node:path";import{readFileSync}from"node:fs";import{parseEnv}from"node:util";import{isObject}from"#shared/guards.js";const DEVELOPMENT_ENV_FILE_NAMES=[`.env.development.local`,`.env.local`,`.env.development`,`.env`];function isMissingEnvironmentFileError(e){return isObject(e)&&e.code===`ENOENT`}const developmentEnvironmentLoaders=new Map;function getDevelopmentEnvironmentFilePaths(n){let r=resolve(n);return DEVELOPMENT_ENV_FILE_NAMES.map(t=>join(r,t))}function loadDevelopmentEnvironmentFiles(e){getDevelopmentEnvironmentLoader(e).reload()}function getDevelopmentEnvironmentLoader(e){let n=resolve(e),r=developmentEnvironmentLoaders.get(n);if(r!==void 0)return r;let i=createDevelopmentEnvironmentLoader(n);return developmentEnvironmentLoaders.set(n,i),i}function createDevelopmentEnvironmentLoader(e){let t=new Set(Object.keys(process.env)),n=new Map;return{reload(){let r=readDevelopmentEnvironmentValues(e);for(let[e,i]of n)r.has(e)||t.has(e)||(process.env[e]===i&&delete process.env[e],n.delete(e));for(let[e,i]of r)t.has(e)||(process.env[e]=i,n.set(e,i))}}}function readDevelopmentEnvironmentValues(t){let i=new Map;for(let o of[...DEVELOPMENT_ENV_FILE_NAMES].reverse())try{let a=parseEnv(readFileSync(join(t,o),`utf8`));for(let[e,t]of Object.entries(a))t!==void 0&&i.set(e,t)}catch(e){if(!isMissingEnvironmentFileError(e))throw e}return i}export{DEVELOPMENT_ENV_FILE_NAMES,getDevelopmentEnvironmentFilePaths,loadDevelopmentEnvironmentFiles};
@@ -1 +1 @@
1
- import{renderCliTaggedLine}from"#cli/ui/output.js";import{resolveTextToResponse}from"#channel/resolve-text.js";var ESCAPED_RUNTIME_INPUT_PROMPT=Symbol(`ash.cli.runtime-input.escaped`);function extractPendingRuntimeInputRequests(e){for(let t=e.length-1;t>=0;--t){let n=e[t];if(n?.type===`input.requested`)return n.data.requests}return[]}async function promptForRuntimeInputRequests(t){let n=[];t.print(renderCliTaggedLine(t.theme,{message:`pending input request${t.requests.length===1?``:`s`}: reply now, press Escape, or type "skip" to return to the normal prompt`,tag:`input`,tone:`info`}));for(let e of t.requests){let r=await promptForRuntimeInputRequest({ask:t.ask,print:t.print,request:e,theme:t.theme});if(r.kind!==`submitted`)return r;n.push(r.inputResponse)}return{inputResponses:n,kind:`submitted`}}function isApprovalRequest(e){return e.display===`confirmation`}async function promptForRuntimeInputRequest(e){return isApprovalRequest(e.request)?await promptForApprovalInputRequest({ask:e.ask,print:e.print,request:e.request,theme:e.theme}):await promptForQuestionInputRequest({ask:e.ask,print:e.print,request:e.request,theme:e.theme})}async function promptForApprovalInputRequest(t){for(t.print(renderCliTaggedLine(t.theme,{message:`approve tool "${t.request.action.toolName}"? (yes/no)`,tag:`approval`,tone:`warning`})),t.print(renderCliTaggedLine(t.theme,{message:JSON.stringify(t.request.action.input,null,2),tag:`tool`,tone:`muted`}));;){let r=await t.ask(`approval> `);if(r===void 0)return{kind:`aborted`};if(r===ESCAPED_RUNTIME_INPUT_PROMPT)return{kind:`deferred`};let i=r.trim().toLowerCase();if(i===`skip`||i===`/skip`)return{kind:`deferred`};if(i===`a`||i===`approve`||i===`y`||i===`yes`)return{inputResponse:{optionId:`approve`,requestId:t.request.requestId},kind:`submitted`};if(i===`d`||i===`deny`||i===`n`||i===`no`)return{inputResponse:{optionId:`deny`,requestId:t.request.requestId},kind:`submitted`};t.print(renderCliTaggedLine(t.theme,{message:`enter "yes" to approve, "no" to deny, press Escape, or type "skip" to return to the normal prompt`,tag:`input`,tone:`warning`}))}}async function promptForQuestionInputRequest(r){r.print(renderCliTaggedLine(r.theme,{message:r.request.prompt,tag:`question`,tone:`info`}));for(let[t,n]of(r.request.options??[]).entries())r.print(renderCliTaggedLine(r.theme,{message:`${t+1}. ${n.label}${n.description===void 0?``:` - ${n.description}`}`,tag:`option`,tone:`muted`}));let i=r.request.allowFreeform===!0||(r.request.options?.length??0)===0;for(;;){let a=await r.ask(`answer> `);if(a===void 0)return{kind:`aborted`};if(a===ESCAPED_RUNTIME_INPUT_PROMPT)return{kind:`deferred`};let o=a.trim();if(o===`skip`||o===`/skip`)return{kind:`deferred`};let s=resolveTextToResponse(o,r.request);if(s!==void 0)return{inputResponse:s,kind:`submitted`};r.print(renderCliTaggedLine(r.theme,{message:r.request.options===void 0||r.request.options.length===0?`enter a response, press Escape, or type "skip" to return to the normal prompt`:i?`enter an option number/id, freeform text, press Escape, or type "skip" to return to the normal prompt`:`enter an option number/id, press Escape, or type "skip" to return to the normal prompt`,tag:`input`,tone:`warning`}))}}export{ESCAPED_RUNTIME_INPUT_PROMPT,extractPendingRuntimeInputRequests,promptForRuntimeInputRequests};
1
+ import{renderCliTaggedLine}from"#cli/ui/output.js";import{resolveTextToResponse}from"#channel/resolve-text.js";const ESCAPED_RUNTIME_INPUT_PROMPT=Symbol(`ash.cli.runtime-input.escaped`);function extractPendingRuntimeInputRequests(e){for(let t=e.length-1;t>=0;--t){let n=e[t];if(n?.type===`input.requested`)return n.data.requests}return[]}async function promptForRuntimeInputRequests(t){let n=[];t.print(renderCliTaggedLine(t.theme,{message:`pending input request${t.requests.length===1?``:`s`}: reply now, press Escape, or type "skip" to return to the normal prompt`,tag:`input`,tone:`info`}));for(let e of t.requests){let r=await promptForRuntimeInputRequest({ask:t.ask,print:t.print,request:e,theme:t.theme});if(r.kind!==`submitted`)return r;n.push(r.inputResponse)}return{inputResponses:n,kind:`submitted`}}function isApprovalRequest(e){return e.display===`confirmation`}async function promptForRuntimeInputRequest(e){return isApprovalRequest(e.request)?await promptForApprovalInputRequest({ask:e.ask,print:e.print,request:e.request,theme:e.theme}):await promptForQuestionInputRequest({ask:e.ask,print:e.print,request:e.request,theme:e.theme})}async function promptForApprovalInputRequest(t){for(t.print(renderCliTaggedLine(t.theme,{message:`approve tool "${t.request.action.toolName}"? (yes/no)`,tag:`approval`,tone:`warning`})),t.print(renderCliTaggedLine(t.theme,{message:JSON.stringify(t.request.action.input,null,2),tag:`tool`,tone:`muted`}));;){let r=await t.ask(`approval> `);if(r===void 0)return{kind:`aborted`};if(r===ESCAPED_RUNTIME_INPUT_PROMPT)return{kind:`deferred`};let i=r.trim().toLowerCase();if(i===`skip`||i===`/skip`)return{kind:`deferred`};if(i===`a`||i===`approve`||i===`y`||i===`yes`)return{inputResponse:{optionId:`approve`,requestId:t.request.requestId},kind:`submitted`};if(i===`d`||i===`deny`||i===`n`||i===`no`)return{inputResponse:{optionId:`deny`,requestId:t.request.requestId},kind:`submitted`};t.print(renderCliTaggedLine(t.theme,{message:`enter "yes" to approve, "no" to deny, press Escape, or type "skip" to return to the normal prompt`,tag:`input`,tone:`warning`}))}}async function promptForQuestionInputRequest(r){r.print(renderCliTaggedLine(r.theme,{message:r.request.prompt,tag:`question`,tone:`info`}));for(let[t,n]of(r.request.options??[]).entries())r.print(renderCliTaggedLine(r.theme,{message:`${t+1}. ${n.label}${n.description===void 0?``:` - ${n.description}`}`,tag:`option`,tone:`muted`}));let i=r.request.allowFreeform===!0||(r.request.options?.length??0)===0;for(;;){let a=await r.ask(`answer> `);if(a===void 0)return{kind:`aborted`};if(a===ESCAPED_RUNTIME_INPUT_PROMPT)return{kind:`deferred`};let o=a.trim();if(o===`skip`||o===`/skip`)return{kind:`deferred`};let s=resolveTextToResponse(o,r.request);if(s!==void 0)return{inputResponse:s,kind:`submitted`};r.print(renderCliTaggedLine(r.theme,{message:r.request.options===void 0||r.request.options.length===0?`enter a response, press Escape, or type "skip" to return to the normal prompt`:i?`enter an option number/id, freeform text, press Escape, or type "skip" to return to the normal prompt`:`enter an option number/id, press Escape, or type "skip" to return to the normal prompt`,tag:`input`,tone:`warning`}))}}export{ESCAPED_RUNTIME_INPUT_PROMPT,extractPendingRuntimeInputRequests,promptForRuntimeInputRequests};