experimental-ash 0.28.0 → 0.29.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.
- package/CHANGELOG.md +19 -0
- package/README.md +1 -0
- package/dist/docs/internals/hooks.md +1 -1
- package/dist/docs/public/cli-build-and-debugging.md +2 -0
- package/dist/docs/public/getting-started.md +1 -0
- package/dist/src/channel/adapter.js +1 -1
- package/dist/src/channel/compiled-channel.js +1 -1
- package/dist/src/channel/http.js +1 -1
- package/dist/src/channel/schedule.js +1 -1
- package/dist/src/channel/send.js +1 -1
- package/dist/src/channel/session-callback.js +1 -1
- package/dist/src/channel/session.js +1 -1
- package/dist/src/cli/commands/channels.js +1 -1
- package/dist/src/cli/dev/environment.js +1 -1
- package/dist/src/cli/dev/input-requests.js +1 -1
- package/dist/src/cli/dev/repl.js +1 -1
- package/dist/src/cli/dev/terminal.js +1 -1
- package/dist/src/cli/dev/url.js +1 -1
- package/dist/src/cli/run.d.ts +9 -0
- package/dist/src/cli/run.js +1 -1
- package/dist/src/compiler/artifacts.js +1 -1
- package/dist/src/compiler/manifest.js +1 -1
- package/dist/src/compiler/model-catalog.js +1 -1
- package/dist/src/compiler/module-map.js +1 -1
- package/dist/src/compiler/normalize-subagent.js +1 -1
- package/dist/src/compiler/remote-agent-node.js +1 -1
- package/dist/src/compiler/workspace-resources.js +1 -1
- package/dist/src/context/accessors.js +1 -1
- package/dist/src/context/container.js +1 -1
- package/dist/src/context/hook-lifecycle.d.ts +3 -3
- package/dist/src/context/hook-lifecycle.js +1 -1
- package/dist/src/context/key.js +1 -1
- package/dist/src/context/keys.d.ts +31 -10
- package/dist/src/context/keys.js +1 -1
- package/dist/src/context/node.js +1 -1
- package/dist/src/context/providers/connection.js +1 -1
- package/dist/src/context/providers/sandbox.js +1 -1
- package/dist/src/context/providers/session.js +1 -1
- package/dist/src/context/run-step.js +1 -1
- package/dist/src/context/serialize.js +1 -1
- package/dist/src/discover/connections.js +1 -1
- package/dist/src/discover/diagnostics.js +1 -1
- package/dist/src/discover/discover-subagent.js +1 -1
- package/dist/src/discover/filesystem.js +1 -1
- package/dist/src/discover/grammar.js +1 -1
- package/dist/src/discover/lib.js +1 -1
- package/dist/src/discover/manifest.js +1 -1
- package/dist/src/discover/sandbox.js +1 -1
- package/dist/src/discover/schedules.js +1 -1
- package/dist/src/discover/skills.js +1 -1
- package/dist/src/evals/runner/discover.js +1 -1
- package/dist/src/evals/runner/execute-suite.js +1 -1
- package/dist/src/evals/runner/reporters/braintrust.js +1 -1
- package/dist/src/evals/scores/index.js +1 -1
- package/dist/src/execution/await-authorization-orchestrator.js +1 -1
- package/dist/src/execution/connection-auth-steps.js +1 -1
- package/dist/src/execution/runtime-context.d.ts +1 -1
- package/dist/src/execution/runtime-context.js +1 -1
- package/dist/src/execution/sandbox/bindings/local.js +1 -1
- package/dist/src/execution/sandbox/bindings/vercel.js +1 -1
- package/dist/src/execution/sandbox/glob-tool.js +1 -1
- package/dist/src/execution/sandbox/grep-tool.js +1 -1
- package/dist/src/execution/sandbox/prewarm.d.ts +12 -2
- package/dist/src/execution/sandbox/prewarm.js +1 -1
- package/dist/src/execution/sandbox/read-file-tool.js +1 -1
- package/dist/src/execution/sandbox/require-sandbox.js +1 -1
- package/dist/src/execution/sandbox/ripgrep-probe.js +1 -1
- package/dist/src/execution/sandbox/truncate-output.js +1 -1
- package/dist/src/execution/session-callback-step.js +1 -1
- package/dist/src/execution/session.js +1 -1
- package/dist/src/execution/subagent-adapter.js +1 -1
- package/dist/src/execution/tool-compaction.js +1 -1
- package/dist/src/execution/turn-workflow.js +1 -1
- package/dist/src/execution/web-fetch/html.js +1 -1
- package/dist/src/execution/web-fetch/tool.js +1 -1
- package/dist/src/execution/workflow-entry.js +1 -1
- package/dist/src/execution/workflow-runtime.js +1 -1
- package/dist/src/execution/workflow-steps.js +1 -1
- package/dist/src/harness/attachment-staging.js +1 -1
- package/dist/src/harness/compaction.js +2 -2
- package/dist/src/harness/emission.js +1 -1
- package/dist/src/harness/input-requests.js +1 -1
- package/dist/src/harness/instrumentation-config.js +1 -1
- package/dist/src/harness/model-call-error.js +1 -1
- package/dist/src/harness/otel-integration.js +1 -1
- package/dist/src/harness/prompt-cache.js +1 -1
- package/dist/src/harness/provider-tools.js +1 -1
- package/dist/src/harness/proxy-input-requests.js +1 -1
- package/dist/src/harness/runtime-actions.js +1 -1
- package/dist/src/harness/step-hooks.js +1 -1
- package/dist/src/harness/tool-loop.js +1 -1
- package/dist/src/harness/tool-result-pruning.js +1 -1
- package/dist/src/internal/application/cache-metadata.js +1 -1
- package/dist/src/internal/application/compiled-artifacts.js +1 -1
- package/dist/src/internal/application/import-specifier.js +1 -1
- package/dist/src/internal/application/package.js +1 -1
- package/dist/src/internal/attachments/refs.js +1 -1
- package/dist/src/internal/attachments/sandbox-refs.js +1 -1
- package/dist/src/internal/attachments/url-refs.js +1 -1
- package/dist/src/internal/authored-asset-import-plugin.js +1 -1
- package/dist/src/internal/authored-definition/connection.js +1 -1
- package/dist/src/internal/authored-module-loader.js +1 -1
- package/dist/src/internal/authored-package-tsconfig-paths.js +1 -1
- package/dist/src/internal/bundler/nitro-rolldown.js +1 -1
- package/dist/src/internal/helpers/markdown.js +2 -2
- package/dist/src/internal/json-schema.js +1 -1
- package/dist/src/internal/logging.js +1 -1
- package/dist/src/internal/nitro/host/channel-routes.js +1 -1
- package/dist/src/internal/nitro/host/compiled-sandbox-backend-prune-plugin.js +1 -1
- package/dist/src/internal/nitro/host/create-application-nitro.js +1 -1
- package/dist/src/internal/nitro/host/dev-authored-source-watcher.js +1 -1
- package/dist/src/internal/nitro/host/schedule-task-routes.js +1 -1
- package/dist/src/internal/nitro/host/server-external-packages.js +1 -1
- package/dist/src/internal/nitro/host/start-development-server.js +1 -1
- package/dist/src/internal/nitro/host/start-production-server.d.ts +8 -0
- package/dist/src/internal/nitro/host/start-production-server.js +3 -0
- package/dist/src/internal/nitro/host/types.d.ts +8 -0
- package/dist/src/internal/nitro/host.d.ts +2 -1
- package/dist/src/internal/nitro/host.js +1 -1
- package/dist/src/internal/nitro/routes/agent-info/load-agent-info-data.js +1 -1
- package/dist/src/internal/nitro/routes/index.js +3 -3
- package/dist/src/internal/nitro/routes/workflow-route-helpers.js +1 -1
- package/dist/src/internal/node-esm-compat-banner.js +1 -1
- package/dist/src/internal/package-name.js +1 -1
- package/dist/src/internal/vercel-agent-summary.js +1 -1
- package/dist/src/internal/workflow-bundle/ash-service-route-output.js +1 -1
- package/dist/src/internal/workflow-bundle/builder-support.js +1 -1
- package/dist/src/internal/workflow-bundle/builder.js +2 -2
- package/dist/src/internal/workflow-bundle/vercel-workflow-output.js +1 -1
- package/dist/src/internal/workflow-bundle/workflow-builders.js +1 -1
- package/dist/src/internal/workflow-bundle/workflow-core-shim.js +1 -1
- package/dist/src/internal/workflow-bundle/workflow-transformer.js +1 -1
- package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/ajv.js +1 -1
- package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/compile/codegen/code.js +1 -1
- package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/compile/codegen/index.js +2 -2
- package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/compile/codegen/scope.js +1 -1
- package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/compile/errors.js +1 -1
- package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/compile/index.js +1 -1
- package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/compile/names.js +1 -1
- package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/compile/ref_error.js +1 -1
- package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/compile/resolve.js +1 -1
- package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/compile/rules.js +1 -1
- package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/compile/util.js +1 -1
- package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/compile/validate/boolSchema.js +1 -1
- package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/compile/validate/dataType.js +2 -2
- package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/compile/validate/defaults.js +1 -1
- package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/compile/validate/index.js +1 -1
- package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/compile/validate/keyword.js +1 -1
- package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/compile/validate/subschema.js +1 -1
- package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/core.js +1 -1
- package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/runtime/equal.js +1 -1
- package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/runtime/uri.js +1 -1
- package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/applicator/additionalItems.js +1 -1
- package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/applicator/additionalProperties.js +1 -1
- package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/applicator/allOf.js +1 -1
- package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/applicator/contains.js +1 -1
- package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/applicator/dependencies.js +2 -2
- package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/applicator/if.js +1 -1
- package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/applicator/index.js +1 -1
- package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/applicator/items.js +1 -1
- package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/applicator/items2020.js +1 -1
- package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/applicator/not.js +1 -1
- package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/applicator/oneOf.js +1 -1
- package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/applicator/patternProperties.js +1 -1
- package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/applicator/prefixItems.js +1 -1
- package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/applicator/properties.js +1 -1
- package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/applicator/propertyNames.js +1 -1
- package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/applicator/thenElse.js +1 -1
- package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/code.js +1 -1
- package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/core/index.js +1 -1
- package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/core/ref.js +1 -1
- package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/discriminator/index.js +1 -1
- package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/draft7.js +1 -1
- package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/format/format.js +1 -1
- package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/validation/const.js +1 -1
- package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/validation/enum.js +1 -1
- package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/validation/index.js +1 -1
- package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/validation/limitItems.js +1 -1
- package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/validation/limitLength.js +1 -1
- package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/validation/limitNumber.js +1 -1
- package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/validation/limitProperties.js +1 -1
- package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/validation/multipleOf.js +1 -1
- package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/validation/pattern.js +1 -1
- package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/validation/required.js +1 -1
- package/dist/src/node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/validation/uniqueItems.js +1 -1
- package/dist/src/node_modules/.pnpm/fast-uri@3.1.2/node_modules/fast-uri/index.js +1 -1
- package/dist/src/node_modules/.pnpm/fast-uri@3.1.2/node_modules/fast-uri/lib/schemes.js +1 -1
- package/dist/src/node_modules/.pnpm/fast-uri@3.1.2/node_modules/fast-uri/lib/utils.js +1 -1
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- package/dist/src/node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/ZodError.js +1 -1
- package/dist/src/node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/errors.js +1 -1
- package/dist/src/node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/parseUtil.js +1 -1
- package/dist/src/node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/util.js +1 -1
- package/dist/src/node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/locales/en.js +1 -1
- package/dist/src/node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/types.js +1 -1
- package/dist/src/packages/ash-scaffold/src/channels.js +2 -2
- package/dist/src/packages/ash-scaffold/src/module-files.js +1 -1
- package/dist/src/protocol/message.js +1 -1
- package/dist/src/protocol/routes.js +1 -1
- package/dist/src/public/channels/ash.js +2 -2
- package/dist/src/public/channels/auth.js +1 -1
- package/dist/src/public/channels/discord/api.js +1 -1
- package/dist/src/public/channels/discord/defaults.js +1 -1
- package/dist/src/public/channels/discord/discordChannel.js +1 -1
- package/dist/src/public/channels/discord/hitl.js +1 -1
- package/dist/src/public/channels/discord/inbound.js +1 -1
- package/dist/src/public/channels/discord/verify.js +1 -1
- package/dist/src/public/channels/discord/verifyInbound.js +1 -1
- package/dist/src/public/channels/slack/api.js +1 -1
- package/dist/src/public/channels/slack/attachments.js +1 -1
- package/dist/src/public/channels/slack/constants.js +1 -1
- package/dist/src/public/channels/slack/defaults.js +2 -2
- package/dist/src/public/channels/slack/hitl.js +1 -1
- package/dist/src/public/channels/slack/interactions.js +1 -1
- package/dist/src/public/channels/slack/limits.js +1 -1
- package/dist/src/public/channels/slack/mrkdwn.js +1 -1
- package/dist/src/public/channels/slack/slackChannel.js +1 -1
- package/dist/src/public/channels/slack/verify.js +1 -1
- package/dist/src/public/channels/teams/api.js +1 -1
- package/dist/src/public/channels/teams/attachments.js +1 -1
- package/dist/src/public/channels/teams/defaults.js +1 -1
- package/dist/src/public/channels/teams/hitl.js +1 -1
- package/dist/src/public/channels/teams/inbound.js +1 -1
- package/dist/src/public/channels/teams/limits.js +1 -1
- package/dist/src/public/channels/teams/teamsChannel.js +1 -1
- package/dist/src/public/channels/teams/verify.js +1 -1
- package/dist/src/public/channels/telegram/api.js +1 -1
- package/dist/src/public/channels/telegram/attachments.js +1 -1
- package/dist/src/public/channels/telegram/defaults.js +1 -1
- package/dist/src/public/channels/telegram/hitl.js +1 -1
- package/dist/src/public/channels/telegram/inbound.js +1 -1
- package/dist/src/public/channels/telegram/telegramChannel.js +1 -1
- package/dist/src/public/channels/telegram/verify.js +1 -1
- package/dist/src/public/channels/twilio/defaults.js +1 -1
- package/dist/src/public/channels/twilio/inbound.js +1 -1
- package/dist/src/public/channels/twilio/twilioChannel.js +1 -1
- package/dist/src/public/channels/twilio/verify.js +1 -1
- package/dist/src/public/channels/upload-policy.js +1 -1
- package/dist/src/public/definitions/channel.js +1 -1
- package/dist/src/public/definitions/tool.js +1 -1
- package/dist/src/public/next/index.js +1 -1
- package/dist/src/public/next/server.js +1 -1
- package/dist/src/public/next/vercel-json.js +1 -1
- package/dist/src/public/tool-result-narrowing.js +1 -1
- package/dist/src/public/tools/defaults.js +1 -1
- package/dist/src/react/use-ash-agent.js +1 -1
- package/dist/src/runtime/actions/types.js +1 -1
- package/dist/src/runtime/agent/bootstrap-model-utils.js +1 -1
- package/dist/src/runtime/agent/bootstrap-model.js +1 -1
- package/dist/src/runtime/agent/bootstrap.js +1 -1
- package/dist/src/runtime/agent/mock-model-adapter.js +1 -1
- package/dist/src/runtime/cache-key.js +1 -1
- package/dist/src/runtime/channels/registry.js +1 -1
- package/dist/src/runtime/connections/authorization-tokens.js +1 -1
- package/dist/src/runtime/connections/callback-route.js +1 -1
- package/dist/src/runtime/connections/principal-context.js +1 -1
- package/dist/src/runtime/connections/principal.js +1 -1
- package/dist/src/runtime/framework-channels/index.js +1 -1
- package/dist/src/runtime/framework-tools/ask-question.js +1 -1
- package/dist/src/runtime/framework-tools/bash.js +1 -1
- package/dist/src/runtime/framework-tools/connection-search.js +1 -1
- package/dist/src/runtime/framework-tools/file-state.js +1 -1
- package/dist/src/runtime/framework-tools/glob.js +1 -1
- package/dist/src/runtime/framework-tools/grep.js +1 -1
- package/dist/src/runtime/framework-tools/index.js +1 -1
- package/dist/src/runtime/framework-tools/pending-connection-tool-calls.js +1 -1
- package/dist/src/runtime/framework-tools/read-file.js +1 -1
- package/dist/src/runtime/framework-tools/skill.js +1 -1
- package/dist/src/runtime/framework-tools/todo.js +2 -2
- package/dist/src/runtime/framework-tools/web-fetch.js +1 -1
- package/dist/src/runtime/framework-tools/web-search.js +1 -1
- package/dist/src/runtime/framework-tools/write-file.js +1 -1
- package/dist/src/runtime/governance/auth/jwt-ecdsa.js +1 -1
- package/dist/src/runtime/governance/auth/oidc.js +1 -1
- package/dist/src/runtime/governance/auth/token-claims.js +1 -1
- package/dist/src/runtime/graph.js +1 -1
- package/dist/src/runtime/input/types.js +1 -1
- package/dist/src/runtime/loaders/bundled-artifacts.d.ts +12 -0
- package/dist/src/runtime/loaders/bundled-artifacts.js +1 -1
- package/dist/src/runtime/loaders/compile-metadata.js +1 -1
- package/dist/src/runtime/loaders/manifest.js +1 -1
- package/dist/src/runtime/loaders/module-map.js +1 -1
- package/dist/src/runtime/prompt/compose.js +2 -2
- package/dist/src/runtime/prompt/connections.js +1 -1
- package/dist/src/runtime/resolve-agent-graph.js +1 -1
- package/dist/src/runtime/resolve-hook.js +1 -1
- package/dist/src/runtime/sandbox/keys.js +1 -1
- package/dist/src/runtime/sandbox/registry.js +1 -1
- package/dist/src/runtime/schedules/register.js +1 -1
- package/dist/src/runtime/session-callback-route.js +1 -1
- package/dist/src/runtime/sessions/auth.js +1 -1
- package/dist/src/runtime/sessions/compiled-agent-cache.js +1 -1
- package/dist/src/runtime/sessions/runtime-context-keys.d.ts +11 -0
- package/dist/src/runtime/sessions/runtime-context-keys.js +1 -0
- package/dist/src/runtime/sessions/runtime-session.js +1 -1
- package/dist/src/runtime/skills/fragment-context.js +1 -1
- package/dist/src/runtime/skills/sandbox-access.js +1 -1
- package/dist/src/runtime/subagents/registry.js +1 -1
- package/dist/src/runtime/workspace/types.js +1 -1
- package/dist/src/services/dev-client/request-headers.js +1 -1
- package/dist/src/services/dev-client/vercel-auth-error.js +1 -1
- package/dist/src/shared/json-schemas.js +1 -1
- package/dist/src/shared/json.js +1 -1
- package/dist/src/shared/skill-package.js +1 -1
- package/package.json +1 -1
- package/dist/src/context/seed-keys.d.ts +0 -39
- package/dist/src/context/seed-keys.js +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createLogger}from"#internal/logging.js";import{isCardElement}from"#compiled/chat/index.js";import{encodeSlackApiBody}from"#public/channels/slack/api-encoding.js";import{cardToBlocks,cardToFallbackText}from"#public/channels/slack/blocks.js";import{gfmToSlackMrkdwn,rewriteBareMentions,slackMrkdwnToGfm}from"#public/channels/slack/mrkdwn.js";
|
|
1
|
+
import{createLogger}from"#internal/logging.js";import{isCardElement}from"#compiled/chat/index.js";import{encodeSlackApiBody}from"#public/channels/slack/api-encoding.js";import{cardToBlocks,cardToFallbackText}from"#public/channels/slack/blocks.js";import{gfmToSlackMrkdwn,rewriteBareMentions,slackMrkdwnToGfm}from"#public/channels/slack/mrkdwn.js";const log=createLogger(`slack.api`);function slackContinuationToken(e,t){return`${e}:${t}`}async function resolveSlackBotToken(e){let t=e??process.env.SLACK_BOT_TOKEN;if(!t)throw Error(`SLACK_BOT_TOKEN is required.`);return typeof t==`function`?await t():t}async function callSlackApi(e){let t=await resolveSlackBotToken(e.botToken),r=encodeSlackApiBody(e.body);return(await fetch(`https://slack.com/api/${e.operation}`,{method:`POST`,headers:{authorization:`Bearer ${t}`,"content-type":r.contentType},body:r.body})).json()}function createSlackRequester(e){return(t,n)=>callSlackApi({botToken:e,operation:t,body:n})}function buildSlackBinding(e){let t=createSlackRequester(e.botToken),n=[],r=e.threadTs;function handleMessageTs(t){r||t===r||(r=t,e.onThreadTsChanged?.(t))}async function uploadFiles(t,n){if(t.length===0)return{fileIds:[],raw:{ok:!0}};let i=n?.channelId??e.channelId,a=n?.threadTs??r,o=await resolveSlackBotToken(e.botToken),s=[];for(let n of t){let t=await readFileBytes(n.data),r=await callSlackApi({botToken:e.botToken,operation:`files.getUploadURLExternal`,body:{filename:n.filename,length:t.byteLength}});if(r.ok!==!0||typeof r.upload_url!=`string`||typeof r.file_id!=`string`)throw Error(`Slack files.getUploadURLExternal failed: ${r.error??`unknown_error`}`);let i=await fetch(r.upload_url,{method:`POST`,headers:{authorization:`Bearer ${o}`,"content-type":`application/octet-stream`},body:t});if(!i.ok)throw Error(`Slack upload POST returned HTTP ${i.status} for ${n.filename}.`);s.push(r.file_id)}let c={files:t.map((e,t)=>({id:s[t],title:e.filename}))};i&&(c.channel_id=i),a&&(c.thread_ts=a),n?.initialComment&&(c.initial_comment=n.initialComment);let l=await callSlackApi({botToken:e.botToken,operation:`files.completeUploadExternal`,body:c});if(l.ok!==!0)throw Error(`Slack files.completeUploadExternal failed: ${l.error??`unknown_error`}`);return{fileIds:s,raw:l}}return{thread:{recentMessages:n,async post(n){let i=normalizePostInput(n),s=i.files??[],l=`blocks`in i||`card`in i;if(s.length>0&&!l){let e=await uploadFiles(s,{initialComment:`markdown`in i?rewriteBareMentions(gfmToSlackMrkdwn(i.markdown)):`text`in i?rewriteBareMentions(i.text):void 0});return{id:Array.isArray(e.raw.files)&&e.raw.files.length>0?String(e.raw.files[0].id??``):``,raw:e.raw}}let u=await t(`chat.postMessage`,buildPostMessageBody(i,e.channelId,r));if(u.ok!==!0)throw Error(`Slack chat.postMessage failed: ${u.error??`unknown_error`}`);let d=typeof u.ts==`string`?u.ts:``;if(handleMessageTs(d),s.length>0&&l)try{await uploadFiles(s)}catch(e){log.warn(`file upload after structured post failed`,{error:e})}return{id:d,raw:u}},async postEphemeral(n,i){let a=buildPostMessageBody(normalizePostInput(i),e.channelId,r);a.user=n;let o=await t(`chat.postEphemeral`,a);if(o.ok!==!0)throw Error(`Slack chat.postEphemeral failed: ${o.error??`unknown_error`}`);return{id:typeof o.message_ts==`string`?o.message_ts:``,raw:o}},async startTyping(n){if(!(!e.channelId||!r))try{let i={channel_id:e.channelId,thread_ts:r,status:n??``};n!==void 0&&n.length>0&&(i.loading_messages=[n]);let a=await t(`assistant.threads.setStatus`,i);a.ok!==!0&&log.debug(`assistant.threads.setStatus returned not-ok`,{error:a.error})}catch(e){log.debug(`startTyping threw — swallowed`,{error:e})}},async refresh(){if(n.length=0,!(!e.channelId||!r))try{let i=await t(`conversations.replies`,{channel:e.channelId,ts:r,limit:50});if(i.ok!==!0||!Array.isArray(i.messages)){log.debug(`conversations.replies returned not-ok`,{error:i.error});return}for(let e of i.messages)n.push(parseThreadMessage(e,r))}catch(e){log.debug(`refresh threw — swallowed`,{error:e})}},mentionUser(e){return`<@${e}>`}},slack:{channelId:e.channelId,get threadTs(){return r},teamId:e.teamId,request:t,uploadFiles}}}function normalizePostInput(e){return typeof e==`string`?{markdown:e}:isCardElement(e)?{card:e}:e}function buildPostMessageBody(e,t,n){let a={channel:t,unfurl_links:!1,unfurl_media:!1};return n&&(a.thread_ts=n),`card`in e?(a.blocks=cardToBlocks(e.card),a.text=e.fallbackText??cardToFallbackText(e.card),a):`blocks`in e?(a.blocks=e.blocks,e.text!==void 0&&(a.text=e.text),a):`markdown`in e?(a.markdown_text=rewriteBareMentions(e.markdown),a):(a.text=rewriteBareMentions(e.text),a)}function parseThreadMessage(e,t){let n=typeof e.text==`string`?e.text:``,r=typeof e.ts==`string`?e.ts:``,i=typeof e.thread_ts==`string`?e.thread_ts:t,a=typeof e.user==`string`?e.user:void 0,o=typeof e.bot_id==`string`?e.bot_id:void 0;return{text:n,markdown:slackMrkdwnToGfm(n),user:a,botId:o,ts:r,threadTs:i,isMe:o!==void 0,raw:e}}async function readFileBytes(e){if(e instanceof ArrayBuffer)return Buffer.from(e);if(typeof Blob<`u`&&e instanceof Blob)return Buffer.from(await e.arrayBuffer());if(ArrayBuffer.isView(e)){let t=e;return Buffer.from(t.buffer,t.byteOffset,t.byteLength)}throw Error(`FileUpload.data must be a Buffer, ArrayBuffer, or Blob.`)}export{buildSlackBinding,callSlackApi,resolveSlackBotToken,slackContinuationToken};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createLogger}from"#internal/logging.js";import{evaluateFilePart,formatUploadPolicyViolation,isUploadsDisabled}from"#public/channels/upload-policy.js";import{resolveSlackBotToken}from"#public/channels/slack/api.js";
|
|
1
|
+
import{createLogger}from"#internal/logging.js";import{evaluateFilePart,formatUploadPolicyViolation,isUploadsDisabled}from"#public/channels/upload-policy.js";import{resolveSlackBotToken}from"#public/channels/slack/api.js";const log=createLogger(`slack.attachments`);function collectSlackFileParts(e,r){let i=[];for(let o of e??[]){let e=toSlackFilePart(o,i.length);if(e===null)continue;let s=evaluateFilePart(e,r);if(s!==null){log.warn(`dropped attachment — ${formatUploadPolicyViolation(s)}`,{name:o.name});continue}i.push(e)}return i}function toSlackFilePart(e,t){return e.type===`audio`||e.type===`video`?null:e.url?{type:`file`,mediaType:e.mimeType??`application/octet-stream`,filename:e.name??`attachment-${t}`,data:new URL(e.url)}:(log.warn(`dropped attachment — no url available`,{name:e.name}),null)}async function collectInboundFileParts(e){let t=collectSlackFileParts(e.mention.attachments,e.policy);if(t.length>0)return t;if(isUploadsDisabled(e.policy))return[];try{await e.thread.refresh()}catch(e){return log.warn(`slack thread refresh failed for attachment collection`,{error:e}),[]}let n=e.thread.recentMessages;for(let t=n.length-1;t>=0;--t){let r=n[t];if(!r||r.isMe)continue;let i=r.raw,a=collectSlackFileParts(extractAttachmentsFromRaw(i?.files),e.policy);return a.length>0?a:[]}return[]}function extractAttachmentsFromRaw(e){return Array.isArray(e)?e.map(e=>{let t=typeof e.mimetype==`string`?e.mimetype:void 0;return{id:typeof e.id==`string`?e.id:``,type:inferAttachmentType(t),url:typeof e.url_private==`string`?e.url_private:void 0,name:typeof e.name==`string`?e.name:void 0,mimeType:t,size:typeof e.size==`number`?e.size:void 0}}):[]}function inferAttachmentType(e){return e===void 0?`file`:e.startsWith(`image/`)?`image`:e.startsWith(`video/`)?`video`:e.startsWith(`audio/`)?`audio`:`file`}function buildSlackTurnMessage(e,t){return t.length===0?e:e.trim().length===0?[...t]:[{type:`text`,text:e},...t]}function createSlackFetchFile(e){return async t=>{if(!t.startsWith(`https://files.slack.com/`))return null;let n=await resolveSlackBotToken(e.botToken),r=await fetch(t,{headers:{authorization:`Bearer ${n}`}});if(!r.ok)throw Error(`Slack file fetch returned HTTP ${r.status} for ${t}.`);return{bytes:Buffer.from(await r.arrayBuffer()),mediaType:r.headers.get(`content-type`)??void 0}}}export{buildSlackTurnMessage,collectInboundFileParts,collectSlackFileParts,createSlackFetchFile};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
const SLACK_CHANNEL_DEFAULT_ROUTE=`/ash/v1/slack`;export{SLACK_CHANNEL_DEFAULT_ROUTE};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{createLogger,extractErrorId,formatErrorHint}from"#internal/logging.js";import{truncateMessageText,truncateTypingStatus}from"#public/channels/slack/limits.js";import{buildAuthCompletedText,buildAuthEphemeralBlocks,buildAuthRequiredPublicText,formatConnectionDisplayName}from"#public/channels/slack/connections.js";import{renderInputRequestBlocks}from"#public/channels/slack/hitl.js";
|
|
2
|
-
`));await t.thread.post({blocks:e.requests.flatMap(renderInputRequestBlocks),text:n})}}
|
|
1
|
+
import{createLogger,extractErrorId,formatErrorHint}from"#internal/logging.js";import{truncateMessageText,truncateTypingStatus}from"#public/channels/slack/limits.js";import{buildAuthCompletedText,buildAuthEphemeralBlocks,buildAuthRequiredPublicText,formatConnectionDisplayName}from"#public/channels/slack/connections.js";import{renderInputRequestBlocks}from"#public/channels/slack/hitl.js";const log=createLogger(`slack.defaults`);function defaultSlackAuth(e,t){let n=e.author;if(!n)return null;let r=e.teamId,i=n.isBot,a=n.userId,o=r?i?`slack:${r}:bot:${a}`:`slack:${r}:${a}`:i?`slack:bot:${a}`:`slack:${a}`,s={author_type:i?`bot`:`user`,channel_id:t.slack.channelId,thread_ts:t.slack.threadTs,user_id:a};return n.userName&&(s.user_name=n.userName),n.fullName&&(s.full_name=n.fullName),r!==void 0&&(s.team_id=r),{attributes:s,authenticator:`slack-webhook`,issuer:r===void 0?`slack`:`slack:${r}`,principalId:o,principalType:i?`service`:`user`}}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)=>{if(e.requests.length===0)return;let n=truncateMessageText(e.requests.map(e=>e.prompt).join(`
|
|
2
|
+
`));await t.thread.post({blocks:e.requests.flatMap(renderInputRequestBlocks),text:n})}}const defaultEvents={async"turn.started"(e,t){t.state.pendingToolCallMessage=null,await t.thread.startTyping(`Working...`)},async"actions.requested"(e,t){let n=t.state.pendingToolCallMessage;if(t.state.pendingToolCallMessage=null,n){await t.thread.startTyping(truncateTypingStatus(n));return}let r=e.actions.map(e=>e.kind===`tool-call`?e.toolName:e.kind);await t.thread.startTyping(truncateTypingStatus(`Running ${r.join(`, `)}...`))},async"message.completed"(e,t){if(e.finishReason===`tool-calls`){t.state.pendingToolCallMessage=e.message?firstNonEmptyLine(e.message)??null:null;return}t.state.pendingToolCallMessage=null,e.message&&await t.thread.post(e.message)},async"turn.failed"(e,r){let i=formatErrorHint(e),a=extractErrorId(e.details);await r.thread.post([`I hit an error while handling your request${i}.`,``,`Please try again, rephrase, or reach out if it keeps failing.`,...a?[``,`_Error id: \`${a}\`_`]:[]].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
4
|
`))},async"connection.authorization_required"(e,t){let n=formatConnectionDisplayName(e.connectionName),r=t.state.triggeringUserId??null,i=e.authorization?.url;if(r&&i)try{await t.thread.postEphemeral(r,{blocks:buildAuthEphemeralBlocks({displayName:n,url:i}),text:`Sign in with ${n}: ${i}`})}catch(t){log.error(`Slack auth ephemeral delivery failed`,{connectionName:e.connectionName,error:t})}let a=buildAuthRequiredPublicText({displayName:n,hasUser:r!==null});try{let n=await t.thread.post(a);n.id&&(t.state.pendingAuthMessageTs={...t.state.pendingAuthMessageTs,[e.connectionName]:n.id})}catch(t){log.error(`Slack auth public message delivery failed`,{connectionName:e.connectionName,error:t})}},async"connection.authorization_completed"(e,t){let n=t.state.pendingAuthMessageTs??{},r=n[e.connectionName];if(r===void 0)return;let i=buildAuthCompletedText({displayName:formatConnectionDisplayName(e.connectionName),outcome:e.outcome,reason:e.reason});try{await t.slack.request(`chat.update`,{channel:t.slack.channelId,ts:r,text:i})}catch(t){log.error(`Slack auth status edit failed`,{connectionName:e.connectionName,error:t})}let o={...n};delete o[e.connectionName],t.state.pendingAuthMessageTs=o}};export{defaultEvents,defaultInputRequestedHandler,defaultOnAppMention,defaultOnDirectMessage,defaultSlackAuth};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{truncateModalTitle,truncatePlainText,truncateSectionText}from"#public/channels/slack/limits.js";
|
|
1
|
+
import{truncateModalTitle,truncatePlainText,truncateSectionText}from"#public/channels/slack/limits.js";const HITL_ACTION_PREFIX=`ash_input:`,HITL_FREEFORM_ACTION_PREFIX=`ash_input_freeform:`,HITL_FREEFORM_MODAL_CALLBACK_ID=`ash_input_freeform_submit`,HITL_FREEFORM_MODAL_BLOCK_ID=`ash_freeform_block`,HITL_FREEFORM_MODAL_ACTION_ID=`ash_freeform_text`,BUTTON_ACTION_ID_RE=/^(?<requestId>.+):button:\d+$/u;function deriveHitlResponse(e){if(!e.actionId.startsWith(`ash_input:`))return null;let t=e.actionId.slice(10);if(e.selectedOptionValue!==void 0)return t?{optionId:e.selectedOptionValue,requestId:t}:null;if(e.value!==void 0){let n=BUTTON_ACTION_ID_RE.exec(t)?.groups?.requestId;return n?{optionId:e.value,requestId:n}:null}return null}function isHitlAction(e){return e.startsWith(HITL_ACTION_PREFIX)}function renderInputRequestBlocks(e){let t={text:{text:truncateSectionText(e.prompt),type:`mrkdwn`},type:`section`},a=`${HITL_ACTION_PREFIX}${e.requestId}`,o=e.options,s=e.allowFreeform===!0||!o||o.length===0;return o&&o.length>0&&e.display===`select`?[t,{type:`actions`,elements:[o.length<=6?{type:`radio_buttons`,action_id:a,options:o.map(buildOption)}:{type:`static_select`,action_id:a,options:o.map(buildOption),placeholder:{type:`plain_text`,text:`Choose an option`}}]}]:o&&o.length>0?[t,{type:`actions`,elements:o.map((e,t)=>buildButton(e,a,t))}]:s?[t,{type:`actions`,elements:[{type:`button`,action_id:`${HITL_FREEFORM_ACTION_PREFIX}${e.requestId}`,text:{type:`plain_text`,text:`Type your answer`},style:`primary`,value:e.requestId}]}]:[t]}function buildFreeformModalView(t){let r=t.prompt?truncateModalTitle(t.prompt):`Your answer`,i=t.prompt?[{type:`section`,text:{type:`mrkdwn`,text:truncateSectionText(t.prompt)}}]:[];return{type:`modal`,callback_id:HITL_FREEFORM_MODAL_CALLBACK_ID,private_metadata:JSON.stringify(t.metadata),title:{type:`plain_text`,text:r},submit:{type:`plain_text`,text:`Submit`},close:{type:`plain_text`,text:`Cancel`},blocks:[...i,{type:`input`,block_id:HITL_FREEFORM_MODAL_BLOCK_ID,element:{type:`plain_text_input`,action_id:HITL_FREEFORM_MODAL_ACTION_ID,multiline:!0,placeholder:{type:`plain_text`,text:`Type your answer here...`}},label:{type:`plain_text`,text:`Answer`}}]}}function isFreeformAction(e){return e.startsWith(HITL_FREEFORM_ACTION_PREFIX)}function freeformRequestIdFromActionId(e){if(!isFreeformAction(e))return;let t=e.slice(19);return t.length>0?t:void 0}function buildButton(e,n,r){let i={action_id:`${n}:button:${r}`,text:{text:truncatePlainText(e.label),type:`plain_text`},type:`button`,value:e.id};return(e.style===`primary`||e.style===`danger`)&&(i.style=e.style),i}function buildOption(e){let n={text:{text:truncatePlainText(e.label),type:`plain_text`},value:e.id},r=truncatePlainText(e.description);return r&&r.length>0&&(n.description={text:r,type:`plain_text`}),n}function buildAnsweredBlocks(e){let t=[];return e.promptBlock!==void 0&&e.promptBlock!==null&&t.push(e.promptBlock),t.push({type:`section`,text:{type:`mrkdwn`,text:`:white_check_mark: *${e.answerLabel}*`}}),e.userId&&e.userId.length>0&&t.push({type:`context`,elements:[{type:`mrkdwn`,text:`Answered by <@${e.userId}>`}]}),t}export{HITL_ACTION_PREFIX,HITL_FREEFORM_ACTION_PREFIX,HITL_FREEFORM_MODAL_ACTION_ID,HITL_FREEFORM_MODAL_BLOCK_ID,HITL_FREEFORM_MODAL_CALLBACK_ID,buildAnsweredBlocks,buildFreeformModalView,deriveHitlResponse,freeformRequestIdFromActionId,isFreeformAction,isHitlAction,renderInputRequestBlocks};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createLogger}from"#internal/logging.js";import{buildSlackBinding,resolveSlackBotToken,slackContinuationToken}from"#public/channels/slack/api.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";
|
|
1
|
+
import{createLogger}from"#internal/logging.js";import{buildSlackBinding,resolveSlackBotToken,slackContinuationToken}from"#public/channels/slack/api.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";const log=createLogger(`slack.interactions`);function parseBlockActionsPayload(e){let t=e.actions;if(!Array.isArray(t))return null;let n=e.channel?.id,r=e.message,i=r?.thread_ts??r?.ts;if(!n||!i)return null;let a=e.team,o=e.user,s=a?.id??o.team_id,c={id:o.id,username:o.username,name:o.name},l=r?.blocks??[];return{actions:t.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:r?.ts,label:extractActionLabel(e),user:c})),channelId:n,threadTs:i,teamId:s,messageBlocks:l}}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){for(let t of e)if(typeof t==`object`&&t&&t.type===`section`)return t}function readPromptTextFromBlocks(e){let t=findPromptBlock(e)?.text?.text;return typeof t==`string`&&t.length>0?t:void 0}async function handleInteractionPost(e,n,i){let a=new Response(`ok`,{status:200}),o=new URLSearchParams(e).get(`payload`);if(!o)return a;let s;try{s=JSON.parse(o)}catch{return log.warn(`failed to parse Slack interaction payload`),a}if(s?.type===`view_submission`)return handleViewSubmission(s,n,i);let c=parseBlockActionsPayload(s);if(!c)return a;let u=c.actions.find(e=>isFreeformAction(e.actionId));if(u)return await openFreeformModal({payload:s,interaction:c,freeformAction:u,deps:i}),a;let p=slackContinuationToken(c.channelId,c.threadTs),m=c.actions.map(deriveHitlResponse).filter(e=>e!==null);m.length>0&&(n.waitUntil(n.send({inputResponses:m},{auth:null,continuationToken:p,state:{channelId:c.channelId,threadTs:c.threadTs,teamId:c.teamId??null,triggeringUserId:c.actions[0]?.user.id??null}}).catch(e=>{log.error(`HITL interaction delivery failed`,{error:e})})),n.waitUntil(updateAnsweredHitlCard(c,i).catch(e=>{log.error(`HITL answered-card update failed`,{error:e})})));let h=i.config.onInteraction;if(h){let e=c.actions.filter(e=>!isHitlAction(e.actionId));if(e.length>0){let{thread:r,slack:a}=buildSlackBinding({botToken:i.config.credentials?.botToken,channelId:c.channelId,threadTs:c.threadTs,teamId:c.teamId}),o={thread:r,slack:a};for(let t of e)n.waitUntil(Promise.resolve(h(t,o)).catch(e=>{log.error(`custom interaction handler failed`,{error:e})}))}}return a}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 i=freeformRequestIdFromActionId(e.freeformAction.actionId)??e.freeformAction.value;if(!i){log.warn(`freeform button click missing requestId`);return}let a=e.freeformAction.messageTs;if(!a){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:a,requestId:i},prompt:readPromptTextFromBlocks(e.interaction.messageBlocks)}),s=await resolveSlackBotToken(e.deps.config.credentials?.botToken),l=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})});l.ok||log.error(`Slack views.open returned non-2xx`,{status:l.status})}async function handleViewSubmission(e,t,n){let r=new Response(`ok`,{status:200}),s=e.view;if(s?.callback_id!==HITL_FREEFORM_MODAL_CALLBACK_ID)return r;let c;try{c=JSON.parse(s.private_metadata??``)}catch{return log.warn(`freeform view_submission carries invalid private_metadata`),r}if(!c.continuationToken||!c.requestId||!c.messageTs||!c.channelId||!c.threadTs)return r;let l=s.state?.values?.[HITL_FREEFORM_MODAL_BLOCK_ID]?.[HITL_FREEFORM_MODAL_ACTION_ID]?.value,u=typeof l==`string`?l:``;if(u.length===0)return r;let d=e.user,f=d.id,p=d.team_id??null;return t.waitUntil(t.send({inputResponses:[{requestId:c.requestId,text:u}]},{auth:null,continuationToken:c.continuationToken,state:{channelId:c.channelId,threadTs:c.threadTs,teamId:p,triggeringUserId:f}}).catch(e=>{log.error(`freeform answer delivery failed`,{error:e})})),t.waitUntil(updateAnsweredFreeformCard({channelId:c.channelId,messageTs:c.messageTs,answerLabel:u,userId:f??void 0,deps:n}).catch(e=>{log.error(`freeform answered-card update failed`,{error:e})})),r}async function updateAnsweredHitlCard(e,t){let r=e.actions.find(e=>isHitlAction(e.actionId));if(!r||!r.messageTs)return;let i=r.label??r.selectedOptionValue??r.value;if(!i)return;let a=buildAnsweredBlocks({promptBlock:findPromptBlock(e.messageBlocks),answerLabel:i,userId:r.user.id}),o=await resolveSlackBotToken(t.config.credentials?.botToken),c=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:r.messageTs,blocks:a,text:`Answered: ${i}`})});if(!c.ok)throw Error(`Slack chat.update returned HTTP ${c.status}`)}async function updateAnsweredFreeformCard(e){let t=buildAnsweredBlocks({promptBlock:void 0,answerLabel:e.answerLabel,userId:e.userId}),r=await resolveSlackBotToken(e.deps.config.credentials?.botToken),i=await fetch(`https://slack.com/api/chat.update`,{method:`POST`,headers:{authorization:`Bearer ${r}`,"content-type":`application/json; charset=utf-8`},body:JSON.stringify({channel:e.channelId,ts:e.messageTs,blocks:t,text:`Answered: ${e.answerLabel}`})});if(!i.ok)throw Error(`Slack chat.update returned HTTP ${i.status}`)}export{handleInteractionPost,parseBlockActionsPayload};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
const SLACK_TYPING_STATUS_MAX_LENGTH=50,SLACK_BLOCK_KIT_PLAIN_TEXT_MAX_LENGTH=75,SLACK_SECTION_TEXT_MAX_LENGTH=3e3,SLACK_MESSAGE_TEXT_MAX_LENGTH=4e4,SLACK_MODAL_TITLE_MAX_LENGTH=24;function truncateTypingStatus(e){return truncateWithEllipsis(e.trim().replace(/\s+/gu,` `),50)}function truncatePlainText(e){if(e!==void 0)return truncateWithEllipsis(e,75)}function truncateSectionText(e){return truncateWithEllipsis(e,SLACK_SECTION_TEXT_MAX_LENGTH)}function truncateMessageText(e){return truncateWithEllipsis(e,SLACK_MESSAGE_TEXT_MAX_LENGTH)}function truncateModalTitle(e){return truncateWithEllipsis(e,24)}function truncateWithEllipsis(e,t){if(e.length<=t)return e;let n=Math.max(0,t-3);return`${e.slice(0,n).trimEnd()}...`}export{SLACK_BLOCK_KIT_PLAIN_TEXT_MAX_LENGTH,SLACK_MESSAGE_TEXT_MAX_LENGTH,SLACK_MODAL_TITLE_MAX_LENGTH,SLACK_SECTION_TEXT_MAX_LENGTH,SLACK_TYPING_STATUS_MAX_LENGTH,truncateMessageText,truncateModalTitle,truncatePlainText,truncateSectionText,truncateTypingStatus};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
const BARE_MENTION_RE=/(?<![<\w])@(\w+)/gu;function rewriteBareMentions(t){return t.replace(BARE_MENTION_RE,`<@$1>`)}function gfmToSlackMrkdwn(e){return splitCodeFences(e).map(e=>e.kind===`code`?e.text:convertInline(e.text)).join(``)}function slackMrkdwnToGfm(e){return splitCodeFences(e).map(e=>e.kind===`code`?e.text:decodeInline(e.text)).join(``)}function splitCodeFences(e){let t=[],n=/```[\s\S]*?```|`[^`\n]+`/gu,r=0;for(let i of e.matchAll(n)){let n=i.index??0;n>r&&t.push({kind:`text`,text:e.slice(r,n)}),t.push({kind:`code`,text:i[0]}),r=n+i[0].length}return r<e.length&&t.push({kind:`text`,text:e.slice(r)}),t}function convertInline(e){let t=e;return t=t.replace(/\*\*([^*\n]+)\*\*/gu,`*$1*`),t=t.replace(/__([^_\n]+)__/gu,`*$1*`),t=t.replace(/~~([^~\n]+)~~/gu,`~$1~`),t=t.replace(/\[([^\]\n]+)\]\(([^)\s]+)\)/gu,`<$2|$1>`),t}function decodeInline(e){let t=e;return t=t.replace(/<!(channel|here|everyone)>/gu,`@$1`),t=t.replace(/<@([A-Z0-9]+)\|([^>]+)>/gu,`@$2`),t=t.replace(/<@([A-Z0-9]+)>/gu,`@$1`),t=t.replace(/<#([A-Z0-9]+)\|([^>]+)>/gu,`#$2`),t=t.replace(/<#([A-Z0-9]+)>/gu,`#$1`),t=t.replace(/<(https?:\/\/[^|>\s]+)\|([^>]+)>/gu,`[$2]($1)`),t=t.replace(/<(https?:\/\/[^>\s]+)>/gu,`$1`),t=t.replace(/(^|[^*])\*([^*\n]+)\*(?!\*)/gu,`$1**$2**`),t=t.replace(/(^|[^~])~([^~\n]+)~(?!~)/gu,`$1~~$2~~`),t}export{gfmToSlackMrkdwn,rewriteBareMentions,slackMrkdwnToGfm};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createLogger}from"#internal/logging.js";import{mergeUploadPolicy}from"#public/channels/upload-policy.js";import{POST,defineChannel}from"#public/definitions/defineChannel.js";import{buildSlackBinding,slackContinuationToken}from"#public/channels/slack/api.js";import{defaultEvents,defaultInputRequestedHandler,defaultOnAppMention,defaultOnDirectMessage}from"#public/channels/slack/defaults.js";import{buildSlackTurnMessage,collectInboundFileParts,createSlackFetchFile}from"#public/channels/slack/attachments.js";import{parseAppMentionEvent,parseDirectMessageEvent,prependSlackContext}from"#public/channels/slack/inbound.js";import{SLACK_CHANNEL_DEFAULT_ROUTE}from"#public/channels/slack/constants.js";import{handleInteractionPost}from"#public/channels/slack/interactions.js";import{verifySlackRequest}from"#public/channels/slack/verify.js";
|
|
1
|
+
import{createLogger}from"#internal/logging.js";import{mergeUploadPolicy}from"#public/channels/upload-policy.js";import{POST,defineChannel}from"#public/definitions/defineChannel.js";import{buildSlackBinding,slackContinuationToken}from"#public/channels/slack/api.js";import{defaultEvents,defaultInputRequestedHandler,defaultOnAppMention,defaultOnDirectMessage}from"#public/channels/slack/defaults.js";import{buildSlackTurnMessage,collectInboundFileParts,createSlackFetchFile}from"#public/channels/slack/attachments.js";import{parseAppMentionEvent,parseDirectMessageEvent,prependSlackContext}from"#public/channels/slack/inbound.js";import{SLACK_CHANNEL_DEFAULT_ROUTE}from"#public/channels/slack/constants.js";import{handleInteractionPost}from"#public/channels/slack/interactions.js";import{verifySlackRequest}from"#public/channels/slack/verify.js";const log=createLogger(`slack.channel`);function rebuildSlackContext(e,t,n){let{thread:r,slack:a}=buildSlackBinding({botToken:n?.botToken,channelId:e.channelId??``,threadTs:e.threadTs??``,teamId:e.teamId??void 0,onThreadTsChanged(n){e.threadTs=n,e.channelId&&t.setContinuationToken(slackContinuationToken(e.channelId,n))}});return{thread:r,slack:a,session:t,state:e}}function slackChannel(e={}){let l=mergeUploadPolicy(e.uploadPolicy),u=createSlackFetchFile({botToken:e.credentials?.botToken}),f=e.onAppMention??defaultOnAppMention,p=e.onDirectMessage??defaultOnDirectMessage,m={...defaultEvents,...e.events,"input.requested":e.events?.[`input.requested`]??defaultInputRequestedHandler()};return defineChannel({kindHint:`slack`,state:{channelId:null,threadTs:null,teamId:null,triggeringUserId:null,pendingToolCallMessage:null,pendingAuthMessageTs:{}},fetchFile:u,context(t,n){return rebuildSlackContext(t,n,e.credentials)},routes:[POST(e.route??SLACK_CHANNEL_DEFAULT_ROUTE,async(t,{send:n,waitUntil:r})=>{let i=await verifyInbound(t,e.credentials);return i===null?new Response(`unauthorized`,{status:401}):(t.headers.get(`content-type`)??``).includes(`application/x-www-form-urlencoded`)?handleInteractionPost(i,{send:n,waitUntil:r},{config:e}):handleEventPost({body:i,send:n,waitUntil:r,onAppMention:f,onDirectMessage:p,uploadPolicy:l,credentials:e.credentials})})],async receive(t,{send:n}){let r=t.args,a=r.channelId;if(!a||typeof a!=`string`)throw Error(`slackChannel().receive requires args.channelId.`);let o=typeof r.threadTs==`string`?r.threadTs:``,s=r.initialMessage;if(s&&o.length>0)throw Error("slackChannel().receive: `threadTs` and `initialMessage` are mutually exclusive.");let c=o;if(s){let{thread:t}=buildSlackBinding({botToken:e.credentials?.botToken,channelId:a,threadTs:``,teamId:void 0}),n={card:s.card};s.fallbackText!==void 0&&(n.fallbackText=s.fallbackText),c=(await t.post(n)).id}return n(t.message,{auth:t.auth,continuationToken:slackContinuationToken(a,c),state:{channelId:a,threadTs:c||null,teamId:null,triggeringUserId:null}})},events:m})}async function handleEventPost(e){let t;try{t=JSON.parse(e.body)}catch(e){return log.warn(`inbound webhook body is not valid JSON`,{error:e}),new Response(`ok`)}if(typeof t.challenge==`string`)return new Response(t.challenge,{status:200,headers:{"content-type":`text/plain`}});let n=parseAppMentionEvent(t);if(n)return e.waitUntil(dispatchInboundMessage({kind:`app_mention`,message:n,handler:e.onAppMention,send:e.send,uploadPolicy:e.uploadPolicy,credentials:e.credentials})),new Response(`ok`);let r=parseDirectMessageEvent(t);return r&&e.waitUntil(dispatchInboundMessage({kind:`direct_message`,message:r,handler:e.onDirectMessage,send:e.send,uploadPolicy:e.uploadPolicy,credentials:e.credentials})),new Response(`ok`)}async function verifyInbound(e,t){try{return await verifySlackRequest(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 dispatchInboundMessage(e){let{message:t,kind:n}=e,{thread:r,slack:a}=buildSlackBinding({botToken:e.credentials?.botToken,channelId:t.channelId,threadTs:t.threadTs,teamId:t.teamId}),o={thread:r,slack:a},s;try{s=await e.handler(o,t)}catch(e){log.error(`${n} handler failed`,{error:e});return}if(s==null)return;let c=await collectInboundFileParts({mention:t,thread:r,policy:e.uploadPolicy}),d=buildSlackTurnMessage(t.markdown,c),f={channelId:t.channelId,fullName:t.author?.fullName,teamId:t.teamId,threadTs:t.threadTs,userId:t.author?.userId??``,userName:t.author?.userName},p=f.userId?prependSlackContext(d,f):d;try{await e.send({message:p,modelContext:s.modelContext},{auth:s.auth,continuationToken:slackContinuationToken(t.channelId,t.threadTs),state:{channelId:t.channelId,threadTs:t.threadTs,teamId:t.teamId??null,triggeringUserId:f.userId||null}})}catch(e){log.error(`${n} delivery failed`,{error:e})}}export{slackChannel};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createLogger}from"#internal/logging.js";import{createHmac,timingSafeEqual}from"node:crypto";
|
|
1
|
+
import{createLogger}from"#internal/logging.js";import{createHmac,timingSafeEqual}from"node:crypto";const log=createLogger(`slack.verify`);async function verifySlackRequest(e,n){let r=await e.text();if(n.webhookVerifier!==void 0){let t=await n.webhookVerifier(e,r);if(!t)throw Error(`slackChannel: inbound webhook verifier rejected the request.`);return typeof t==`string`?t:r}if(!n.signingSecret)throw Error(`slackChannel: missing signing secret. Pass credentials.signingSecret, set SLACK_SIGNING_SECRET, or supply credentials.webhookVerifier.`);let i=e.headers.get(`x-slack-request-timestamp`)??``,a=e.headers.get(`x-slack-signature`)??``;if(!i||!a)throw Error(`slackChannel: inbound request missing Slack signature headers.`);let o=Number(i);if(!Number.isFinite(o))throw Error(`slackChannel: inbound request has malformed timestamp.`);let s=n.maxSkewSeconds??300,c=Math.floor(Date.now()/1e3);if(Math.abs(c-o)>s)throw Error(`slackChannel: inbound request timestamp outside allowed skew.`);let l=`v0:${i}:${r}`;if(!constantTimeCompare(`v0=${createHmac(`sha256`,n.signingSecret).update(l).digest(`hex`)}`,a))throw Error(`slackChannel: inbound request signature mismatch.`);return r}function constantTimeCompare(e,t){if(e.length!==t.length)return!1;try{return timingSafeEqual(Buffer.from(e),Buffer.from(t))}catch(e){return log.debug(`timingSafeEqual threw`,{error:e}),!1}}export{verifySlackRequest};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{isObject}from"#shared/guards.js";import{parseJsonObject}from"#shared/json.js";
|
|
1
|
+
import{isObject}from"#shared/guards.js";import{parseJsonObject}from"#shared/json.js";const TEAMS_MESSAGE_TEXT_MAX_LENGTH=80*1024,BOT_FRAMEWORK_TENANT=`botframework.com`,accessTokenCache=new Map;function teamsContinuationToken(e){return[e.tenantId??`_`,e.conversationId,e.replyToActivityId??``].map(e=>encodeURIComponent(e)).join(`:`)}async function resolveTeamsAppId(e){let t=e??process.env.MICROSOFT_APP_ID??process.env.TEAMS_APP_ID;if(!t)throw Error(`MICROSOFT_APP_ID or TEAMS_APP_ID is required.`);return typeof t==`function`?await t():t}async function resolveTeamsAppPassword(e){let t=e??process.env.MICROSOFT_APP_PASSWORD??process.env.TEAMS_APP_PASSWORD;if(!t)throw Error(`MICROSOFT_APP_PASSWORD or TEAMS_APP_PASSWORD is required.`);return typeof t==`function`?await t():t}async function resolveTeamsTenantId(e){let t=e??process.env.MICROSOFT_TENANT_ID??process.env.TEAMS_TENANT_ID;if(t)return typeof t==`function`?await t():t}async function resolveTeamsAccessToken(t={}){let n=t.credentials;if(n?.tokenProvider!==void 0)return normalizeAccessTokenResult(await n.tokenProvider()).accessToken;let a=await resolveTeamsAppId(n?.appId),o=await resolveTeamsAppPassword(n?.appPassword),s=await resolveTeamsTenantId(n?.tenantId),c=trimTrailingSlash(t.loginBaseUrl??`https://login.microsoftonline.com`),l=`${c}:${s??BOT_FRAMEWORK_TENANT}:${a}`,u=accessTokenCache.get(l),d=Date.now();if(u!==void 0&&u.expiresAt-6e4>d)return u.accessToken;let f=`${c}/${encodeURIComponent(s??BOT_FRAMEWORK_TENANT)}/oauth2/v2.0/token`,p=new URLSearchParams({client_id:a,client_secret:o,grant_type:`client_credentials`,scope:`https://api.botframework.com/.default`}),m=await(t.fetch??fetch)(f,{body:p,headers:{"content-type":`application/x-www-form-urlencoded`},method:`POST`}),h=await parseResponseBody(m);if(!m.ok)throw Error(`Teams access-token request failed with HTTP ${m.status}.`);let g=isObject(h)?h:{},_=typeof g.access_token==`string`?g.access_token:``;if(!_)throw Error(`Teams access-token response did not include access_token.`);let v=typeof g.expires_in==`number`?g.expires_in:3600;return accessTokenCache.set(l,{accessToken:_,expiresAt:d+v*1e3}),_}async function callTeamsConnectorApi(e){let n=e.fetch??fetch,r=new Headers;r.set(`authorization`,`Bearer ${await resolveTeamsAccessToken(e)}`),r.set(`content-type`,`application/json; charset=utf-8`);let i={headers:r,method:e.method??`POST`};e.body!==void 0&&(i.body=JSON.stringify(parseJsonObject(e.body)));let a=await n(`${trimTrailingSlash(e.serviceUrl)}${e.path}`,i);return{body:await parseResponseBody(a),ok:a.ok,status:a.status}}async function sendTeamsActivity(e){let t=await callTeamsConnectorApi({...e,body:e.body,path:`/v3/conversations/${encodeURIComponent(e.conversationId)}/activities`});if(!t.ok)throw Error(`Teams send activity failed with HTTP ${t.status}.`);return toPostedActivity(t.body)}async function replyToTeamsActivity(e){let t=await callTeamsConnectorApi({...e,body:e.body,path:`/v3/conversations/${encodeURIComponent(e.conversationId)}/activities/${encodeURIComponent(e.activityId)}`});if(!t.ok)throw Error(`Teams reply activity failed with HTTP ${t.status}.`);return toPostedActivity(t.body)}async function updateTeamsActivity(e){let t=await callTeamsConnectorApi({...e,body:e.body,method:`PUT`,path:`/v3/conversations/${encodeURIComponent(e.conversationId)}/activities/${encodeURIComponent(e.activityId)}`});if(!t.ok)throw Error(`Teams update activity failed with HTTP ${t.status}.`);return toPostedActivity(t.body)}async function triggerTeamsTypingIndicator(e){let t=await callTeamsConnectorApi({...e,body:{type:`typing`},path:`/v3/conversations/${encodeURIComponent(e.conversationId)}/activities`});if(!t.ok)throw Error(`Teams typing indicator failed with HTTP ${t.status}.`)}function splitTeamsMessageText(e){if(e.length<=81920)return[e];let t=[],r=e;for(;r.length>TEAMS_MESSAGE_TEXT_MAX_LENGTH;){let e=r.lastIndexOf(`
|
|
2
2
|
|
|
3
3
|
`,TEAMS_MESSAGE_TEXT_MAX_LENGTH);e<=0&&(e=r.lastIndexOf(`
|
|
4
4
|
`,TEAMS_MESSAGE_TEXT_MAX_LENGTH)),e<=0&&(e=r.lastIndexOf(` `,TEAMS_MESSAGE_TEXT_MAX_LENGTH)),e<=0&&(e=TEAMS_MESSAGE_TEXT_MAX_LENGTH),t.push(r.slice(0,e).trimEnd()),r=r.slice(e).trimStart()}return t.push(r),t}function normalizeTeamsPostInput(e){return typeof e==`string`?{text:e,textFormat:`markdown`}:e}function normalizeAccessTokenResult(e){if(typeof e==`string`)return{accessToken:e};let t=e.expiresAt instanceof Date?e.expiresAt.getTime():e.expiresAt;return{accessToken:e.accessToken,expiresAt:t}}function toPostedActivity(t){let n=isObject(t)?t:{};return{id:typeof n.id==`string`?n.id:``,raw:t}}function trimTrailingSlash(e){return e.replace(/\/+$/,``)}async function parseResponseBody(e){let t=await e.text();if(!t)return null;try{return JSON.parse(t)}catch{return t}}export{TEAMS_MESSAGE_TEXT_MAX_LENGTH,callTeamsConnectorApi,normalizeTeamsPostInput,replyToTeamsActivity,resolveTeamsAccessToken,resolveTeamsAppId,resolveTeamsAppPassword,resolveTeamsTenantId,sendTeamsActivity,splitTeamsMessageText,teamsContinuationToken,triggerTeamsTypingIndicator,updateTeamsActivity};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createLogger}from"#internal/logging.js";import{isObject}from"#shared/guards.js";import{evaluateFilePart,formatUploadPolicyViolation,isUploadsDisabled,mergeUploadPolicy}from"#public/channels/upload-policy.js";
|
|
1
|
+
import{createLogger}from"#internal/logging.js";import{isObject}from"#shared/guards.js";import{evaluateFilePart,formatUploadPolicyViolation,isUploadsDisabled,mergeUploadPolicy}from"#public/channels/upload-policy.js";const log=createLogger(`teams.attachments`);function normalizeTeamsFilesPolicy(e){return{allowedHosts:e?.allowedHosts??[],enabled:e?.enabled===!0,uploadPolicy:mergeUploadPolicy(e?.uploadPolicy)}}function collectTeamsFileParts(e,t){if(!t.enabled||isUploadsDisabled(t.uploadPolicy))return[];let a=[];for(let i of e){let e=toTeamsFilePart(i,a.length,t);if(e===null)continue;let o=evaluateFilePart(e,t.uploadPolicy);if(o!==null){log.warn(`dropped Teams attachment — ${formatUploadPolicyViolation(o)}`,{name:i.name});continue}a.push(e)}return a}function buildTeamsTurnMessage(e,t){return t.length===0?e:e.trim().length===0?[...t]:[{type:`text`,text:e},...t]}function createTeamsFetchFile(e){return async t=>{if(!e.enabled||!isAllowedUrl(t,e.allowedHosts))return null;let n=await fetch(t);if(!n.ok)throw Error(`Teams file fetch returned HTTP ${n.status} for ${t}.`);return{bytes:Buffer.from(await n.arrayBuffer()),mediaType:n.headers.get(`content-type`)??void 0}}}function toTeamsFilePart(e,t,n){let r=readAttachmentUrl(e);return!r||!isAllowedUrl(r,n.allowedHosts)?null:{data:new URL(r),filename:e.name??`teams-attachment-${t}`,mediaType:inferMediaType(e),type:`file`}}function readAttachmentUrl(e){return e.contentType===`application/vnd.microsoft.teams.file.download.info`&&isObject(e.content)&&typeof e.content.downloadUrl==`string`?e.content.downloadUrl:e.contentUrl&&!e.contentType.startsWith(`application/vnd.microsoft.card.`)?e.contentUrl:null}function inferMediaType(e){return e.contentType===`application/vnd.microsoft.teams.file.download.info`&&(isObject(e.content)&&typeof e.content.fileType==`string`?e.content.fileType:void 0)===`txt`?`text/plain`:e.contentType||`application/octet-stream`}function isAllowedUrl(e,t){if(t===`*`)return!0;let n;try{n=new URL(e)}catch{return!1}return t.some(e=>n.host===e||n.hostname===e)}export{buildTeamsTurnMessage,collectTeamsFileParts,createTeamsFetchFile,normalizeTeamsFilesPolicy};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{extractErrorId,formatErrorHint}from"#internal/logging.js";import{parseJsonObject}from"#shared/json.js";import{splitTeamsMessageText}from"#public/channels/teams/api.js";import{renderAnsweredInputRequestMessage,renderInputRequestMessage}from"#public/channels/teams/hitl.js";function defaultTeamsAuth(e){let t=e.tenantId,n={activity_id:e.id,conversation_id:e.conversation.id,scope:e.scope,user_id:e.from.id};e.from.name!==void 0&&(n.user_name=e.from.name),e.from.aadObjectId!==void 0&&(n.aad_object_id=e.from.aadObjectId),t!==void 0&&(n.tenant_id=t),e.teamId!==void 0&&(n.team_id=e.teamId),e.teamsChannelId!==void 0&&(n.channel_id=e.teamsChannelId);let r=t?`teams:${t}:${e.from.id}`:`teams:${e.from.id}`;return{attributes:n,authenticator:`teams-activity`,issuer:t?`teams:${t}`:`teams`,principalId:r,principalType:e.from.role===`bot`?`service`:`user`,subject:e.from.aadObjectId}}async function defaultOnMessage(e,t){return t.scope!==`personal`&&!t.isBotMentioned?null:(await e.thread.startTyping(),{auth:defaultTeamsAuth(t)})}
|
|
1
|
+
import{extractErrorId,formatErrorHint}from"#internal/logging.js";import{parseJsonObject}from"#shared/json.js";import{splitTeamsMessageText}from"#public/channels/teams/api.js";import{renderAnsweredInputRequestMessage,renderInputRequestMessage}from"#public/channels/teams/hitl.js";function defaultTeamsAuth(e){let t=e.tenantId,n={activity_id:e.id,conversation_id:e.conversation.id,scope:e.scope,user_id:e.from.id};e.from.name!==void 0&&(n.user_name=e.from.name),e.from.aadObjectId!==void 0&&(n.aad_object_id=e.from.aadObjectId),t!==void 0&&(n.tenant_id=t),e.teamId!==void 0&&(n.team_id=e.teamId),e.teamsChannelId!==void 0&&(n.channel_id=e.teamsChannelId);let r=t?`teams:${t}:${e.from.id}`:`teams:${e.from.id}`;return{attributes:n,authenticator:`teams-activity`,issuer:t?`teams:${t}`:`teams`,principalId:r,principalType:e.from.role===`bot`?`service`:`user`,subject:e.from.aadObjectId}}async function defaultOnMessage(e,t){return t.scope!==`personal`&&!t.isBotMentioned?null:(await e.thread.startTyping(),{auth:defaultTeamsAuth(t)})}const defaultEvents={async"turn.started"(e,t){await t.thread.startTyping()},async"actions.requested"(e,t){await t.thread.startTyping()},async"input.requested"(e,t){for(let n of e.requests)await t.thread.post(renderInputRequestMessage(n,{adaptiveCardVersion:t.adaptiveCardVersion}))},async"message.completed"(e,t){if(!(e.finishReason===`tool-calls`||!e.message))for(let n of splitTeamsMessageText(e.message))await t.thread.post(n)},async"session.failed"(n,r){let i=formatErrorHint(n),a=extractErrorId(n.details);await r.thread.post([`This session could not recover from an error${i}.`,``,`Start a new Teams conversation to continue.`,...a?[``,`Error id: ${a}`]:[]].join(`
|
|
2
2
|
`))},async"turn.failed"(n,r){let i=formatErrorHint(n),a=extractErrorId(n.details);await r.thread.post([`I hit an error while handling your request${i}.`,``,`Please try again, rephrase, or reach out if it keeps failing.`,...a?[``,`Error id: ${a}`]:[]].join(`
|
|
3
3
|
`))},async"connection.authorization_required"(e,t){let r=formatConnectionDisplayName(e.connectionName),i=e.authorization?.url,a=i?`Authorization required for ${r}: ${i}`:`Authorization required for ${r}.`,o=await t.thread.post({attachments:[{content:parseJsonObject({$schema:`http://adaptivecards.io/schemas/adaptive-card.json`,actions:i?[{title:`Sign in with ${r}`,type:`Action.OpenUrl`,url:i}]:[],body:[{text:`Authorization required for ${r}`,type:`TextBlock`,weight:`Bolder`,wrap:!0},{text:t.state.triggeringUser?`Requested by ${t.state.triggeringUser.name??t.state.triggeringUser.id}.`:`No triggering user is available for a private prompt.`,type:`TextBlock`,wrap:!0}],type:`AdaptiveCard`,version:t.adaptiveCardVersion}),contentType:`application/vnd.microsoft.card.adaptive`}],text:a});o.id&&(t.state.pendingAuthActivityId=o.id)},async"connection.authorization_completed"(e,t){let n=t.state.pendingAuthActivityId;if(!n)return;let r=buildAuthCompletedText({displayName:formatConnectionDisplayName(e.connectionName),outcome:e.outcome,reason:e.reason});await t.thread.update(n,renderAnsweredInputRequestMessage({prompt:r})),t.state.pendingAuthActivityId=null}};function formatConnectionDisplayName(e){return e.length===0?e:e.charAt(0).toUpperCase()+e.slice(1)}function buildAuthCompletedText(e){if(e.outcome===`authorized`)return`${e.displayName} connected.`;let t=e.reason===void 0?``:` (${e.reason})`;return`${e.displayName} authorization ${e.outcome}${t}.`}function teamsMentionUser(e){let t=e.name??e.id;return{mentioned:{id:e.id,name:e.name},text:`<at>${t}</at>`,type:`mention`}}export{buildAuthCompletedText,defaultEvents,defaultOnMessage,defaultTeamsAuth,formatConnectionDisplayName,teamsMentionUser};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{isObject}from"#shared/guards.js";import{parseJsonObject}from"#shared/json.js";import{TEAMS_ADAPTIVE_CARD_ACTION_LIMIT,TEAMS_ADAPTIVE_CARD_ACTION_TITLE_MAX_LENGTH,TEAMS_ADAPTIVE_CARD_CHOICE_TITLE_MAX_LENGTH,TEAMS_ADAPTIVE_CARD_TEXT_MAX_LENGTH}from"#public/channels/teams/limits.js";
|
|
1
|
+
import{isObject}from"#shared/guards.js";import{parseJsonObject}from"#shared/json.js";import{TEAMS_ADAPTIVE_CARD_ACTION_LIMIT,TEAMS_ADAPTIVE_CARD_ACTION_TITLE_MAX_LENGTH,TEAMS_ADAPTIVE_CARD_CHOICE_TITLE_MAX_LENGTH,TEAMS_ADAPTIVE_CARD_TEXT_MAX_LENGTH}from"#public/channels/teams/limits.js";const TEAMS_ADAPTIVE_CARD_CONTENT_TYPE=`application/vnd.microsoft.card.adaptive`,TEAMS_HITL_DATA_KEY=`ash_input`,TEAMS_HITL_CHOICE_INPUT_ID=`ash_option`,TEAMS_HITL_FREEFORM_INPUT_ID=`ash_freeform_text`;function renderInputRequestMessage(e,t={}){return{attachments:[renderInputRequestAttachment(e,t)],text:e.prompt}}function renderInputRequestAttachment(e,n={}){return{content:parseJsonObject({$schema:`http://adaptivecards.io/schemas/adaptive-card.json`,actions:renderActions(e),body:[{text:truncate(e.prompt,TEAMS_ADAPTIVE_CARD_TEXT_MAX_LENGTH),type:`TextBlock`,wrap:!0},...renderInputs(e)],type:`AdaptiveCard`,version:n.adaptiveCardVersion??`1.5`}),contentType:TEAMS_ADAPTIVE_CARD_CONTENT_TYPE}}function renderAnsweredInputRequestMessage(e){return{attachments:[{content:parseJsonObject({$schema:`http://adaptivecards.io/schemas/adaptive-card.json`,body:[{text:truncate(e.prompt,TEAMS_ADAPTIVE_CARD_TEXT_MAX_LENGTH),type:`TextBlock`,wrap:!0},{color:`good`,text:e.label?`Answered: ${e.label}`:`Answered`,type:`TextBlock`,wrap:!0}],type:`AdaptiveCard`,version:`1.5`}),contentType:TEAMS_ADAPTIVE_CARD_CONTENT_TYPE}],text:e.label?`Answered: ${e.label}`:`Answered`}}function isTeamsInputResponseActivity(e){return deriveTeamsInputResponses(e).length>0}function deriveTeamsInputResponses(e){let t=readActivityValue(e);if(!t)return[];let n=readHitlPayload(t);if(!n)return[];let r=typeof n.requestId==`string`?n.requestId:``;if(!r)return[];let i=typeof n.optionId==`string`?n.optionId:typeof t.ash_option==`string`?t[TEAMS_HITL_CHOICE_INPUT_ID]:void 0,a=typeof t.ash_freeform_text==`string`?t[TEAMS_HITL_FREEFORM_INPUT_ID]:void 0;return i===void 0?a===void 0?[{requestId:r}]:[{requestId:r,text:a}]:[{optionId:i,requestId:r}]}function teamsInvokeResponse(e={}){return{statusCode:e.statusCode??200,type:`application/vnd.microsoft.activity.message`,value:e.message??`Answer received.`}}function renderInputs(e){return e.display===`select`&&e.options&&e.options.length>0?[{choices:e.options.map(e=>({title:truncate(e.label,TEAMS_ADAPTIVE_CARD_CHOICE_TITLE_MAX_LENGTH),value:e.id})),id:TEAMS_HITL_CHOICE_INPUT_ID,isMultiSelect:!1,style:`compact`,type:`Input.ChoiceSet`}]:e.allowFreeform===!0||!e.options||e.options.length===0?[{id:TEAMS_HITL_FREEFORM_INPUT_ID,isMultiline:!0,placeholder:`Type your answer`,type:`Input.Text`}]:[]}function renderActions(e){let t=e.options;return t&&t.length>0&&e.display!==`select`?t.slice(0,TEAMS_ADAPTIVE_CARD_ACTION_LIMIT).map(t=>({data:{[TEAMS_HITL_DATA_KEY]:{optionId:t.id,requestId:e.requestId}},title:truncate(t.label,TEAMS_ADAPTIVE_CARD_ACTION_TITLE_MAX_LENGTH),type:`Action.Submit`})):[{data:{[TEAMS_HITL_DATA_KEY]:{requestId:e.requestId}},title:`Submit`,type:`Action.Submit`}]}function readActivityValue(e){return e.type===`message`?readMessageValue(e):e.type===`invoke`?readInvokeValue(e):null}function readMessageValue(e){return e.value??null}function readInvokeValue(t){let n=t.value;if(!n)return null;let r=isObject(n.action)?n.action:null;return(r&&isObject(r.data)?r.data:null)??n}function readHitlPayload(t){let n=t[TEAMS_HITL_DATA_KEY];if(isObject(n))return n;let r=isObject(t.action)?t.action:null,i=(r&&isObject(r.data)?r.data:null)?.[TEAMS_HITL_DATA_KEY];return isObject(i)?i:null}function truncate(e,t){if(e.length<=t)return e;let n=Math.max(0,t-3);return`${e.slice(0,n).trimEnd()}...`}export{TEAMS_ADAPTIVE_CARD_CONTENT_TYPE,TEAMS_HITL_CHOICE_INPUT_ID,TEAMS_HITL_DATA_KEY,TEAMS_HITL_FREEFORM_INPUT_ID,deriveTeamsInputResponses,isTeamsInputResponseActivity,renderAnsweredInputRequestMessage,renderInputRequestAttachment,renderInputRequestMessage,teamsInvokeResponse};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{isNonEmptyString,isObject}from"#shared/guards.js";import{parseJsonObject}from"#shared/json.js";import TurndownService from"#compiled/turndown/index.js";
|
|
1
|
+
import{isNonEmptyString,isObject}from"#shared/guards.js";import{parseJsonObject}from"#shared/json.js";import TurndownService from"#compiled/turndown/index.js";const HTML_ENTITY_MAP={"&":`&`,">":`>`,"<":`<`," ":` `,""":`"`,"'":`'`,"'":`'`},HTML_ENTITY_PATTERN=new RegExp(Object.keys(HTML_ENTITY_MAP).join(`|`),`gi`);let turndownService=null;function parseTeamsActivity(e){return isObject(e)?e.type===`message`?parseMessageActivity(e):e.type===`invoke`?parseInvokeActivity(e):e.type===`conversationUpdate`?parseConversationUpdateActivity(e):null:null}function isTeamsPersonalMessage(e){return e.scope===`personal`}function teamsThreadRootActivityId(e){return e.scope===`personal`?null:e.replyToId??e.id}function formatTeamsContextBlock(e){return[`<teams_context>`,`response_medium: microsoft_teams`,`response_instructions: Reply for Microsoft Teams in concise Markdown. Avoid broad mentions, large tables, and messages that need more than a few short posts.`,`user_id: ${e.userId}`,...e.userName?[`user_name: ${e.userName}`]:[],`conversation_id: ${e.conversationId}`,`scope: ${e.scope}`,...e.conversationType?[`conversation_type: ${e.conversationType}`]:[],...e.tenantId?[`tenant_id: ${e.tenantId}`]:[],...e.teamId?[`team_id: ${e.teamId}`]:[],...e.channelId?[`channel_id: ${e.channelId}`]:[],`activity_id: ${e.activityId}`,`</teams_context>`].join(`
|
|
2
2
|
`)}function prependTeamsContext(e,t){let n=formatTeamsContextBlock(t);return typeof e==`string`?e.length>0?`${n}\n\n${e}`:n:[{type:`text`,text:n},...e]}function parseMessageActivity(n){let r=parseActivityBase(n);if(!r)return null;let i=parseMentions(n.entities),a=normalizeTeamsText(stripBotMention(readText(n),i,r.recipient.id));return{...r,attachments:parseAttachments(n.attachments),isBotMentioned:i.some(e=>e.mentioned.id===r.recipient.id),mentions:i,replyToId:isNonEmptyString(n.replyToId)?n.replyToId:void 0,scope:inferScope(r.conversation),text:a,textFormat:isNonEmptyString(n.textFormat)?n.textFormat:void 0,type:`message`,value:isObject(n.value)?n.value:void 0}}function parseInvokeActivity(n){let r=parseActivityBase(n);return!r||!isNonEmptyString(n.name)?null:{...r,name:n.name,replyToId:isNonEmptyString(n.replyToId)?n.replyToId:void 0,scope:inferScope(r.conversation),type:`invoke`,value:isObject(n.value)?n.value:void 0}}function parseConversationUpdateActivity(e){let t=parseActivityBase(e);return t?{...t,type:`conversationUpdate`}:null}function parseActivityBase(n){if(!isNonEmptyString(n.serviceUrl))return null;let r=parseConversation(n.conversation),i=parseChannelAccount(n.from),a=parseChannelAccount(n.recipient);if(!r||!i||!a)return null;let o=isObject(n.channelData)?n.channelData:{},s=readNestedString(o,[`tenant`,`id`])??r.tenantId,c=readNestedString(o,[`team`,`id`]),l=readNestedString(o,[`channel`,`id`]);return{channelData:o,conversation:r,conversationType:r.conversationType,from:i,id:isNonEmptyString(n.id)?n.id:``,raw:n,recipient:a,serviceUrl:n.serviceUrl,tenantId:s,teamId:c,teamsChannelId:l}}function parseConversation(n){return!isObject(n)||!isNonEmptyString(n.id)?null:{conversationType:isNonEmptyString(n.conversationType)?n.conversationType:void 0,id:n.id,isGroup:typeof n.isGroup==`boolean`?n.isGroup:void 0,name:isNonEmptyString(n.name)?n.name:void 0,tenantId:isNonEmptyString(n.tenantId)?n.tenantId:void 0}}function parseChannelAccount(n){return!isObject(n)||!isNonEmptyString(n.id)?null:{aadObjectId:isNonEmptyString(n.aadObjectId)?n.aadObjectId:void 0,id:n.id,name:isNonEmptyString(n.name)?n.name:void 0,role:isNonEmptyString(n.role)?n.role:void 0}}function parseMentions(n){if(!Array.isArray(n))return[];let r=[];for(let i of n){if(!isObject(i)||i.type!==`mention`||!isNonEmptyString(i.text))continue;let n=parseChannelAccount(i.mentioned);n&&r.push({mentioned:n,text:i.text,type:`mention`})}return r}function parseAttachments(r){if(!Array.isArray(r))return[];let i=[];for(let a of r){if(!isObject(a)||!isNonEmptyString(a.contentType))continue;let r={content:isObject(a.content)?parseJsonObject(a.content):void 0,contentType:a.contentType,contentUrl:isNonEmptyString(a.contentUrl)?a.contentUrl:void 0,name:isNonEmptyString(a.name)?a.name:void 0};i.push(r)}return i}function inferScope(e){let t=e.conversationType;return t===`personal`||t===`groupChat`||t===`channel`?t:e.isGroup===!0?`groupChat`:e.isGroup===!1?`personal`:`unknown`}function readText(e){return typeof e.text==`string`?e.text:``}function stripBotMention(e,t,n){let r=e;for(let e of t)e.mentioned.id===n&&(r=r.replace(e.text,``));return r.trim()}function normalizeTeamsText(e){let t=e.trim();return looksLikeHtml(t)?getTurndownService().turndown(t.replace(/<at>(.*?)<\/at>/gi,`@$1`)).replace(/ {2}\n/g,`
|
|
3
3
|
`).trim():decodeHtmlEntities(t)}function readNestedString(n,r){let i=n;for(let e of r){if(!isObject(i))return;i=i[e]}return isNonEmptyString(i)?i:void 0}function looksLikeHtml(e){return/<\/?[a-z][\s\S]*>/i.test(e)}function decodeHtmlEntities(e){return e.replace(HTML_ENTITY_PATTERN,e=>HTML_ENTITY_MAP[e.toLowerCase()]??e)}function getTurndownService(){return turndownService??=new TurndownService({bulletListMarker:`-`,codeBlockStyle:`fenced`,emDelimiter:`*`,headingStyle:`atx`,hr:`---`}),turndownService}export{formatTeamsContextBlock,isTeamsPersonalMessage,parseTeamsActivity,prependTeamsContext,teamsThreadRootActivityId};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
const TEAMS_ADAPTIVE_CARD_TEXT_MAX_LENGTH=4e3,TEAMS_ADAPTIVE_CARD_ACTION_TITLE_MAX_LENGTH=80,TEAMS_ADAPTIVE_CARD_CHOICE_TITLE_MAX_LENGTH=100,TEAMS_ADAPTIVE_CARD_ACTION_LIMIT=6;export{TEAMS_ADAPTIVE_CARD_ACTION_LIMIT,TEAMS_ADAPTIVE_CARD_ACTION_TITLE_MAX_LENGTH,TEAMS_ADAPTIVE_CARD_CHOICE_TITLE_MAX_LENGTH,TEAMS_ADAPTIVE_CARD_TEXT_MAX_LENGTH};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createLogger}from"#internal/logging.js";import{parseJsonObject}from"#shared/json.js";import{POST,defineChannel}from"#public/definitions/defineChannel.js";import{callTeamsConnectorApi,normalizeTeamsPostInput,replyToTeamsActivity,sendTeamsActivity,teamsContinuationToken,triggerTeamsTypingIndicator,updateTeamsActivity}from"#public/channels/teams/api.js";import{deriveTeamsInputResponses,isTeamsInputResponseActivity,teamsInvokeResponse}from"#public/channels/teams/hitl.js";import{parseTeamsActivity,prependTeamsContext,teamsThreadRootActivityId}from"#public/channels/teams/inbound.js";import{buildTeamsTurnMessage,collectTeamsFileParts,createTeamsFetchFile,normalizeTeamsFilesPolicy}from"#public/channels/teams/attachments.js";import{defaultEvents,defaultOnMessage,teamsMentionUser}from"#public/channels/teams/defaults.js";import{verifyTeamsRequest}from"#public/channels/teams/verify.js";
|
|
1
|
+
import{createLogger}from"#internal/logging.js";import{parseJsonObject}from"#shared/json.js";import{POST,defineChannel}from"#public/definitions/defineChannel.js";import{callTeamsConnectorApi,normalizeTeamsPostInput,replyToTeamsActivity,sendTeamsActivity,teamsContinuationToken,triggerTeamsTypingIndicator,updateTeamsActivity}from"#public/channels/teams/api.js";import{deriveTeamsInputResponses,isTeamsInputResponseActivity,teamsInvokeResponse}from"#public/channels/teams/hitl.js";import{parseTeamsActivity,prependTeamsContext,teamsThreadRootActivityId}from"#public/channels/teams/inbound.js";import{buildTeamsTurnMessage,collectTeamsFileParts,createTeamsFetchFile,normalizeTeamsFilesPolicy}from"#public/channels/teams/attachments.js";import{defaultEvents,defaultOnMessage,teamsMentionUser}from"#public/channels/teams/defaults.js";import{verifyTeamsRequest}from"#public/channels/teams/verify.js";const log=createLogger(`teams.channel`);function teamsChannel(e={}){let i=normalizeTeamsFilesPolicy(e.files),a=e.onMessage??defaultOnMessage,o={...defaultEvents,...e.events};return defineChannel({kindHint:`teams`,state:initialTeamsState(),fetchFile:createTeamsFetchFile(i),context(t,n){return rebuildTeamsContext(t,n,e)},routes:[POST(e.route??`/ash/v1/teams`,async(n,{send:r,waitUntil:o})=>{let s=await verifyInbound(n,e.credentials);if(s===null)return new Response(`unauthorized`,{status:401});let c;try{c=parseJsonObject(JSON.parse(s))}catch(e){return log.warn(`inbound Teams body is not valid JSON`,{error:e}),teamsOk()}let l=parseTeamsActivity(c);return l===null?teamsOk():l.type===`message`?(o(dispatchMessage({activity:l,config:e,filesPolicy:i,onMessage:a,send:r})),teamsOk()):l.type===`invoke`?handleInvoke({activity:l,config:e,send:r,waitUntil:o}):teamsOk()})],async receive(t,{send:n}){let r=t.args,i=readString(r.serviceUrl),a=readString(r.conversationId);if(!i||!a)throw Error(`teamsChannel().receive requires args.serviceUrl and args.conversationId.`);let o=readString(r.conversationType)??null,s=readString(r.replyToActivityId)??null,l=r.initialMessage;if(l!==void 0&&s!==null)throw Error("teamsChannel().receive: `replyToActivityId` and `initialMessage` are mutually exclusive.");let u={...initialTeamsState(),channelId:readString(r.channelId)??null,conversationId:a,conversationType:o,replyToActivityId:s,serviceUrl:i,teamId:readString(r.teamId)??null,tenantId:readString(r.tenantId)??null};if(l!==void 0){let t=await buildTeamsBinding({config:e,state:u}).thread.post(l);o!==`personal`&&t.id&&(s=t.id,u.replyToActivityId=t.id)}return n(t.message,{auth:t.auth,continuationToken:teamsContinuationToken({conversationId:a,replyToActivityId:s,tenantId:u.tenantId}),state:u})},events:o})}function rebuildTeamsContext(e,t,n){return{...buildTeamsBinding({config:n,session:t,state:e}),adaptiveCardVersion:n.adaptiveCardVersion??`1.5`,session:t,state:e}}function buildTeamsBinding(e){let t=buildTeamsHandle(e);return{teams:t,thread:{mentionUser:teamsMentionUser,post(e){return t.sendActivity(e)},async startTyping(){try{await t.startTyping()}catch(e){log.debug(`Teams typing indicator failed — swallowed`,{error:e})}},update(e,n){return t.updateActivity(e,n)}}}}function buildTeamsHandle(e){let t=e.state,n=e.config.api,r=e.config.credentials;function requireAddress(){let e=t.conversationId??``,n=t.serviceUrl??``;if(!e||!n)throw Error(`teamsChannel: missing serviceUrl or conversationId for outbound message.`);return{conversationId:e,serviceUrl:n}}function anchor(n){if(!n.id||t.replyToActivityId||t.conversationType===`personal`)return;t.replyToActivityId=n.id;let r=t.conversationId;r&&e.session?.setContinuationToken(teamsContinuationToken({conversationId:r,replyToActivityId:n.id,tenantId:t.tenantId}))}async function send(e){let i=requireAddress(),a=buildOutboundActivity(t,e),c=t.replyToActivityId===null?await sendTeamsActivity({...n,body:a,credentials:r,conversationId:i.conversationId,serviceUrl:i.serviceUrl}):await replyToTeamsActivity({...n,body:a,credentials:r,activityId:t.replyToActivityId,conversationId:i.conversationId,serviceUrl:i.serviceUrl});return anchor(c),c}return{channelId:t.channelId??void 0,conversationId:t.conversationId??``,conversationType:t.conversationType??void 0,replyToActivityId:t.replyToActivityId??void 0,serviceUrl:t.serviceUrl??``,teamId:t.teamId??void 0,tenantId:t.tenantId??void 0,request(e,t,a){let o=requireAddress();return callTeamsConnectorApi({...n,body:t,credentials:r,method:a?.method,path:e,serviceUrl:o.serviceUrl})},sendActivity:send,replyToActivity(e){let i=requireAddress(),a=t.replyToActivityId??``;if(!a)throw Error(`teamsChannel: missing reply activity id.`);return replyToTeamsActivity({...n,body:buildOutboundActivity(t,e),credentials:r,activityId:a,conversationId:i.conversationId,serviceUrl:i.serviceUrl})},updateActivity(e,i){let a=requireAddress();return updateTeamsActivity({...n,body:buildOutboundActivity(t,i),credentials:r,activityId:e,conversationId:a.conversationId,serviceUrl:a.serviceUrl})},async startTyping(){let e=requireAddress();await triggerTeamsTypingIndicator({...n,credentials:r,conversationId:e.conversationId,serviceUrl:e.serviceUrl})}}}async function verifyInbound(e,t){try{return await verifyTeamsRequest(e,{appId:t?.webhookVerifier?void 0:t?.appId,webhookVerifier:t?.webhookVerifier})}catch(e){return log.warn(`teams inbound verification failed`,{error:e}),null}}async function dispatchMessage(e){let t=stateFromActivity(e.activity),n=buildTeamsBinding({config:e.config,state:t}),r;try{r=await e.onMessage(n,e.activity)}catch(e){log.error(`Teams message handler failed`,{error:e});return}if(r==null)return;let i=collectTeamsFileParts(e.activity.attachments,e.filesPolicy),a=prependTeamsContext(buildTeamsTurnMessage(e.activity.text,i),{activityId:e.activity.id,channelId:e.activity.teamsChannelId,conversationId:e.activity.conversation.id,conversationType:e.activity.conversationType,scope:e.activity.scope,teamId:e.activity.teamId,tenantId:e.activity.tenantId,userId:e.activity.from.id,userName:e.activity.from.name});try{await e.send({message:a,modelContext:r.modelContext},{auth:r.auth,continuationToken:stateToken(t),state:t})}catch(e){log.error(`Teams message delivery failed`,{error:e})}}async function handleInvoke(e){if(isTeamsInputResponseActivity(e.activity))return e.waitUntil(dispatchInputResponses({activity:e.activity,send:e.send})),Response.json(teamsInvokeResponse());if(e.config.onInvoke===void 0)return teamsOk();let t=buildTeamsBinding({config:e.config,state:stateFromActivity(e.activity)}),n=await e.config.onInvoke(t,e.activity);return n instanceof Response?n:n&&typeof n==`object`?Response.json(n):teamsOk()}async function dispatchInputResponses(e){let t=deriveTeamsInputResponses(e.activity);if(t.length===0)return;let n=stateFromActivity(e.activity);try{await e.send({inputResponses:t},{auth:null,continuationToken:stateToken(n),state:n})}catch(e){log.error(`Teams input response delivery failed`,{error:e})}}function stateFromActivity(e){return{bot:e.recipient,channelId:e.teamsChannelId??null,conversationId:e.conversation.id,conversationType:e.conversationType??e.scope,pendingAuthActivityId:null,replyToActivityId:teamsThreadRootActivityId(e),serviceUrl:e.serviceUrl,teamId:e.teamId??null,tenantId:e.tenantId??null,triggeringUser:e.from}}function initialTeamsState(){return{bot:null,channelId:null,conversationId:null,conversationType:null,pendingAuthActivityId:null,replyToActivityId:null,serviceUrl:null,teamId:null,tenantId:null,triggeringUser:null}}function stateToken(e){let t=e.conversationId??``;if(!t)throw Error(`teamsChannel: missing conversation id.`);return teamsContinuationToken({conversationId:t,replyToActivityId:e.replyToActivityId,tenantId:e.tenantId})}function buildOutboundActivity(e,t){if(typeof t!=`string`&&`type`in t&&t.type===`typing`)return t;let n=normalizeTeamsPostInput(t),r=mergeChannelData(e,n.channelData);return{...n,channelData:r,conversation:e.conversationId?{id:e.conversationId}:void 0,from:e.bot??void 0,replyToId:e.replyToActivityId??void 0,type:`message`}}function mergeChannelData(e,n){let r={...n};return e.tenantId&&(r.tenant={id:e.tenantId}),e.teamId&&(r.team={id:e.teamId}),e.channelId&&(r.channel={id:e.channelId}),Object.keys(r).length>0?parseJsonObject(r):void 0}function teamsOk(){return new Response(`ok`,{status:200})}function readString(e){return typeof e==`string`&&e.length>0?e:void 0}export{teamsChannel};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createLogger}from"#internal/logging.js";import{isObject}from"#shared/guards.js";import{importJWK,jwtVerify}from"#compiled/jose/index.js";import{resolveTeamsAppId}from"#public/channels/teams/api.js";
|
|
1
|
+
import{createLogger}from"#internal/logging.js";import{isObject}from"#shared/guards.js";import{importJWK,jwtVerify}from"#compiled/jose/index.js";import{resolveTeamsAppId}from"#public/channels/teams/api.js";const log=createLogger(`teams.verify`);async function verifyTeamsRequest(e,t){let n=await e.text();if(t.webhookVerifier!==void 0){let r=await t.webhookVerifier(e,n);if(!r)throw Error(`teamsChannel: inbound webhook verifier rejected the request.`);return typeof r==`string`?r:n}let r=readBearerToken(e.headers.get(`authorization`)??``);if(!r)throw Error(`teamsChannel: inbound request missing bearer token.`);return await verifyTeamsJwt(r,t),n}async function verifyTeamsJwt(e,t){let a=await resolveTeamsAppId(t.appId),o=await loadJwks(t);return(await jwtVerify(e,async e=>importJWK(selectJwk(o,e),typeof e.alg==`string`?e.alg:void 0),{audience:a,clockTolerance:t.maxSkewSeconds??300,issuer:`https://api.botframework.com`})).payload}function readBearerToken(e){let[t,n]=e.split(/\s+/,2);return t?.toLowerCase()!==`bearer`||!n?null:n}async function loadJwks(e){let n=e.fetch??fetch,r=await n(e.jwksUrl??await loadJwksUrl(e,n),{headers:{accept:`application/json`}});if(!r.ok)throw Error(`Teams JWKS route returned HTTP ${r.status}.`);let i=await r.json();if(!isObject(i)||!Array.isArray(i.keys))throw Error(`Teams JWKS response is malformed.`);return i.keys.filter(isObject)}async function loadJwksUrl(e,n){let r=await n(e.openIdMetadataUrl??`https://login.botframework.com/v1/.well-known/openidconfiguration`,{headers:{accept:`application/json`}});if(!r.ok)throw Error(`Teams OpenID metadata route returned HTTP ${r.status}.`);let i=await r.json();if(!isObject(i)||typeof i.jwks_uri!=`string`)throw Error(`Teams OpenID metadata response is missing jwks_uri.`);return i.jwks_uri}function selectJwk(e,t){let n=typeof t.kid==`string`?t.kid:void 0,r=typeof t.x5t==`string`?t.x5t:void 0,i=e.find(e=>n!==void 0&&e.kid===n||r!==void 0&&e.x5t===r)??(e.length===1?e[0]:void 0);if(i===void 0)throw log.debug(`Teams JWT key not found`,{kid:n,x5t:r}),Error(`teamsChannel: inbound JWT key was not found in JWKS.`);return i}export{verifyTeamsJwt,verifyTeamsRequest};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{isObject}from"#shared/guards.js";import{parseJsonObject}from"#shared/json.js";
|
|
1
|
+
import{isObject}from"#shared/guards.js";import{parseJsonObject}from"#shared/json.js";const TELEGRAM_MESSAGE_TEXT_MAX_LENGTH=4096;function telegramContinuationToken(e){let t=e.messageThreadId===void 0?``:String(e.messageThreadId),n=e.conversationId===void 0?``:String(e.conversationId);return`${String(e.chatId)}:${t}:${n}`}async function resolveTelegramBotToken(e){let t=e??process.env.TELEGRAM_BOT_TOKEN;if(!t)throw Error(`TELEGRAM_BOT_TOKEN is required.`);return typeof t==`function`?await t():t}async function callTelegramApi(e){let n=e.fetch??fetch,r=await resolveTelegramBotToken(e.botToken),i={headers:{"content-type":`application/json; charset=utf-8`},method:`POST`};e.body!==void 0&&(i.body=JSON.stringify(parseJsonObject(e.body)));let a=await n(`${e.apiBaseUrl??`https://api.telegram.org`}/bot${r}/${encodeURIComponent(e.method)}`,i);return{body:await parseResponseBody(a),ok:a.ok,status:a.status}}async function sendTelegramMessage(e){let t=await callTelegramApi({apiBaseUrl:e.apiBaseUrl,body:normalizeTelegramMessageBody(e.body,e.chatId),botToken:e.credentials?.botToken,fetch:e.fetch,method:`sendMessage`});if(!t.ok)throw Error(`Telegram sendMessage failed with HTTP ${t.status}.`);return toTelegramMessageResult(t.body)}async function sendTelegramChatAction(e){return callTelegramApi({apiBaseUrl:e.apiBaseUrl,body:parseJsonObject({action:e.action,chat_id:e.chatId,message_thread_id:e.messageThreadId}),botToken:e.credentials?.botToken,fetch:e.fetch,method:`sendChatAction`})}async function answerTelegramCallbackQuery(e){return callTelegramApi({apiBaseUrl:e.apiBaseUrl,body:parseJsonObject({callback_query_id:e.callbackQueryId,show_alert:e.showAlert,text:e.text}),botToken:e.credentials?.botToken,fetch:e.fetch,method:`answerCallbackQuery`})}async function editTelegramMessageReplyMarkup(e){return callTelegramApi({apiBaseUrl:e.apiBaseUrl,body:parseJsonObject({chat_id:e.chatId,message_id:Number(e.messageId),reply_markup:e.replyMarkup}),botToken:e.credentials?.botToken,fetch:e.fetch,method:`editMessageReplyMarkup`})}async function getTelegramFile(t){let n=await callTelegramApi({apiBaseUrl:t.apiBaseUrl,body:{file_id:t.fileId},botToken:t.credentials?.botToken,fetch:t.fetch,method:`getFile`});if(!n.ok)throw Error(`Telegram getFile failed with HTTP ${n.status}.`);let r=isObject(n.body)?n.body:{},i=isObject(r.result)?r.result:{};if(typeof i.file_path!=`string`||i.file_path.length===0)throw Error(`Telegram getFile response did not include result.file_path.`);return{filePath:i.file_path,raw:n.body}}async function downloadTelegramFile(e){let t=e.fetch??fetch,n=await resolveTelegramBotToken(e.credentials?.botToken);return t(`${e.fileBaseUrl??e.apiBaseUrl??`https://api.telegram.org`}/file/bot${n}/${e.filePath}`)}function splitTelegramMessageText(e){if(e.length<=4096)return[e];let t=[],r=e;for(;r.length>TELEGRAM_MESSAGE_TEXT_MAX_LENGTH;){let e=r.lastIndexOf(`
|
|
2
2
|
`,TELEGRAM_MESSAGE_TEXT_MAX_LENGTH);e<=0&&(e=r.lastIndexOf(` `,TELEGRAM_MESSAGE_TEXT_MAX_LENGTH)),e<=0&&(e=TELEGRAM_MESSAGE_TEXT_MAX_LENGTH),t.push(r.slice(0,e).trimEnd()),r=r.slice(e).trimStart()}return t.push(r),t}function normalizeTelegramMessageBody(e,n){return parseJsonObject({...e,chat_id:n})}function toTelegramMessageResult(t){let n=isObject(t)?t:{},r=isObject(n.result)?n.result:{},i=isObject(r.chat)?r.chat:{};return{chatId:typeof i.id==`number`||typeof i.id==`string`?String(i.id):void 0,id:typeof r.message_id==`number`||typeof r.message_id==`string`?String(r.message_id):``,raw:t}}async function parseResponseBody(e){let t=await e.text();if(!t)return null;try{return JSON.parse(t)}catch{return t}}export{TELEGRAM_MESSAGE_TEXT_MAX_LENGTH,answerTelegramCallbackQuery,callTelegramApi,downloadTelegramFile,editTelegramMessageReplyMarkup,getTelegramFile,resolveTelegramBotToken,sendTelegramChatAction,sendTelegramMessage,splitTelegramMessageText,telegramContinuationToken};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createLogger}from"#internal/logging.js";import{evaluateFilePart,formatUploadPolicyViolation,isMediaTypeAllowed,isUploadsDisabled}from"#public/channels/upload-policy.js";import{downloadTelegramFile,getTelegramFile}from"#public/channels/telegram/api.js";
|
|
1
|
+
import{createLogger}from"#internal/logging.js";import{evaluateFilePart,formatUploadPolicyViolation,isMediaTypeAllowed,isUploadsDisabled}from"#public/channels/upload-policy.js";import{downloadTelegramFile,getTelegramFile}from"#public/channels/telegram/api.js";const log=createLogger(`telegram.attachments`),TELEGRAM_FILE_URL_PROTOCOL=`telegram-file:`;function collectTelegramFileParts(e,t){if(isUploadsDisabled(t))return[];let r=[];for(let i of e){let e=toTelegramFilePart(i,r.length);if(e===null)continue;let a=evaluateTelegramFilePart(e,i.size,t);if(a!==null){log.warn(`dropped attachment — ${formatUploadPolicyViolation(a)}`,{fileId:i.fileId,name:i.fileName});continue}r.push(e)}return r}function buildTelegramTurnMessage(e,t){let n=e.text||e.caption;return t.length===0?n:n.trim().length===0?[...t]:[{type:`text`,text:n},...t]}function createTelegramFetchFile(e){return async r=>{let i=parseTelegramFileUrl(r);if(i===null)return null;let o=await getTelegramFile({apiBaseUrl:e.api?.apiBaseUrl,credentials:e.credentials,fetch:e.api?.fetch,fileId:i.fileId}),s=await downloadTelegramFile({apiBaseUrl:e.api?.apiBaseUrl,credentials:e.credentials,fetch:e.api?.fetch,fileBaseUrl:e.api?.fileBaseUrl,filePath:o.filePath});if(!s.ok)throw Error(`Telegram file fetch returned HTTP ${s.status} for ${r}.`);let c=Buffer.from(await s.arrayBuffer()),l=s.headers.get(`content-type`)??i.mediaType??`application/octet-stream`,u={bytes:c,filename:i.filename,mediaType:l},d=evaluateFilePart({data:u.bytes,filename:u.filename,mediaType:l,type:`file`},e.policy);if(d!==null)throw Error(`Telegram file rejected — ${formatUploadPolicyViolation(d)}`);return u}}function createTelegramFileUrl(e){let t=new URLSearchParams;e.filename!==void 0&&t.set(`filename`,e.filename),e.mediaType!==void 0&&t.set(`mediaType`,e.mediaType);let n=t.size>0?`?${t.toString()}`:``;return new URL(`${TELEGRAM_FILE_URL_PROTOCOL}${encodeURIComponent(e.fileId)}${n}`)}function toTelegramFilePart(e,t){let n=e.mediaType??(e.kind===`photo`?`image/jpeg`:`application/octet-stream`),r=e.fileName??(e.kind===`photo`?`photo-${t}.jpg`:`file-${t}`);return{data:createTelegramFileUrl({fileId:e.fileId,filename:r,mediaType:n}),filename:r,mediaType:n,type:`file`}}function parseTelegramFileUrl(e){let t;try{t=new URL(e)}catch{return null}if(t.protocol!==`telegram-file:`)return null;let n=decodeURIComponent(t.pathname);return n?{fileId:n,filename:t.searchParams.get(`filename`)??void 0,mediaType:t.searchParams.get(`mediaType`)??void 0}:null}function evaluateTelegramFilePart(e,n,i){return i===`disabled`||!isMediaTypeAllowed(e.mediaType,i)?evaluateFilePart(e,i):n!==void 0&&n>i.maxBytes?{byteLength:n,filename:e.filename,kind:`too-large`,limit:i.maxBytes,mediaType:e.mediaType}:null}export{TELEGRAM_FILE_URL_PROTOCOL,buildTelegramTurnMessage,collectTelegramFileParts,createTelegramFetchFile,createTelegramFileUrl};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{extractErrorId,formatErrorHint}from"#internal/logging.js";import{registerTelegramFreeformPrompt,renderTelegramInputRequest}from"#public/channels/telegram/hitl.js";function defaultTelegramAuth(e){let t=e.from;if(!t)return null;let n={chat_id:e.chat.id,chat_type:e.chat.type,message_id:e.messageId,user_id:t.id};e.chat.title!==void 0&&(n.chat_title=e.chat.title),e.messageThreadId!==void 0&&(n.message_thread_id=String(e.messageThreadId)),t.username!==void 0&&(n.username=t.username);let r=e.chat.type===`group`||e.chat.type===`supergroup`,i=r?`telegram:${e.chat.id}:${t.id}`:`telegram:${t.id}`;return{attributes:n,authenticator:`telegram-webhook`,issuer:r?`telegram:${e.chat.id}`:`telegram`,principalId:i,principalType:t.isBot?`service`:`user`}}async function defaultOnMessage(e,t){return shouldDispatchTelegramMessage(t,e.telegram.botUsername)?(await e.telegram.startTyping(),{auth:defaultTelegramAuth(t)}):null}
|
|
1
|
+
import{extractErrorId,formatErrorHint}from"#internal/logging.js";import{registerTelegramFreeformPrompt,renderTelegramInputRequest}from"#public/channels/telegram/hitl.js";function defaultTelegramAuth(e){let t=e.from;if(!t)return null;let n={chat_id:e.chat.id,chat_type:e.chat.type,message_id:e.messageId,user_id:t.id};e.chat.title!==void 0&&(n.chat_title=e.chat.title),e.messageThreadId!==void 0&&(n.message_thread_id=String(e.messageThreadId)),t.username!==void 0&&(n.username=t.username);let r=e.chat.type===`group`||e.chat.type===`supergroup`,i=r?`telegram:${e.chat.id}:${t.id}`:`telegram:${t.id}`;return{attributes:n,authenticator:`telegram-webhook`,issuer:r?`telegram:${e.chat.id}`:`telegram`,principalId:i,principalType:t.isBot?`service`:`user`}}async function defaultOnMessage(e,t){return shouldDispatchTelegramMessage(t,e.telegram.botUsername)?(await e.telegram.startTyping(),{auth:defaultTelegramAuth(t)}):null}const defaultEvents={async"turn.started"(e,t){await t.telegram.startTyping()},async"actions.requested"(e,t){await t.telegram.startTyping()},async"input.requested"(e,t){for(let i of e.requests){let e=renderTelegramInputRequest(i,t.state),a=await t.telegram.post({reply_markup:e.replyMarkup,text:e.text});e.freeformRequestId!==void 0&&a.id&®isterTelegramFreeformPrompt(t.state,{messageId:a.id,requestId:e.freeformRequestId})}},async"message.completed"(e,t){e.finishReason===`tool-calls`||!e.message||await t.telegram.post(e.message)},async"turn.failed"(n,r){let i=formatErrorHint(n),a=extractErrorId(n.details);await r.telegram.post([`I hit an error while handling your request${i}.`,``,`Please try again, rephrase, or reach out if it keeps failing.`,...a?[``,`Error id: ${a}`]:[]].join(`
|
|
2
2
|
`))},async"session.failed"(n,r){let i=formatErrorHint(n),a=extractErrorId(n.details);await r.telegram.post([`This session could not recover from an error${i}.`,``,`Start a new message to continue.`,...a?[``,`Error id: ${a}`]:[]].join(`
|
|
3
3
|
`))}};function shouldDispatchTelegramMessage(e,t){if(e.from?.isBot===!0||e.chat.type===`channel`)return!1;let n=e.text||e.caption;return n.trim().length>0||e.attachments.length>0?!!(e.chat.type===`private`||e.replyToMessage?.from?.isBot===!0||isBotCommand(n,t)||t!==void 0&&mentionsBot(n,t)):!1}function isBotCommand(e,t){let n=/^\/(?<command>[A-Za-z0-9_]+)(?:@(?<target>[A-Za-z0-9_]+))?(?:\s|$)/u.exec(e);if(!n)return!1;let r=n.groups?.target;return r===void 0?!0:t!==void 0&&r.toLowerCase()===t.toLowerCase()}function mentionsBot(e,t){return e.toLowerCase().includes(`@${t.toLowerCase()}`)}export{defaultEvents,defaultOnMessage,defaultTelegramAuth};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
const TELEGRAM_HITL_CALLBACK_PREFIX=`ash:`,TELEGRAM_CALLBACK_RESPONSE_PREFIX=`telegram_callback:`,TELEGRAM_REPLY_RESPONSE_PREFIX=`telegram_reply:`,TELEGRAM_PROMPT_MAX_LENGTH=4e3;function renderTelegramInputRequest(e,t){let n=e.options;return n&&n.length>0?{replyMarkup:{inline_keyboard:chunk(n.map(n=>({callback_data:registerTelegramCallback(t,{optionId:n.id,requestId:e.requestId}),text:truncate(n.label,64)})),2)},text:truncate(e.prompt,TELEGRAM_PROMPT_MAX_LENGTH)}:{freeformRequestId:e.requestId,replyMarkup:{force_reply:!0,input_field_placeholder:truncate(`Type your answer`,64),selective:!0},text:truncate(e.prompt,TELEGRAM_PROMPT_MAX_LENGTH)}}function registerTelegramFreeformPrompt(e,t){e.pendingFreeformReplies={...e.pendingFreeformReplies,[t.messageId]:t.requestId}}function telegramCallbackInputResponse(e){return{optionId:`selected`,requestId:`${TELEGRAM_CALLBACK_RESPONSE_PREFIX}${e}`}}function telegramReplyInputResponse(e){return{requestId:`${TELEGRAM_REPLY_RESPONSE_PREFIX}${e.messageId}`,text:e.text}}function isTelegramSyntheticResponse(e){return e.requestId.startsWith(`telegram_callback:`)||e.requestId.startsWith(`telegram_reply:`)}function resolveTelegramInputResponses(e,t){let n=[];for(let r of t){if(r.requestId.startsWith(`telegram_callback:`)){let t=r.requestId.slice(18),i=e.hitlCallbacks?.[t];i!==void 0&&(n.push(i),delete e.hitlCallbacks?.[t]);continue}if(r.requestId.startsWith(`telegram_reply:`)){let t=r.requestId.slice(15),i=e.pendingFreeformReplies?.[t];i!==void 0&&r.text!==void 0&&(n.push({requestId:i,text:r.text}),delete e.pendingFreeformReplies?.[t]);continue}n.push(r)}return n}function registerTelegramCallback(t,n){let r=t.nextHitlCallbackId??0;t.nextHitlCallbackId=r+1;let i=`${TELEGRAM_HITL_CALLBACK_PREFIX}${r.toString(36)}`;return t.hitlCallbacks={...t.hitlCallbacks,[i]:n},i}function truncate(e,t){if(e.length<=t)return e;let n=Math.max(0,t-3);return`${e.slice(0,n).trimEnd()}...`}function chunk(e,t){let n=[];for(let r=0;r<e.length;r+=t)n.push(e.slice(r,r+t));return n}export{TELEGRAM_CALLBACK_RESPONSE_PREFIX,TELEGRAM_HITL_CALLBACK_PREFIX,TELEGRAM_REPLY_RESPONSE_PREFIX,isTelegramSyntheticResponse,registerTelegramFreeformPrompt,renderTelegramInputRequest,resolveTelegramInputResponses,telegramCallbackInputResponse,telegramReplyInputResponse};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{isNonEmptyString,isObject}from"#shared/guards.js";
|
|
1
|
+
import{isNonEmptyString,isObject}from"#shared/guards.js";function parseTelegramUpdate(e){if(!isObject(e))return null;let n=parseTelegramMessage(e.message);if(n!==null)return{kind:`message`,message:n};let r=parseTelegramCallbackQuery(e.callback_query);return r===null?null:{callbackQuery:r,kind:`callback_query`}}function formatTelegramContextBlock(e){return[`<telegram_context>`,`response_medium: telegram`,`response_instructions: Reply for Telegram in concise plain text. Avoid tables, long code fences, and formatting that depends on Markdown rendering.`,`chat_id: ${e.chatId}`,`chat_type: ${e.chatType}`,...e.chatTitle?[`chat_title: ${e.chatTitle}`]:[],`message_id: ${e.messageId}`,...e.messageThreadId===void 0?[]:[`message_thread_id: ${e.messageThreadId}`],...e.userId?[`user_id: ${e.userId}`]:[],...e.username?[`username: ${e.username}`]:[],...e.botUsername?[`bot_username: ${e.botUsername}`]:[],`</telegram_context>`].join(`
|
|
2
2
|
`)}function prependTelegramContext(e,t){let n=formatTelegramContextBlock(t);return typeof e==`string`?e.length>0?`${n}\n\n${e}`:n:[{type:`text`,text:n},...e]}function parseTelegramMessage(e){if(!isObject(e))return null;let n=parseTelegramChat(e.chat),r=numberLikeToString(e.message_id);return!n||!r?null:{attachments:parseAttachments(e),caption:typeof e.caption==`string`?e.caption:``,chat:n,from:parseTelegramUser(e.from),messageId:r,messageThreadId:typeof e.message_thread_id==`number`?e.message_thread_id:void 0,raw:e,replyToMessage:parseMessageReference(e.reply_to_message),text:typeof e.text==`string`?e.text:``}}function parseTelegramCallbackQuery(n){if(!isObject(n)||!isNonEmptyString(n.id))return null;let r=parseTelegramUser(n.from);return r?{data:typeof n.data==`string`?n.data:void 0,from:r,id:n.id,message:parseMessageReference(n.message),raw:n}:null}function parseMessageReference(e){if(!isObject(e))return;let n=parseTelegramChat(e.chat),r=numberLikeToString(e.message_id);if(!(!n||!r))return{chat:n,from:parseTelegramUser(e.from),messageId:r,messageThreadId:typeof e.message_thread_id==`number`?e.message_thread_id:void 0}}function parseTelegramChat(e){if(!isObject(e))return null;let n=numberLikeToString(e.id),r=parseChatType(e.type);return!n||!r?null:{id:n,title:typeof e.title==`string`?e.title:void 0,type:r,username:typeof e.username==`string`?e.username:void 0}}function parseTelegramUser(e){if(!isObject(e))return;let n=numberLikeToString(e.id);if(n)return{firstName:typeof e.first_name==`string`?e.first_name:void 0,id:n,isBot:e.is_bot===!0,languageCode:typeof e.language_code==`string`?e.language_code:void 0,lastName:typeof e.last_name==`string`?e.last_name:void 0,username:typeof e.username==`string`?e.username:void 0}}function parseAttachments(e){let t=[],n=parseLargestPhoto(e.photo);n!==null&&t.push(n);let r=parseDocument(e.document);return r!==null&&t.push(r),t}function parseLargestPhoto(e){if(!Array.isArray(e)||e.length===0)return null;let n=e.filter(isObject).map(e=>({fileId:typeof e.file_id==`string`?e.file_id:``,fileUniqueId:typeof e.file_unique_id==`string`?e.file_unique_id:void 0,height:typeof e.height==`number`?e.height:void 0,size:typeof e.file_size==`number`?e.file_size:void 0,width:typeof e.width==`number`?e.width:void 0})).filter(e=>e.fileId.length>0).sort((e,t)=>scorePhoto(t)-scorePhoto(e))[0];return n?{fileId:n.fileId,fileName:`photo.jpg`,fileUniqueId:n.fileUniqueId,height:n.height,kind:`photo`,mediaType:`image/jpeg`,size:n.size,width:n.width}:null}function parseDocument(e){return!isObject(e)||typeof e.file_id!=`string`?null:{fileId:e.file_id,fileName:typeof e.file_name==`string`?e.file_name:void 0,fileUniqueId:typeof e.file_unique_id==`string`?e.file_unique_id:void 0,kind:`document`,mediaType:typeof e.mime_type==`string`?e.mime_type:void 0,size:typeof e.file_size==`number`?e.file_size:void 0}}function scorePhoto(e){return e.size===void 0?(e.width??0)*(e.height??0):e.size}function parseChatType(e){return e===`channel`||e===`group`||e===`private`||e===`supergroup`?e:null}function numberLikeToString(e){if(typeof e==`string`&&e.length>0)return e;if(typeof e==`number`&&Number.isFinite(e))return String(e)}export{formatTelegramContextBlock,parseTelegramUpdate,prependTelegramContext};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createLogger}from"#internal/logging.js";import{isCompiledChannel}from"#channel/compiled-channel.js";import{parseJsonObject}from"#shared/json.js";import{defaultDeliverResult}from"#channel/adapter.js";import{mergeUploadPolicy}from"#public/channels/upload-policy.js";import{POST,defineChannel}from"#public/definitions/defineChannel.js";import{answerTelegramCallbackQuery,callTelegramApi,editTelegramMessageReplyMarkup,sendTelegramChatAction,sendTelegramMessage,splitTelegramMessageText,telegramContinuationToken}from"#public/channels/telegram/api.js";import{TELEGRAM_HITL_CALLBACK_PREFIX,isTelegramSyntheticResponse,resolveTelegramInputResponses,telegramCallbackInputResponse,telegramReplyInputResponse}from"#public/channels/telegram/hitl.js";import{parseTelegramUpdate,prependTelegramContext}from"#public/channels/telegram/inbound.js";import{buildTelegramTurnMessage,collectTelegramFileParts,createTelegramFetchFile}from"#public/channels/telegram/attachments.js";import{defaultEvents,defaultOnMessage}from"#public/channels/telegram/defaults.js";import{verifyTelegramRequest}from"#public/channels/telegram/verify.js";
|
|
1
|
+
import{createLogger}from"#internal/logging.js";import{isCompiledChannel}from"#channel/compiled-channel.js";import{parseJsonObject}from"#shared/json.js";import{defaultDeliverResult}from"#channel/adapter.js";import{mergeUploadPolicy}from"#public/channels/upload-policy.js";import{POST,defineChannel}from"#public/definitions/defineChannel.js";import{answerTelegramCallbackQuery,callTelegramApi,editTelegramMessageReplyMarkup,sendTelegramChatAction,sendTelegramMessage,splitTelegramMessageText,telegramContinuationToken}from"#public/channels/telegram/api.js";import{TELEGRAM_HITL_CALLBACK_PREFIX,isTelegramSyntheticResponse,resolveTelegramInputResponses,telegramCallbackInputResponse,telegramReplyInputResponse}from"#public/channels/telegram/hitl.js";import{parseTelegramUpdate,prependTelegramContext}from"#public/channels/telegram/inbound.js";import{buildTelegramTurnMessage,collectTelegramFileParts,createTelegramFetchFile}from"#public/channels/telegram/attachments.js";import{defaultEvents,defaultOnMessage}from"#public/channels/telegram/defaults.js";import{verifyTelegramRequest}from"#public/channels/telegram/verify.js";const log=createLogger(`telegram.channel`);function telegramChannel(e={}){let t=mergeUploadPolicy(e.uploadPolicy),r=e.onMessage??defaultOnMessage,s={...defaultEvents,...e.events},c=defineChannel({kindHint:`telegram`,state:initialTelegramState(e.botUsername),fetchFile:createTelegramFetchFile({api:e.api,credentials:e.credentials,policy:t}),context(t,n){return rebuildTelegramContext(t,n,e)},routes:[POST(e.route??`/ash/v1/telegram`,async(i,{send:a,waitUntil:o})=>{let s=await verifyInbound(i,e.credentials);if(s===null)return new Response(`unauthorized`,{status:401});let c;try{c=parseJsonObject(JSON.parse(s))}catch(e){return log.warn(`inbound Telegram body is not valid JSON`,{error:e}),new Response(`ok`)}let l=parseTelegramUpdate(c);return l===null?new Response(`ok`):l.kind===`message`?(o(dispatchMessage({config:e,message:l.message,onMessage:r,send:a,uploadPolicy:t})),new Response(`ok`)):(o(dispatchCallbackQuery({config:e,query:l.callbackQuery,send:a})),new Response(`ok`))})],async receive(t,{send:n}){let r=t.args,i=readChatId(r.chatId);if(i===void 0)throw Error(`telegramChannel().receive requires args.chatId.`);let a=typeof r.messageThreadId==`number`?r.messageThreadId:void 0,o=readOptionalString(r.conversationId),s=r.initialMessage;if(s!==void 0&&o!==void 0)throw Error("telegramChannel().receive: `conversationId` and `initialMessage` are mutually exclusive.");let c=o;return s!==void 0&&(c=(await buildTelegramHandle({config:e,state:{...initialTelegramState(e.botUsername),chatId:i,messageThreadId:a??null}}).sendMessage(s)).id||void 0),n(t.message,{auth:t.auth,continuationToken:telegramContinuationToken({chatId:i,conversationId:c,messageThreadId:a}),state:{...initialTelegramState(e.botUsername),chatId:i,conversationId:c??null,messageThreadId:a??null}})},events:s});return attachTelegramDeliver(c),c}function rebuildTelegramContext(e,t,n){return{session:t,state:e,telegram:buildTelegramHandle({config:n,session:t,state:e})}}function buildTelegramHandle(e){let t=e.config.api,n=e.state,r=e.config.credentials;function anchor(t){!t.id||n.chatType===`private`||(n.conversationId=t.id,n.chatId&&e.session?.setContinuationToken(telegramContinuationToken({chatId:n.chatId,conversationId:t.id,messageThreadId:n.messageThreadId??void 0})))}async function sendOne(e){let i=n.chatId??``;if(!i)throw Error(`telegramChannel: missing chat id for outbound message.`);let a=await sendTelegramMessage({apiBaseUrl:t?.apiBaseUrl,body:{...e,message_thread_id:e.message_thread_id??n.messageThreadId??void 0},credentials:r,fetch:t?.fetch,fileBaseUrl:t?.fileBaseUrl,chatId:i});return anchor(a),a}return{botUsername:n.botUsername??e.config.botUsername,chatId:n.chatId??``,chatType:n.chatType??void 0,conversationId:n.conversationId??void 0,messageThreadId:n.messageThreadId??void 0,answerCallbackQuery(e){return answerTelegramCallbackQuery({apiBaseUrl:t?.apiBaseUrl,callbackQueryId:e.callbackQueryId,credentials:r,fetch:t?.fetch,showAlert:e.showAlert,text:e.text})},editMessageReplyMarkup(e){let i=n.chatId??``;if(!i)throw Error(`telegramChannel: missing chat id for reply-markup edit.`);return editTelegramMessageReplyMarkup({apiBaseUrl:t?.apiBaseUrl,chatId:i,credentials:r,fetch:t?.fetch,messageId:e.messageId,replyMarkup:e.replyMarkup})},post(e){return postTelegramMessage(e,sendOne)},request(e,n){return callTelegramApi({apiBaseUrl:t?.apiBaseUrl,body:n,botToken:r?.botToken,fetch:t?.fetch,method:e})},sendMessage(e){return postTelegramMessage(e,sendOne)},async startTyping(e=`typing`){let i=n.chatId??``;if(i)try{await sendTelegramChatAction({action:e,apiBaseUrl:t?.apiBaseUrl,chatId:i,credentials:r,fetch:t?.fetch,messageThreadId:n.messageThreadId??void 0})}catch(e){log.debug(`Telegram typing indicator failed — swallowed`,{error:e})}}}}async function postTelegramMessage(e,t){let n=typeof e==`string`?{text:e}:e,r=splitTelegramMessageText(n.text),i;for(let[e,a]of r.entries()){let r=await t(e===0?{...n,text:a}:{text:a});i===void 0&&(i=r)}return i??{id:``,raw:null}}async function verifyInbound(e,t){try{return await verifyTelegramRequest(e,{secretToken:t?.webhookVerifier?void 0:t?.webhookSecretToken,webhookVerifier:t?.webhookVerifier})}catch(e){return log.warn(`telegram inbound verification failed`,{error:e}),null}}async function dispatchMessage(e){if(e.message.from?.isBot===!0)return;let t=stateFromMessage(e.message,e.config),n={telegram:buildTelegramHandle({config:e.config,state:t})},r;try{r=await e.onMessage(n,e.message)}catch(e){log.error(`message handler failed`,{error:e});return}if(r==null)return;let i=collectTelegramFileParts(e.message.attachments,e.uploadPolicy),a=prependTelegramContext(buildTelegramTurnMessage(e.message,i),{botUsername:e.config.botUsername,chatId:e.message.chat.id,chatTitle:e.message.chat.title,chatType:e.message.chat.type,messageId:e.message.messageId,messageThreadId:e.message.messageThreadId,userId:e.message.from?.id,username:e.message.from?.username}),o=e.message.text||e.message.caption,s=e.message.replyToMessage?.from?.isBot===!0&&o.trim().length>0?[telegramReplyInputResponse({messageId:e.message.replyToMessage.messageId,text:o})]:void 0;try{await e.send({inputResponses:s,message:a,modelContext:r.modelContext},{auth:r.auth,continuationToken:continuationTokenFromState(t),state:t})}catch(e){log.error(`message delivery failed`,{error:e})}}async function dispatchCallbackQuery(e){let t=stateFromCallbackQuery(e.query,e.config),n={telegram:buildTelegramHandle({config:e.config,state:t})};if(e.query.data?.startsWith(TELEGRAM_HITL_CALLBACK_PREFIX)===!0){try{await n.telegram.answerCallbackQuery({callbackQueryId:e.query.id,text:`Answer received.`})}catch(e){log.warn(`Telegram callback-query acknowledgement failed`,{error:e})}if(!e.query.message||!t.chatId)return;try{await e.send({inputResponses:[telegramCallbackInputResponse(e.query.data)]},{auth:null,continuationToken:continuationTokenFromState(t),state:t})}catch(e){log.error(`callback query delivery failed`,{error:e})}return}if(e.config.onCallbackQuery!==void 0){try{await e.config.onCallbackQuery(n,e.query)}catch(e){log.error(`custom callback-query handler failed`,{error:e})}return}try{await n.telegram.answerCallbackQuery({callbackQueryId:e.query.id,text:`Unsupported action.`})}catch(e){log.warn(`Telegram unsupported callback-query acknowledgement failed`,{error:e})}}function attachTelegramDeliver(e){if(!isCompiledChannel(e))return;let n=e.adapter;n.deliver=(e,t)=>{let n=e.inputResponses??[];if(n.some(isTelegramSyntheticResponse)){let r=resolveTelegramInputResponses(t.state,n);return r.length>0?{inputResponses:r,modelContext:e.modelContext}:e.message===void 0?void 0:{message:e.message,modelContext:e.modelContext}}return defaultDeliverResult(e)}}function stateFromMessage(e,t){let n=e.chat.type===`private`;return{...initialTelegramState(t.botUsername),chatId:e.chat.id,chatType:e.chat.type,conversationId:n?null:conversationIdForMessage(e),messageThreadId:e.messageThreadId??null,triggeringUserId:e.from?.id??null}}function stateFromCallbackQuery(e,t){let n=e.message;if(!n)return{...initialTelegramState(t.botUsername),triggeringUserId:e.from.id};let r=n.chat.type===`private`;return{...initialTelegramState(t.botUsername),chatId:n.chat.id,chatType:n.chat.type,conversationId:r?null:n.messageId,messageThreadId:n.messageThreadId??null,triggeringUserId:e.from.id}}function conversationIdForMessage(e){return e.replyToMessage?.from?.isBot===!0?e.replyToMessage.messageId:e.messageId}function continuationTokenFromState(e){return telegramContinuationToken({chatId:e.chatId??``,conversationId:e.chatType===`private`?void 0:e.conversationId??void 0,messageThreadId:e.messageThreadId??void 0})}function initialTelegramState(e){return{botUsername:e??null,chatId:null,chatType:null,conversationId:null,hitlCallbacks:{},messageThreadId:null,nextHitlCallbackId:0,pendingFreeformReplies:{},triggeringUserId:null}}function readChatId(e){if(typeof e==`string`&&e.length>0)return e;if(typeof e==`number`&&Number.isFinite(e))return String(e)}function readOptionalString(e){if(typeof e==`string`&&e.length>0)return e;if(typeof e==`number`&&Number.isFinite(e))return String(e)}export{telegramChannel};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createLogger}from"#internal/logging.js";import{timingSafeEqual}from"node:crypto";
|
|
1
|
+
import{createLogger}from"#internal/logging.js";import{timingSafeEqual}from"node:crypto";const log=createLogger(`telegram.verify`);async function resolveTelegramWebhookSecretToken(e){let t=e??process.env.TELEGRAM_WEBHOOK_SECRET_TOKEN;if(!t)throw Error(`TELEGRAM_WEBHOOK_SECRET_TOKEN is required.`);return typeof t==`function`?await t():t}async function verifyTelegramRequest(e,t){let n=await e.text();if(t.webhookVerifier!==void 0){let r=await t.webhookVerifier(e,n);if(!r)throw Error(`telegramChannel: inbound webhook verifier rejected the request.`);return typeof r==`string`?r:n}let r=await resolveTelegramWebhookSecretToken(t.secretToken),i=e.headers.get(`x-telegram-bot-api-secret-token`)??``;if(!i)throw Error(`telegramChannel: inbound request missing Telegram secret-token header.`);if(!constantTimeCompare(r,i))throw Error(`telegramChannel: inbound request secret-token mismatch.`);return n}function constantTimeCompare(e,r){if(e.length!==r.length)return!1;try{return timingSafeEqual(Buffer.from(e),Buffer.from(r))}catch(e){return log.debug(`timingSafeEqual threw`,{error:e}),!1}}export{resolveTelegramWebhookSecretToken,verifyTelegramRequest};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{extractErrorId,formatErrorHint}from"#internal/logging.js";function defaultTwilioAuth(e){let t={channel:e.channel,from:e.from};return e.to!==void 0&&(t.to=e.to),{attributes:t,authenticator:`twilio-webhook`,issuer:`twilio`,principalId:`twilio:${e.from}`,principalType:`user`}}function defaultOnText(e,t){return{auth:defaultTwilioAuth({channel:`text`,from:t.from,to:t.to})}}function defaultOnVoice(e,t){return{}}function defaultOnVoiceTranscription(e,t){return{auth:defaultTwilioAuth({channel:`voice`,from:t.from,to:t.to})}}
|
|
1
|
+
import{extractErrorId,formatErrorHint}from"#internal/logging.js";function defaultTwilioAuth(e){let t={channel:e.channel,from:e.from};return e.to!==void 0&&(t.to=e.to),{attributes:t,authenticator:`twilio-webhook`,issuer:`twilio`,principalId:`twilio:${e.from}`,principalType:`user`}}function defaultOnText(e,t){return{auth:defaultTwilioAuth({channel:`text`,from:t.from,to:t.to})}}function defaultOnVoice(e,t){return{}}function defaultOnVoiceTranscription(e,t){return{auth:defaultTwilioAuth({channel:`voice`,from:t.from,to:t.to})}}const defaultEvents={async"message.completed"(e,t){e.finishReason===`tool-calls`||!e.message||await t.twilio.sendMessage(e.message)},async"turn.failed"(n,r){let i=formatErrorHint(n),a=extractErrorId(n.details);await r.twilio.sendMessage([`I hit an error while handling your request${i}.`,``,`Please try again, rephrase, or reach out if it keeps failing.`,...a?[``,`Error id: ${a}`]:[]].join(`
|
|
2
2
|
`))},async"session.failed"(n,r){let i=formatErrorHint(n),a=extractErrorId(n.details);await r.twilio.sendMessage([`This session could not recover from an error${i}.`,``,`Start a new message to continue.`,...a?[``,`Error id: ${a}`]:[]].join(`
|
|
3
3
|
`))}};export{defaultEvents,defaultOnText,defaultOnVoice,defaultOnVoiceTranscription,defaultTwilioAuth};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
function parseTwilioTextMessage(e){let t=requiredParam(e,`From`),n=requiredParam(e,`Body`);return!t||!n?null:{accountSid:optionalParam(e,`AccountSid`),body:n,from:t,messageSid:optionalParam(e,`MessageSid`)??optionalParam(e,`SmsMessageSid`),raw:e,to:optionalParam(e,`To`)}}function parseTwilioVoiceCall(e){let t=requiredParam(e,`From`)??requiredParam(e,`Caller`);return t?{accountSid:optionalParam(e,`AccountSid`),callSid:optionalParam(e,`CallSid`),from:t,raw:e,to:optionalParam(e,`To`)??optionalParam(e,`Called`)}:null}function parseTwilioVoiceTranscription(e){let t=requiredParam(e,`From`)??requiredParam(e,`Caller`);if(!t)return null;let n=parseTranscriptionData(optionalParam(e,`TranscriptionData`));if(optionalParam(e,`Final`)===`false`)return null;let r=optionalParam(e,`SpeechResult`)??optionalParam(e,`TranscriptionText`)??n?.transcript??``;return r.trim()?{callSid:optionalParam(e,`CallSid`),confidence:parseConfidence(optionalParam(e,`Confidence`)??n?.confidence),from:t,raw:e,text:r,to:optionalParam(e,`To`)??optionalParam(e,`Called`),transcriptionSid:optionalParam(e,`TranscriptionSid`)}:null}function formatTwilioContextBlock(e){return[`<twilio_context>`,`channel: ${e.channel}`,`response_medium: sms`,`response_instructions: Reply for SMS in plain text. Keep the response concise and avoid Markdown formatting, tables, headings, code fences, and long lists. Ask at most one short follow-up question when more information is needed.`,`from: ${e.from}`,...e.to?[`to: ${e.to}`]:[],...e.messageSid?[`message_sid: ${e.messageSid}`]:[],...e.callSid?[`call_sid: ${e.callSid}`]:[],`</twilio_context>`].join(`
|
|
2
2
|
`)}function prependTwilioContext(e,t){let n=formatTwilioContextBlock(t);return typeof e==`string`?e.length>0?`${n}\n\n${e}`:n:[{type:`text`,text:n},...e]}function requiredParam(e,t){let n=e.get(t);return n&&n.trim().length>0?n:null}function optionalParam(e,t){let n=e.get(t);return n===null||n.length===0?void 0:n}function parseTranscriptionData(e){if(!e)return null;try{let t=JSON.parse(e);return{confidence:typeof t.confidence==`number`||typeof t.confidence==`string`?String(t.confidence):void 0,transcript:typeof t.transcript==`string`?t.transcript:void 0}}catch{return null}}function parseConfidence(e){if(e===void 0)return;let t=Number(e);return Number.isFinite(t)?t:void 0}export{formatTwilioContextBlock,parseTwilioTextMessage,parseTwilioVoiceCall,parseTwilioVoiceTranscription,prependTwilioContext};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createLogger}from"#internal/logging.js";import{POST,defineChannel}from"#public/definitions/defineChannel.js";import{verifyTwilioRequest}from"#public/channels/twilio/verify.js";import{callTwilioApi,sendTwilioMessage,twilioContinuationToken,updateTwilioCall}from"#public/channels/twilio/api.js";import{emptyTwilioResponse,gatherSpeechTwilioResponse,sayTwilioResponse}from"#public/channels/twilio/twiml.js";import{defaultEvents,defaultOnText,defaultOnVoice,defaultOnVoiceTranscription}from"#public/channels/twilio/defaults.js";import{parseTwilioTextMessage,parseTwilioVoiceCall,parseTwilioVoiceTranscription,prependTwilioContext}from"#public/channels/twilio/inbound.js";
|
|
1
|
+
import{createLogger}from"#internal/logging.js";import{POST,defineChannel}from"#public/definitions/defineChannel.js";import{verifyTwilioRequest}from"#public/channels/twilio/verify.js";import{callTwilioApi,sendTwilioMessage,twilioContinuationToken,updateTwilioCall}from"#public/channels/twilio/api.js";import{emptyTwilioResponse,gatherSpeechTwilioResponse,sayTwilioResponse}from"#public/channels/twilio/twiml.js";import{defaultEvents,defaultOnText,defaultOnVoice,defaultOnVoiceTranscription}from"#public/channels/twilio/defaults.js";import{parseTwilioTextMessage,parseTwilioVoiceCall,parseTwilioVoiceTranscription,prependTwilioContext}from"#public/channels/twilio/inbound.js";const log=createLogger(`twilio.channel`);function twilioChannel(e){assertAllowFromConfigured(e);let r=buildRoutes(e.route??`/ash/v1/twilio`),i=e.onText??defaultOnText,a=e.onVoice??defaultOnVoice,s=e.onVoiceTranscription??defaultOnVoiceTranscription,l={...defaultEvents,...e.events};return defineChannel({kindHint:`twilio`,state:{from:null,to:null,lastCallSid:null,lastMessageSid:null},context(t,n){return rebuildTwilioContext(t,n,e)},routes:[POST(r.messages,async(t,{send:n,waitUntil:r})=>{let a=await verifyInbound(t,e);if(a===null)return new Response(`unauthorized`,{status:401});let o=parseTwilioTextMessage(a.params);return o?await isAllowed(o.from,e.allowFrom)?(r(dispatchText({config:e,message:o,onText:i,send:n})),emptyTwilioResponse()):new Response(`forbidden`,{status:403}):emptyTwilioResponse()}),POST(r.voice,async t=>{let n=await verifyInbound(t,e);if(n===null)return new Response(`unauthorized`,{status:401});let i=parseTwilioVoiceCall(n.params);if(!i)return sayTwilioResponse(`Missing caller information.`);if(!await isAllowed(i.from,e.allowFrom))return new Response(`forbidden`,{status:403});let o=await acceptVoiceCall({call:i,config:e,onVoice:a});if(o===null)return new Response(`forbidden`,{status:403});let s=o??{};return gatherSpeechTwilioResponse({actionUrl:await buildActionUrl(t,e,r.transcription),hints:s.hints??e.voice?.hints,language:s.language??e.voice?.language,profanityFilter:s.profanityFilter??e.voice?.profanityFilter,prompt:s.prompt??e.voice?.prompt??`Please say your message after the tone.`,speechModel:s.speechModel??e.voice?.speechModel,speechTimeout:s.speechTimeout??e.voice?.speechTimeout??`auto`,timeoutSeconds:s.timeoutSeconds??e.voice?.timeoutSeconds,voice:s.voice??e.voice?.voice})}),POST(r.transcription,async(t,{send:n,waitUntil:i})=>{let a=await verifyInbound(t,e);if(a===null)return new Response(`unauthorized`,{status:401});let o=parseTwilioVoiceTranscription(a.params);return o?await isAllowed(o.from,e.allowFrom)?(i(dispatchVoiceTranscription({config:e,onVoiceTranscription:s,send:n,transcription:o})),sayTwilioResponse(e.voice?.acknowledgement??`Thanks. I'll follow up by text.`)):new Response(`forbidden`,{status:403}):gatherSpeechTwilioResponse({actionUrl:await buildActionUrl(t,e,r.transcription),language:e.voice?.language,prompt:e.voice?.prompt??`Please say your message after the tone.`,speechTimeout:e.voice?.speechTimeout??`auto`,timeoutSeconds:e.voice?.timeoutSeconds})})],async receive(t,{send:n}){let r=readString(t.args.phoneNumber);if(!r)throw Error(`twilioChannel().receive requires args.phoneNumber.`);let i=readString(t.args.from)??e.messaging?.from??null;return n(t.message,{auth:t.auth,continuationToken:twilioContinuationToken(r,i??void 0),state:{from:r,lastCallSid:null,lastMessageSid:null,to:i}})},events:l})}function rebuildTwilioContext(e,t,n){return{session:t,state:e,twilio:buildTwilioHandle({callSid:e.lastCallSid??void 0,config:n,from:e.from??``,to:e.to??void 0})}}function buildTwilioHandle(e){let t=e.config.api,n=e.config.credentials,r=e.config.messaging?.from??e.to,o=e.config.messaging?.messagingServiceSid,c=e.config.messaging?.statusCallbackUrl;return{callSid:e.callSid,from:e.from,to:e.to,request(e,r){return callTwilioApi({apiBaseUrl:t?.apiBaseUrl,body:r,credentials:n,fetch:t?.fetch,path:e})},sendMessage(i,s){return sendTwilioMessage({apiBaseUrl:t?.apiBaseUrl,body:i,credentials:n,fetch:t?.fetch,from:s?.from??r,messagingServiceSid:s?.messagingServiceSid??o,statusCallbackUrl:s?.statusCallbackUrl??c,to:s?.to??e.from})},updateCall(e,r){return updateTwilioCall({apiBaseUrl:t?.apiBaseUrl,callSid:e,credentials:n,fetch:t?.fetch,twiml:r})}}}function buildRoutes(e){let t=e.endsWith(`/`)?e.slice(0,-1):e;return{messages:`${t}/messages`,transcription:`${t}/voice/transcription`,voice:`${t}/voice`}}function assertAllowFromConfigured(e){if(e?.allowFrom===void 0)throw Error(`twilioChannel requires allowFrom. Use allowFrom: "*" to allow all numbers.`)}async function verifyInbound(e,t){try{return await verifyTwilioRequest(e,{authToken:t.credentials?.authToken,webhookUrl:t.webhookUrl})}catch(e){return log.warn(`twilio inbound verification failed`,{error:e}),null}}async function dispatchText(e){let{message:t}=e,n={twilio:buildTwilioHandle({callSid:void 0,config:e.config,from:t.from,to:t.to})},r;try{r=await e.onText(n,t)}catch(e){log.error(`text handler failed`,{error:e});return}if(r==null)return;let i=prependTwilioContext(t.body,{channel:`text`,from:t.from,messageSid:t.messageSid,to:t.to});try{await e.send(i,{auth:r.auth,continuationToken:twilioContinuationToken(t.from,t.to),state:{from:t.from,lastCallSid:null,lastMessageSid:t.messageSid??null,to:t.to??null}})}catch(e){log.error(`text delivery failed`,{error:e})}}async function acceptVoiceCall(e){let{call:t}=e,n={twilio:buildTwilioHandle({callSid:t.callSid,config:e.config,from:t.from,to:t.to})};try{return await e.onVoice(n,t)}catch(e){return log.error(`voice handler failed`,{error:e}),null}}async function dispatchVoiceTranscription(e){let{transcription:t}=e,n={twilio:buildTwilioHandle({callSid:t.callSid,config:e.config,from:t.from,to:t.to})},r;try{r=await e.onVoiceTranscription(n,t)}catch(e){log.error(`voice transcription handler failed`,{error:e});return}if(r==null)return;let i=prependTwilioContext(t.text,{callSid:t.callSid,channel:`voice`,from:t.from,to:t.to});try{await e.send(i,{auth:r.auth,continuationToken:twilioContinuationToken(t.from,t.to),state:{from:t.from,lastCallSid:t.callSid??null,lastMessageSid:null,to:t.to??null}})}catch(e){log.error(`voice transcription delivery failed`,{error:e})}}async function isAllowed(e,t){let n=typeof t==`function`?await t():t;return n===`*`?!0:typeof n==`string`?n===e:n.includes(e)}async function buildActionUrl(e,t,n){let r=typeof t.publicBaseUrl==`function`?await t.publicBaseUrl(e):t.publicBaseUrl;if(r)return new URL(n,ensureTrailingSlash(r)).toString();let i=new URL(e.url);return i.pathname=n,i.search=``,i.toString()}function ensureTrailingSlash(e){return e.endsWith(`/`)?e:`${e}/`}function readString(e){return typeof e==`string`&&e.length>0?e:void 0}export{twilioChannel};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createLogger}from"#internal/logging.js";import{createHmac,timingSafeEqual}from"node:crypto";
|
|
1
|
+
import{createLogger}from"#internal/logging.js";import{createHmac,timingSafeEqual}from"node:crypto";const log=createLogger(`twilio.verify`);async function resolveTwilioAuthToken(e){let t=e??process.env.TWILIO_AUTH_TOKEN;if(!t)throw Error(`TWILIO_AUTH_TOKEN is required.`);return typeof t==`function`?await t():t}async function verifyTwilioRequest(e,t){let n=await e.text(),r=new URLSearchParams(n),i=await resolveTwilioAuthToken(t.authToken),a=e.headers.get(`x-twilio-signature`)??``;if(!a)throw Error(`twilioChannel: inbound request missing X-Twilio-Signature.`);if(!constantTimeCompare(signTwilioRequest({authToken:i,params:r,url:await resolveWebhookUrl(e,t.webhookUrl)}),a))throw Error(`twilioChannel: inbound request signature mismatch.`);return{body:n,params:r}}function signTwilioRequest(e){let n=buildTwilioSignatureBase(e.url,e.params);return createHmac(`sha1`,e.authToken).update(n).digest(`base64`)}function buildTwilioSignatureBase(e,t){let n=Array.from(t.entries()).sort(([e,t],[n,r])=>{let i=e<n?-1:+(e>n);return i===0?t<r?-1:+(t>r):i}),r=e;for(let[e,t]of n)r+=`${e}${t}`;return r}async function resolveWebhookUrl(e,t){return typeof t==`function`?t(e):t??e.url}function constantTimeCompare(e,t){if(e.length!==t.length)return!1;try{return timingSafeEqual(Buffer.from(e),Buffer.from(t))}catch(e){return log.debug(`timingSafeEqual threw`,{error:e}),!1}}export{buildTwilioSignatureBase,resolveTwilioAuthToken,signTwilioRequest,verifyTwilioRequest};
|